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
Jupyter notebooks for the code samples of the book "Deep Learning with Python"

Jupyter notebooks for the code samples of the book "Deep Learning with Python"

François Chollet 16.2k Dec 30, 2022
Library extending Jupyter notebooks to integrate with Apache TinkerPop and RDF SPARQL.

Graph Notebook: easily query and visualize graphs The graph notebook provides an easy way to interact with graph databases using Jupyter notebooks. Us

Amazon Web Services 501 Dec 28, 2022
Rethinking Semantic Segmentation from a Sequence-to-Sequence Perspective with Transformers

Segmentation Transformer Implementation of Segmentation Transformer in PyTorch, a new model to achieve SOTA in semantic segmentation while using trans

Abhay Gupta 161 Dec 8, 2022
Implementation of SETR model, Original paper: Rethinking Semantic Segmentation from a Sequence-to-Sequence Perspective with Transformers.

SETR - Pytorch Since the original paper (Rethinking Semantic Segmentation from a Sequence-to-Sequence Perspective with Transformers.) has no official

zhaohu xing 112 Dec 16, 2022
Understanding and Improving Encoder Layer Fusion in Sequence-to-Sequence Learning (ICLR 2021)

Understanding and Improving Encoder Layer Fusion in Sequence-to-Sequence Learning (ICLR 2021) Citation Please cite as: @inproceedings{liu2020understan

Sunbow Liu 22 Nov 25, 2022
[CVPR 2021] Rethinking Semantic Segmentation from a Sequence-to-Sequence Perspective with Transformers

[CVPR 2021] Rethinking Semantic Segmentation from a Sequence-to-Sequence Perspective with Transformers

Fudan Zhang Vision Group 897 Jan 5, 2023
Sequence to Sequence Models with PyTorch

Sequence to Sequence models with PyTorch This repository contains implementations of Sequence to Sequence (Seq2Seq) models in PyTorch At present it ha

Sandeep Subramanian 708 Dec 19, 2022
Sequence-to-Sequence learning using PyTorch

Seq2Seq in PyTorch This is a complete suite for training sequence-to-sequence models in PyTorch. It consists of several models and code to both train

Elad Hoffer 514 Nov 17, 2022
Pervasive Attention: 2D Convolutional Networks for Sequence-to-Sequence Prediction

This is a fork of Fairseq(-py) with implementations of the following models: Pervasive Attention - 2D Convolutional Neural Networks for Sequence-to-Se

Maha 490 Dec 15, 2022
An implementation of a sequence to sequence neural network using an encoder-decoder

Keras implementation of a sequence to sequence model for time series prediction using an encoder-decoder architecture. I created this post to share a

Luke Tonin 195 Dec 17, 2022
Sequence lineage information extracted from RKI sequence data repo

Pango lineage information for German SARS-CoV-2 sequences This repository contains a join of the metadata and pango lineage tables of all German SARS-

Cornelius Roemer 24 Oct 26, 2022
Official repository of OFA. Paper: Unifying Architectures, Tasks, and Modalities Through a Simple Sequence-to-Sequence Learning Framework

Paper | Blog OFA is a unified multimodal pretrained model that unifies modalities (i.e., cross-modality, vision, language) and tasks (e.g., image gene

OFA Sys 1.4k Jan 8, 2023
Deep learning library featuring a higher-level API for TensorFlow.

TFLearn: Deep learning library featuring a higher-level API for TensorFlow. TFlearn is a modular and transparent deep learning library built on top of

TFLearn 9.6k Jan 2, 2023
Deep learning library featuring a higher-level API for TensorFlow.

TFLearn: Deep learning library featuring a higher-level API for TensorFlow. TFlearn is a modular and transparent deep learning library built on top of

TFLearn 9.5k Feb 12, 2021
FID calculation with proper image resizing and quantization steps

clean-fid: Fixing Inconsistencies in FID Project | Paper The FID calculation involves many steps that can produce inconsistencies in the final metric.

Gaurav Parmar 606 Jan 6, 2023
Proximal Backpropagation - a neural network training algorithm that takes implicit instead of explicit gradient steps

Proximal Backpropagation Proximal Backpropagation (ProxProp) is a neural network training algorithm that takes implicit instead of explicit gradient s

Thomas Frerix 40 Dec 17, 2022
codes for "Scheduled Sampling Based on Decoding Steps for Neural Machine Translation" (long paper of EMNLP-2022)

Scheduled Sampling Based on Decoding Steps for Neural Machine Translation (EMNLP-2021 main conference) Contents Overview Background Quick to Use Furth

Adaxry 13 Jul 25, 2022
FAST Aiming at the problems of cumbersome steps and slow download speed of GNSS data

FAST Aiming at the problems of cumbersome steps and slow download speed of GNSS data, a relatively complete set of integrated multi-source data download terminal software fast is developed. The software contains most of the data sources required in the process of GNSS scientific research and learning. The way of parallel download greatly improves the efficiency of download.

ChangChuntao 23 Dec 31, 2022