前言

最近在github上看到一个Oklahoma State University,Suraj Pawar and Omer San等人写的
CFD入门教程CFD: 'Julia A Learning Module Structuriing an Introductory Course on Computational Fluid Dynamics'(https://github.com/surajp92/CFD_Julia), 并附有PDF教程(https://www.mdpi.com/2311-5521/4/3/159)。该教程质量比较高,在这里分享给大家。

教程主要内容

目录

| --- | --- |
| 01 | 1D heat equation: Forward time central space (FTCS) scheme |
| 02 | 1D heat equation: Third-order Runge-Kutta (RK3) scheme |
| 03 | 1D heat equation: Crank-Nicolson (CN) scheme |
| 04 | 1D heat equation: Implicit compact Pade (ICP) scheme |
| 05 | 1D inviscid Burgers equation: WENO-5 with Dirichlet and periodic boundary condition |
| 06 | 1D inviscid Burgers equation: CRWENO-5 with Dirichlet and periodic boundary conditions |
| 07 | 1D inviscid Burgers equation: Flux-splitting approach with WENO-5|
| 08 | 1D inviscid Burgers equation: Riemann solver approach with WENO-5 using Rusanov solver |
| 09 | 1D Euler equations: Roe solver, WENO-5, RK3 for time integration |
| 10 | 1D Euler equations: HLLC solver, WENO-5, RK3 for time integration |
| 11 | 1D Euler equations: Rusanov solver, WENO-5, RK3 for time integration |
| 12 | 2D Poisson equation: Finite difference fast Fourier transform (FFT) based direct solver |
| 13 | 2D Poisson equation: Spectral fast Fourier transform (FFT) based direct solver |
| 14 | 2D Poisson equation: Fast sine transform (FST) based direct solver for Dirichlet boundary |
| 15 | 2D Poisson equation: Gauss-Seidel iterative method |
| 16 | 2D Poisson equation: Conjugate gradient iterative method |
| 17 | 2D Poisson equation: V-cycle multigrid iterative method  |
| 18 | 2D incompressible Navier-Stokes equations (cavity flow): Arakawa, FST, RK3 schemes |
| 19 | 2D incompressible Navier-Stokes equations (vortex merging): Arakawa, FFT, RK3 schemes |
| 20 | 2D incompressible Navier-Stokes equations (vortex merging): Hybrid RK3/CN approach |
| 21 | 2D incompressible Navier-Stokes equations (vortex merging): Pseudospectral solver, 3/2 dealiasing, Hybrid RK3/CN approach |
| 22 | 2D incompressible Navier-Stokes equations (vortex merging): Pseudospectral solver, 2/3 dealiasing, Hybrid RK3/CN approach |

说明

上述教程虽说是面向高年级本科生以及研究生的CFD入门教程,但也只给出了求解算法及其Julia实现,缺少一定的推导过程,数值计算基础较差的人比较难以理解。因此我收集了一些参考资料,以便读者能更容易地理解教程内容。

另外,github上的代码几乎是用Julia完成的,我也用Python(少部分使用了Matlab)重写了一遍。Python代码及参考资料都可在https://download.csdn.net/download/liuqihang11/85195758下载,不过需要付费9.9元。无法使用github,对Julia代码不熟悉以及需要一些数值计算理论辅助的可考虑下载我整理的文档,否则直接点击开头的两个链接下载PDF以及Julia代码即可。

另外需要注意,Suraj Pawar等人给的PDF教程有些地方有错,这是我按照PDF所给算法编写Python代码时发现的(事实上他们给的Julia代码没有错误,PDF文档中的应该是编辑错误)。下面我直接给大家指出来:

(1) Page 15/77, 3rd term of Equation(40) ,
beta2=13/12(ui − 2ui+1 + ui+2)2 + 14(3ui − 4ui+1 + ui+2)2
instead of 
13/12(ui − 2ui+1 + ui+2)2 + 14(3ui − 4ui+1 + 3ui+2)2

(2) Page 25/77,Equation(59),
fi+1/2 = 1/2  fLi+1/2 + fRi+1/2 − (ci+1/2)/2 (uRi+1/2 − uLi+1/2)
instead of 
fi+1/2 = 1/2  fLi+1/2 + fRi+1/2 − (ci+1/2)/2 (uLi+1/2 − uRi+1/2)

(3) Page 32/77,Equation(79),
(SL − uL)-rhoR*uR instead of (SL − uL)*rhoR*uR

(4) Page 32/77,Equation(81),
SL*uL*FL instead of SL*uL-FL
SR*uR*FR instead of SR*uR-FR

(5) Page 32/77,Equation(105),
(2/delta_x**2+2/delta_y**2)**(-1) instead of 2/delta_x**2+2/delta_y**2

(6) Page 51/77,Equation(120),
e=(...)/4 instead of e=(...)/2

上述内容看起来或许有点晦涩,不过比照PDF就很清楚了。

文档说明

最后的最后介绍一下https://download.csdn.net/download/liuqihang11/85195758里面的内容吧。

(1)CFD_Julia-master

这个文件是在https://github.com/surajp92/CFD_Julia'上直接下载的,里面是CFD的julia代码,这并非本人创作内容,放在这里只是为了给大家提供方便。

(2)CFD Julia A Learning Module Structuriing an Introductory Course on Computational Fluid Dynamics

这个文件是在Fluids | Free Full-Text | CFD Julia: A Learning Module Structuring an Introductory Course on Computational Fluid Dynamics上下载的,它是CFD教程的核心内容,介绍了一些基本的CFD算法,(1)中的CFD_Julia-master文件不过是此PDF的一个Julia实现,同样,这也并非本人创作内容,放在这里只是为了给大家提供方便;

(3)CFD study

这个文件是我根据上述PDF教程自己编写的Python代码,与Suraj Pawar等人给的Julia代码功能基本一致。写python时,我虽然尽可能使用了数组运算来提高速度,但计算效率仍旧会比Julia低一些,没办法,Python老毛病了。这里也建议大家用自己擅长的语言重新实现PDF中的算法,以便加深自己对CFD计算过程的理解。

这里给出了一个对顶盖方腔驱动流(lid driven cavity)进行CFD模拟的Python代码作为示例:

#!/usr/bin/env python3
# -*- coding: utf-8 -*-import time
import copy
import numpy as np
from matplotlib import cm
from matplotlib import pyplot as pltdef discrete_computing(x_range, y_range, nx, ny):x = np.linspace(0, x_range, nx + 1)y = np.linspace(0, y_range, ny + 1)dx = x[1] - x[0]dy = y[1] - y[0]return dx, dydef Conjugate_Gradient_Algorithm(dx, dy, nx, ny, f):phi = np.zeros((nx + 1, ny + 1))r = np.zeros_like(phi)q = np.zeros_like(phi)phi_p1 = copy.deepcopy(phi)epsilon = 10**-5min_parameter = 10**-16Alpha_computing = lambda a1, a2, a3, a4, a6: (a1 - 2 * a2 + a3) / dx**2 + (a4 - 2 * a2 + a6) / dy**2r[1:-1, 1:-1] = f[1:-1, 1:-1] - Alpha_computing(phi[2:, 1:-1], phi[1:-1, 1:-1], phi[:-2, 1:-1], phi[1:-1, 2:],phi[1:-1, :-2])p = copy.deepcopy(r)while 1:q[1:-1, 1:-1] = Alpha_computing(p[2:, 1:-1], p[1:-1, 1:-1],p[:-2, 1:-1], p[1:-1,2:], p[1:-1, :-2])alpha_temp1 = (r[1:-1, 1:-1]**2).sum()alpha_temp2 = (q[1:-1, 1:-1] * p[1:-1, 1:-1]).sum()alpha = alpha_temp1 / (alpha_temp2 + min_parameter)phi_p1[1:-1, 1:-1] = phi[1:-1, 1:-1] + alpha * p[1:-1, 1:-1]r[1:-1, 1:-1] -= alpha * q[1:-1, 1:-1]beta_temp1 = (r[1:-1, 1:-1]**2).sum()beta_temp2 = alpha_temp1beta = beta_temp1 / (beta_temp2 + min_parameter)p[1:-1, 1:-1] = r[1:-1, 1:-1] + beta * p[1:-1, 1:-1]if (abs(phi_p1 - phi) > epsilon).sum() == 0:breakelse:phi = copy.deepcopy(phi_p1)return phi_p1[1:-1, 1:-1]def rhs_computing(dx, dy, re_number, omega, phi):rhs_value = np.ones_like(omega)jacobi1 = ((omega[2:, 1:-1] - omega[:-2, 1:-1]) *(phi[1:-1, 2:] - phi[1:-1, :-2]) -(omega[1:-1, 2:] - omega[1:-1, :-2]) *(phi[2:, 1:-1] - phi[:-2, 1:-1])) / (4 * dx * dy)jacobi2 = (omega[2:, 1:-1] *(phi[2:, 2:] - phi[2:, :-2]) - omega[:-2, 1:-1] *(phi[:-2, 2:] - phi[:-2, :-2]) - omega[1:-1, 2:] *(phi[2:, 2:] - phi[:-2, 2:]) + omega[1:-1, :-2] *(phi[2:, :-2] - phi[:-2, :-2])) / (4 * dx * dy)jacobi3 = (omega[2:, 2:] *(phi[1:-1, 2:] - phi[2:, 1:-1]) - omega[:-2, :-2] *(phi[:-2, 1:-1] - phi[1:-1, :-2]) - omega[:-2, 2:] *(phi[1:-1, 2:] - phi[:-2, 1:-1]) + omega[2:, :-2] *(phi[2:, 1:-1] - phi[1:-1, :-2])) / (4 * dx * dy)jacobi = (jacobi1 + jacobi2 + jacobi3) / 3rhs_value[1:-1, 1:-1] = -jacobi + (omega[2:, 1:-1] - 2.0 * omega[1:-1, 1:-1] + omega[:-2, 1:-1]) / (re_number * dx * dx) + (omega[1:-1, 2:] - 2.0 * omega[1:-1, 1:-1] +omega[1:-1, :-2]) / (re_number * dy * dy)return rhs_valuedef boundary_condition_updating(dx, dy, omega, phi):omega[0] = (-4 * phi[1] + 0.5 * phi[2]) / dx**2omega[-1] = (-4 * phi[-2] + 0.5 * phi[-3]) / dx**2omega[:, 0] = (-4 * phi[:, 1] + 0.5 * phi[:, 2]) / dy**2omega[:, -1] = (-4 * phi[:, -2] + 0.5 * phi[:, -3]) / dy**2 - 3 / dyreturn omegadef RK3(nx, ny, dx, dy, dt, re_number, omega, phi):omega1 = np.zeros_like(omega)rhs_value = rhs_computing(dx, dy, re_number, omega, phi)omega1[1:-1, 1:-1] = omega[1:-1, 1:-1] + dt * rhs_value[1:-1, 1:-1]omega1 = boundary_condition_updating(dx, dy, omega1, phi)phi[1:-1, 1:-1] = Conjugate_Gradient_Algorithm(dx, dy, nx, ny, -omega1)rhs_value = rhs_computing(dx, dy, re_number, omega1, phi)omega1[1:-1, 1:-1] = 0.75 * omega[1:-1, 1:-1] + 0.25 * omega1[1:-1, 1:-1] + 0.25 * dt * rhs_value[1:-1, 1:-1]omega1 = boundary_condition_updating(dx, dy, omega1, phi)phi[1:-1, 1:-1] = Conjugate_Gradient_Algorithm(dx, dy, nx, ny, -omega1)rhs_value = rhs_computing(dx, dy, re_number, omega1, phi)omega[1:-1, 1:-1] = (1.0 / 3.0) * omega[1:-1, 1:-1] + (2.0 / 3.0) * omega1[1:-1, 1:-1] + (2.0 / 3.0) * dt * rhs_value[1:-1, 1:-1]omega = boundary_condition_updating(dx, dy, omega, phi)phi[1:-1, 1:-1] = Conjugate_Gradient_Algorithm(dx, dy, nx, ny, -omega)return omega, phidef lid_driven_cavity_problem_solver(nx, ny, nt, dx, dy, dt, re_number):omega = np.zeros((nx + 1, ny + 1))phi = np.zeros_like(omega)for _ in range(nt):omega, phi = RK3(nx, ny, dx, dy, dt, re_number, omega, phi)return omega, phidef drow_contour(data1, data2):plt.rc('font', family='Times New Roman')fig = plt.figure("lid_driven_cavity_problem",figsize=(14, 6),constrained_layout=True)level1 = np.arange(-195, 65 + 5, 5)level2 = np.arange(-0.104, 0.002 + 0.002, 0.002)ax1 = plt.subplot(1, 2, 1)cset1 = ax1.contourf(data1.T, level1, cmap=cm.jet, vmin=-180, vmax=60)ax1.set_title("Vorticity field")ax1.set_xlabel("X")ax1.set_ylabel("Y")cbar1 = fig.colorbar(cset1, ax=ax1)cbar1.set_ticks([-180, -150, -120, -90, -60, -30, 0, 30, 60])ax2 = plt.subplot(1, 2, 2)cset2 = ax2.contourf(data2.T, level2, cmap=cm.jet)ax2.set_title("Streamfunction")ax2.set_xlabel("X")ax2.set_ylabel("Y")cbar2 = fig.colorbar(cset2, ax=ax2)cbar2.set_ticks([-0.096, -0.084, -0.072, -0.060, -0.048, -0.036, -0.024, -0.012, 0.000])# plt.savefig('lid_driven_cavity_problem.svg', dpi=500)end_time = time.time()plt.show()return end_timedef result_showing(x_range, y_range, t_range, nx, ny, dt, re_number):dx, dy = discrete_computing(x_range, y_range, nx, ny)nt = int(t_range / dt)omega, phi = lid_driven_cavity_problem_solver(nx, ny, nt, dx, dy, dt,re_number)end_time = drow_contour(omega, phi)return end_timeif __name__ == "__main__":start_time = time.time()end_time = result_showing(1.0, 1.0, 10, 32, 32, 0.01, 100.0)print('Time Consuming: {:.2f}s'.format(end_time - start_time))

计算结果如下:

Time Consuming: 17.91s

上述代码基本没有注释以及变量解释,不过结合PDF内容就很容易理解了,基本不需要额外的注释。

(4)Reference

这个里面是一些数值计算算法的详细介绍。因为PDF教程里面只给了求解算法,没有具体介绍算法推导原理,这里搜集了一些基本数值算法,以供数值计算基础薄弱的读者使用。主要包含以下内容:

1)FFT的详细推导

求解泊松方程时会用到该算法。其实这部分内容可在我发布的https://blog.csdn.net/liuqihang11/article/details/124026272上查看。

2)场论基础

这部分介绍了一些场论基础知识,比如梯度,散度、旋度以及Nabla算子的性质及基本运算等,化简二维不可压缩流体的NS方程时会涉及一些矢量运算。

3)多网格技术

求解泊松方程时会使用到多网格技术。

4)共轭梯度法

求解泊松方程时会用到共轭梯度法。

5)循环三对角矩阵求解

求解周期性边界条件下的一维博格斯方程时会用到循环TDMA法。

6)CFD专业词汇

由于PDF是英文的,对英文不太熟悉的读者对照该文档能更容易理解PDF内容。

7)NumericalRecipesin

详细介绍了大量数值计算算法,包罗万象。

8)euler_1d

介绍了一维欧拉方程的推导过程。

计算流体力学CFD入门教程介绍相关推荐

  1. 计算流体力学(CFD)学习小记1 ANSYS Icepak入门

    前言 最近需要解决一个比较麻烦的问题:车载充电机(OBC)散热器的设计.散热器太小,MOSFET估计会炸:散热器太大,则无法满足功率密度指标的要求.与很多电力电子的工程师交流过,散热器设计估计仅次于E ...

  2. 通俗易懂的SpringBoot教程---day1---Springboot入门教程介绍

    通俗易懂的SpringBoot教程-day1-教程介绍 教程介绍: 初级教程: 一. Spring Boot入门 二. Spring Boot配置 三. Spring Boot与日志 四. Sprin ...

  3. C++ 偏微分数值计算库_一文带你了解计算流体力学CFD及其应用领域

    计算流体力学的发展 计算流体动力学(Computational Fluid Dynamics)简写为CFD,经过半个世纪的迅猛发展,这门学科已经是相当的成熟了,一个重要的标志就是近几十年来,各种CFD ...

  4. python计算存款_python入门教程NO.8 用python写个存款利息计算器

    本文涉及的python基础语法为def函数,return,函数的各参数示例,匿名函数等 函数初识 函数是一段组织好的 可重复使用的 用来实现特定功能的代码块. 函数能提高代码的模块性,和代码的重复利用 ...

  5. java eclipse 入门_Eclipse使用入门教程介绍

    1. 常用快捷键 这是使用工具的第一步,熟练使用快捷键对于我们编写程序会起到相当大帮助,所以这里笔者列出的快捷键建议大家必须都掌握. Ctrl + 鼠标左键(类.方法.属性的变量名词):定位跟踪某变量 ...

  6. 【计算流体力学CFD】Fluent软件模拟:方腔热对流圆柱绕流(卡门涡街)|Matlab

  7. 利用计算流体力学(CFD)方法求解流场

    计算流体力学(CFD)是一种利用数学模型和计算机技术来研究物理流动问题的方法.通过对流体运动的数学建模,并使用数值解法计算流场,从而获得流体的速度.压力.温度等物理量的分布.这种方法在航空.航天.石油 ...

  8. 资深程序员的Metal入门教程总结

    1.Metal Metal 是一个和 OpenGL ES 类似的面向底层的图形编程接口,可以直接操作GPU:支持iOS和OS X,提供图形渲染和通用计算能力.(不支持模拟器) 图片来源 https:/ ...

  9. Android 2D游戏引擎AndEngine快速入门教程

    Android 2D游戏引擎AndEngine快速入门教程 介绍:AndEngine是一款知名的Android 2D游戏引擎.该引擎代码开源,并且可以免费使用.本书详细讲解如何使用AndEngine引 ...

  10. WinDbg入门教程

    WinDbg 入门教程 介绍 在我的职业生涯中,我看到我们大多数都是使用Visual Studio来进行调试,而不是用其它许多免费的调试器.你可能有许多理由来使用这样的调试器,比如,在你家里的机器上没 ...

最新文章

  1. SpringBoot中@ControlAdvice的使用
  2. python求向量函数的雅可比矩阵_在python Numpy中求向量和矩阵的范数实例
  3. java方法生命周期_Java线程的第二种实现方式以及生命周期
  4. python web为什么不火-python web为什么不火
  5. Linux开启路由转发功能(透明代理环境搭建)
  6. java round指令_Java PApplet.round方法代码示例
  7. java8 垃圾收集_面试官:怎么做JDK8的垃圾收集器的调优(面试常问)
  8. xpath解析库的语法及使用
  9. 辰星计划2022 | 旷视研究院春季实习生招募开始啦!
  10. Linux静默安装oracle
  11. [html] 一个标签上同时出现三个或多个class属性,请问它的渲染顺序是怎样的?
  12. 虚拟资源拳王公社:小白从0到1搭建个人私域流量池的实操方法,6招玩转流量裂变法
  13. 元胞自动机小团体matlab,元胞自动机matlab程序代码
  14. 【C++从入门到踹门】第十四篇:二叉搜索树
  15. 基于 BIP39 协议创建 Ethereum HD Wallet
  16. android 手势识别 (缩放 单指滑动 多指滑动)
  17. FFmpeg音频解码-音频可视化
  18. rocksdb 安装全过程 一些问题解决方法
  19. windows:QueryPerformanceCounter函数/PerformanceCounter函数
  20. 浙江大学PAT-1003. 我要通过!(20)

热门文章

  1. 【Pycharm】笔记内容010:记录Pycharm报错“Can not find 程序所在目录 或者Can not run program...“的问题解决
  2. OpenCms后台工作间汉化设置10.5
  3. 介质天线的设计原理_详解rifd标签天线的设计原理和测量技巧
  4. 认证协议RADIUS篇
  5. 计算机专业学不学画法几何,给新手们学CAD的建议
  6. 学完计算机绘图收获有哪些,概率论与数理统计热合买提江网课参考答案查询,画法几何及土木工程制图计算机绘图...
  7. matlab神经网络工具箱教程,matlab神经网络能做什么
  8. LD3320 语音识别模块 开发板集成STC单片机_笔记1
  9. 各类经纬度转换工具类
  10. 如何设置windows服务