{ "cells": [ { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "# 二维Taylor-Green涡流动\n", "\n", "[![下载Notebook](https://mindspore-website.obs.cn-north-4.myhuaweicloud.com/website-images/master/resource/_static/logo_notebook.svg)](https://mindspore-website.obs.cn-north-4.myhuaweicloud.com/notebook/master/mindflow/zh_cn/physics_driven/mindspore_taylor_green2D.ipynb) [![下载样例代码](https://mindspore-website.obs.cn-north-4.myhuaweicloud.com/website-images/master/resource/_static/logo_download_code.svg)](https://mindspore-website.obs.cn-north-4.myhuaweicloud.com/notebook/master/mindflow/zh_cn/physics_driven/mindspore_taylor_green2D.py) [![查看源文件](https://mindspore-website.obs.cn-north-4.myhuaweicloud.com/website-images/master/resource/_static/logo_source.svg)](https://gitee.com/mindspore/docs/blob/master/docs/mindflow/docs/source_zh_cn/physics_driven/taylor_green2D.ipynb)\n", "\n", "本案例要求**MindSpore版本 >= 2.0.0**调用如下接口: *mindspore.jit,mindspore.jit_class,mindspore.jacrev*。" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "## 概述\n", "\n", "在流体力学中,Taylor-Green涡流动是一种不稳定的衰减的涡流,在二维周期性边界条件时存在精确解,物理启发的神经网络方法(Physics-informed Neural Networks),以下简称PINNs,通过使用逼近控制方程的损失函数以及简单的网络构型,为快速求解复杂流体问题提供了新的方法。本案例将基于PINNs方法实现二维Taylor-Green涡流动的仿真。" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "## 二维不可压缩纳维-斯托克斯方程(Navier-Stokes equation)\n", "\n", "纳维-斯托克斯方程(Navier-Stokes equation),简称`N-S`方程,是流体力学领域的经典偏微分方程,在粘性不可压缩情况下,无量纲`N-S`方程的形式如下:\n", "\n", "$$\n", "\\frac{\\partial u}{\\partial x} + \\frac{\\partial v}{\\partial y} = 0\n", "$$\n", "\n", "$$\n", "\\frac{\\partial u} {\\partial t} + u \\frac{\\partial u}{\\partial x} + v \\frac{\\partial u}{\\partial y} = - \\frac{\\partial p}{\\partial x} + \\frac{1} {Re} (\\frac{\\partial^2u}{\\partial x^2} + \\frac{\\partial^2u}{\\partial y^2})\n", "$$\n", "\n", "$$\n", "\\frac{\\partial v} {\\partial t} + u \\frac{\\partial v}{\\partial x} + v \\frac{\\partial v}{\\partial y} = - \\frac{\\partial p}{\\partial y} + \\frac{1} {Re} (\\frac{\\partial^2v}{\\partial x^2} + \\frac{\\partial^2v}{\\partial y^2})\n", "$$\n", "\n", "其中,`Re`表示雷诺数。\n", "\n", "本案例利用PINNs方法学习位置和时间到相应流场物理量的映射,实现`N-S`方程的求解:\n", "\n", "$$\n", "(x, y, t) \\mapsto (u, v, p)\n", "$$" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "## 技术路径\n", "\n", "MindSpore Flow求解该问题的具体流程如下:\n", "\n", "1. 创建数据集。\n", "2. 构建模型。\n", "3. 优化器。\n", "4. NavierStokes2D。\n", "5. 模型训练。\n", "6. 模型推理及可视化。" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "## 导入所需要的包" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "import time\n", "import numpy as np\n", "import sympy\n", "import mindspore\n", "from mindspore import nn, ops, jit, set_seed\n", "from mindspore import numpy as mnp" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "下述`src`包可以在 [applications/physics_driven/navier_stokes/taylor_green/src](https://gitee.com/mindspore/mindscience/tree/master/MindFlow/applications/physics_driven/navier_stokes/taylor_green/src)下载。" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "from mindflow.cell import MultiScaleFCCell\n", "from mindflow.utils import load_yaml_config\n", "from mindflow.pde import NavierStokes, sympy_to_mindspore\n", "\n", "from src import create_training_dataset, create_test_dataset, calculate_l2_error, NavierStokes2D\n", "\n", "set_seed(123456)\n", "np.random.seed(123456)" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "下述`taylor_green_2D.yaml`配置文件可以在[applications/physics_driven/navier_stokes/taylor_green/configs/taylor_green_2D.yaml](https://gitee.com/mindspore/mindscience/blob/master/MindFlow/applications/physics_driven/navier_stokes/taylor_green/configs/taylor_green_2D.yaml)下载。" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "mindspore.set_context(mode=mindspore.GRAPH_MODE, device_target=\"GPU\", device_id=0, save_graphs=False)\n", "use_ascend = mindspore.get_context(attr_key='device_target') == \"Ascend\"\n", "\n", "config = load_yaml_config('taylor_green_2D.yaml')" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "## 创建数据集\n", "\n", "训练数据集通过create_training_dataset函数导入,数据集分为区域内数据点、初始条件点、边界条件点,即['time_rect_domain_points', 'time_rect_IC_points', 'time_rect_BC_points'],均采用mindflow.geometry相应接口采样,内容在/src/dataset.py中的create_training_dataset函数中。\n", "\n", "测试数据集通过create_test_dataset函数导入。本案例使用 [J Kim, P Moin, Application of a fractional-step method to incompressible Navier-Stokes equations, Journal of Computational Physics, Volume 59, Issue 2, 1985](https://www.ljll.math.upmc.fr/~frey/papers/Navier-Stokes/KimJ.,%20Application%20of%20a%20fractional%20step%20method%20to%20incompressible%20Navier-Stokes%20equations.pdf)中给出的精确解构建验证集。\n", "\n", "本案例考虑一个大小为 $2\\pi \\times 2\\pi$ 的正方形区域在 $t \\in (0,2)$ 时段的aylor-Green涡流动仿真。该问题的精确解为:\n", "\n", "$$\n", "u(x,y,t) = -cos(x)sin(y)e^{-2t}\n", "$$\n", "\n", "$$\n", "v(x,y,t) = sin(x)cos(y)e^{-2t}\n", "$$\n", "\n", "$$\n", "p(x,y,t) = -0.25(cos(2x)+cos(2y))e^{-4t}\n", "$$" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "# create training dataset\n", "taylor_dataset = create_training_dataset(config)\n", "train_dataset = taylor_dataset.create_dataset(batch_size=config[\"train_batch_size\"],\n", " shuffle=True,\n", " prebatched_data=True,\n", " drop_remainder=True)\n", "\n", "# create test dataset\n", "inputs, label = create_test_dataset(config)" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "## 构建模型\n", "\n", "本示例使用一个简单的全连接网络,深度为6层,每层128个神经元,激活函数是tanh函数。" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [], "source": [ "coord_min = np.array(config[\"geometry\"][\"coord_min\"] + [config[\"geometry\"][\"time_min\"]]).astype(np.float32)\n", "coord_max = np.array(config[\"geometry\"][\"coord_max\"] + [config[\"geometry\"][\"time_max\"]]).astype(np.float32)\n", "input_center = list(0.5 * (coord_max + coord_min))\n", "input_scale = list(2.0 / (coord_max - coord_min))\n", "\n", "model = MultiScaleFCCell(in_channels=config[\"model\"][\"in_channels\"],\n", " out_channels=config[\"model\"][\"out_channels\"],\n", " layers=config[\"model\"][\"layers\"],\n", " neurons=config[\"model\"][\"neurons\"],\n", " residual=config[\"model\"][\"residual\"],\n", " act='tanh',\n", " num_scales=1,\n", " input_scale=input_scale,\n", " input_center=input_center)" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "## 优化器" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [], "source": [ "params = model.trainable_params()\n", "optimizer = nn.Adam(params, learning_rate=config[\"optimizer\"][\"initial_lr\"])" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "## NavierStokes2D\n", "\n", "下述NavierStokes2D将圆柱绕流问题同数据集关联起来,包含3个部分:控制方程,边界条件和初始条件。控制方程在mindflow.pde中实现,边界条件与初始条件也是根据上述论文中的解析解实现。" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [], "source": [ "class NavierStokes2D(NavierStokes):\n", " def __init__(self, model, re=100, loss_fn=nn.MSELoss()):\n", " super(NavierStokes2D, self).__init__(model, re=re, loss_fn=loss_fn)\n", " self.ic_nodes = sympy_to_mindspore(self.ic(), self.in_vars, self.out_vars)\n", " self.bc_nodes = sympy_to_mindspore(self.bc(), self.in_vars, self.out_vars)\n", "\n", " def ic(self):\n", " \"\"\"\n", " Define initial condition equations based on sympy, abstract method.\n", " \"\"\"\n", " ic_u = self.u + sympy.cos(self.x) * sympy.sin(self.y)\n", " ic_v = self.v - sympy.sin(self.x) * sympy.cos(self.y)\n", " ic_p = self.p + 0.25 * (sympy.cos(2*self.x) + sympy.cos(2*self.y))\n", " equations = {\"ic_u\": ic_u, \"ic_v\": ic_v, \"ic_p\": ic_p}\n", " return equations\n", "\n", " def bc(self):\n", " \"\"\"\n", " Define boundary condition equations based on sympy, abstract method.\n", " \"\"\"\n", " bc_u = self.u + sympy.cos(self.x) * sympy.sin(self.y) * sympy.exp(-2*self.t)\n", " bc_v = self.v - sympy.sin(self.x) * sympy.cos(self.y) * sympy.exp(-2*self.t)\n", " bc_p = self.p + 0.25 * (sympy.cos(2*self.x) + sympy.cos(2*self.y)) * sympy.exp(-4*self.t)\n", " equations = {\"bc_u\": bc_u, \"bc_v\": bc_v, \"bc_p\": bc_p}\n", " return equations\n", "\n", " def get_loss(self, pde_data, ic_data, bc_data):\n", " \"\"\"\n", " Compute loss of 3 parts: governing equation, initial condition and boundary conditions.\n", "\n", " Args:\n", " pde_data (Tensor): the input data of governing equations.\n", " ic_data (Tensor): the input data of initial condition.\n", " bc_data (Tensor): the input data of boundary condition.\n", " \"\"\"\n", " pde_res = self.parse_node(self.pde_nodes, inputs=pde_data)\n", " pde_residual = ops.Concat(1)(pde_res)\n", " pde_loss = self.loss_fn(pde_residual, mnp.zeros_like(pde_residual))\n", "\n", " ic_res = self.parse_node(self.ic_nodes, inputs=ic_data)\n", " ic_residual = ops.Concat(1)(ic_res)\n", " ic_loss = self.loss_fn(ic_residual, mnp.zeros_like(ic_residual))\n", "\n", " bc_res = self.parse_node(self.bc_nodes, inputs=bc_data)\n", " bc_residual = ops.Concat(1)(bc_res)\n", " bc_loss = self.loss_fn(bc_residual, mnp.zeros_like(bc_residual))\n", "\n", " return pde_loss + ic_loss + bc_loss" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "## 模型训练\n", "\n", "使用MindSpore>= 2.0.0的版本,可以使用函数式编程范式训练神经网络。" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [], "source": [ "def train():\n", " problem = NavierStokes2D(model, re=config[\"Re\"])\n", "\n", " if use_ascend:\n", " from mindspore.amp import DynamicLossScaler, auto_mixed_precision, all_finite\n", " loss_scaler = DynamicLossScaler(1024, 2, 100)\n", " auto_mixed_precision(model, 'O3')\n", "\n", " def forward_fn(pde_data, ic_data, bc_data):\n", " loss = problem.get_loss(pde_data, ic_data, bc_data)\n", " if use_ascend:\n", " loss = loss_scaler.scale(loss)\n", " return loss\n", "\n", " grad_fn = mindspore.value_and_grad(forward_fn, None, optimizer.parameters, has_aux=False)\n", "\n", " @jit\n", " def train_step(pde_data, ic_data, bc_data):\n", " loss, grads = grad_fn(pde_data, ic_data, bc_data)\n", " if use_ascend:\n", " loss = loss_scaler.unscale(loss)\n", " if all_finite(grads):\n", " grads = loss_scaler.unscale(grads)\n", " loss = ops.depend(loss, optimizer(grads))\n", " else:\n", " loss = ops.depend(loss, optimizer(grads))\n", " return loss\n", "\n", " epochs = config[\"train_epochs\"]\n", " steps_per_epochs = train_dataset.get_dataset_size()\n", " sink_process = mindspore.data_sink(train_step, train_dataset, sink_size=1)\n", " for epoch in range(1, 1 + epochs):\n", " # train\n", " time_beg = time.time()\n", " model.set_train(True)\n", " for _ in range(steps_per_epochs):\n", " step_train_loss = sink_process()\n", " model.set_train(False)\n", "\n", " if epoch % config[\"eval_interval_epochs\"] == 0:\n", " print(f\"epoch: {epoch} train loss: {step_train_loss} epoch time: {(time.time() - time_beg) * 1000 :.3f} ms\")\n", " calculate_l2_error(model, inputs, label, config)" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "momentum_x: u(x, y, t)*Derivative(u(x, y, t), x) + v(x, y, t)*Derivative(u(x, y, t), y) + Derivative(p(x, y, t), x) + Derivative(u(x, y, t), t) - 1.0*Derivative(u(x, y, t), (x, 2)) - 1.0*Derivative(u(x, y, t), (y, 2))\n", " Item numbers of current derivative formula nodes: 6\n", "momentum_y: u(x, y, t)*Derivative(v(x, y, t), x) + v(x, y, t)*Derivative(v(x, y, t), y) + Derivative(p(x, y, t), y) + Derivative(v(x, y, t), t) - 1.0*Derivative(v(x, y, t), (x, 2)) - 1.0*Derivative(v(x, y, t), (y, 2))\n", " Item numbers of current derivative formula nodes: 6\n", "continuty: Derivative(u(x, y, t), x) + Derivative(v(x, y, t), y)\n", " Item numbers of current derivative formula nodes: 2\n", "ic_u: u(x, y, t) + sin(y)*cos(x)\n", " Item numbers of current derivative formula nodes: 2\n", "ic_v: v(x, y, t) - sin(x)*cos(y)\n", " Item numbers of current derivative formula nodes: 2\n", "ic_p: p(x, y, t) + 0.25*cos(2*x) + 0.25*cos(2*y)\n", " Item numbers of current derivative formula nodes: 3\n", "bc_u: u(x, y, t) + exp(-2*t)*sin(y)*cos(x)\n", " Item numbers of current derivative formula nodes: 2\n", "bc_v: v(x, y, t) - exp(-2*t)*sin(x)*cos(y)\n", " Item numbers of current derivative formula nodes: 2\n", "bc_p: p(x, y, t) + 0.25*exp(-4*t)*cos(2*x) + 0.25*exp(-4*t)*cos(2*y)\n", " Item numbers of current derivative formula nodes: 3\n", "epoch: 20 train loss: 0.11818831 epoch time: 9838.472 ms\n", " predict total time: 342.714786529541 ms\n", " l2_error, U: 0.7095809547153462 , V: 0.7081305150496081 , P: 1.004580707024092 , Total: 0.7376210740866216\n", "==================================================================================================\n", "epoch: 40 train loss: 0.025397364 epoch time: 9853.950 ms\n", " predict total time: 67.26336479187012 ms\n", " l2_error, U: 0.09177234501446464 , V: 0.14504987645942635 , P: 1.0217915750380309 , Total: 0.3150453016208772\n", "==================================================================================================\n", "epoch: 60 train loss: 0.0049396083 epoch time: 10158.307 ms\n", " predict total time: 121.54984474182129 ms\n", " l2_error, U: 0.08648064925211238 , V: 0.07875554509736878 , P: 0.711385847511365 , Total: 0.2187113170206073\n", "==================================================================================================\n", "epoch: 80 train loss: 0.0018874758 epoch time: 10349.795 ms\n", " predict total time: 85.42561531066895 ms\n", " l2_error, U: 0.08687053366212526 , V: 0.10624717784645109 , P: 0.3269822261697911 , Total: 0.1319986181134018\n", "==================================================================================================\n", "......\n", "epoch: 460 train loss: 0.00015093417 epoch time: 9928.474 ms\n", " predict total time: 81.79974555969238 ms\n", " l2_error, U: 0.033782269766829076 , V: 0.025816595720090357 , P: 0.08782072926563861 , Total: 0.03824859644715835\n", "==================================================================================================\n", "epoch: 480 train loss: 6.400551e-05 epoch time: 9956.549 ms\n", " predict total time: 104.77519035339355 ms\n", " l2_error, U: 0.02242134127961232 , V: 0.021098481157660533 , P: 0.06210985820202502 , Total: 0.027418651376509482\n", "==================================================================================================\n", "epoch: 500 train loss: 8.7400025e-05 epoch time: 10215.720 ms\n", " predict total time: 77.20041275024414 ms\n", " l2_error, U: 0.021138056243295636 , V: 0.013343674071961624 , P: 0.045241559122240635 , Total: 0.02132725837819097\n", "==================================================================================================\n", "End-to-End total time: 5011.718255519867 s\n" ] } ], "source": [ "start_time = time.time()\n", "train()\n", "print(\"End-to-End total time: {} s\".format(time.time() - start_time))" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "## 模型推理及可视化" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "data": { "image/png": "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10Z3X+MNdAeFr0pKSmLMmDE89NBD3efVm81mHA4Hw4YN4/PPP8fr9eJyuZg6dSoPP/wwO3bs4J133uHRRx/l7rvvxmw209bWRlFRUZ9NQBRC9C2ZAyDEEGIymXC5XGzbto2amhp0XT/irzF58mRsNhsvvvgiNTU1rFu3jg8//JCuri5GjhyJYRjU1tYSDAZZsGABa9asISkpCavVimEYaJqGx+Ohra2NwsLCHkOGECL65CdTiCHEbrfzk5/8hCVLlvCDH/wATdMYMWIEJpOJ7OxsRo4cCUTu/ouLi8nKygIgLi6OkpIS3G43GRkZ/O///i+tra387Gc/4+mnn0bXdeLi4sjMzKSoqIiNGzcCkSOFn332WW644QY8Hg8///nPSUhIoLy8HJPJxLhx46L2XgghDk6OAxZCHDalFJ9++ikVFRVcfPHF2O32Hss888wz5ObmMm/evCjUUghxOCQACCGOiN/vp6uri+Tk5B7H95VS1NfXk5yc3L0qQAgx8EgAEEIIIWKQzAEQQgghYpAEACGEECIGSQAQQgghYpAEACGEECIGSQAQQgghYpAEACGEECIGSQAQQgghYpAEACGEECIGSQAQQgghYpAEACGEECIGSQAQQgghYpAEACGEECIGSQAQQgghYpAEACGEECIGSQAQQgghYpAEACGEECIG/X9baPUYV1g4VAAAAABJRU5ErkJggg==", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "from src import visual\n", "\n", "# visualization\n", "visual(model=model, epoch=config[\"train_epochs\"], input_data=inputs, label=label)" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "因速度呈指数下降的趋势,随着时间推移,误差变大,但整体处于5%的误差范围内。" ] } ], "metadata": { "kernelspec": { "display_name": "mindspore_py37", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.7.12" }, "orig_nbformat": 4, "vscode": { "interpreter": { "hash": "55cde14d23a44784ae1a8ec18da2253dd69c1bd4d69757e4b4870283359a8176" } } }, "nbformat": 4, "nbformat_minor": 2 }