fixing typos, unifying nomenclature

This commit is contained in:
NT committed 2021-09-09 10:34:36 +02:00
1 parent 73ec4d1155
commit e0dcf28064
13 files changed
+381 -376

No files matched your search

+5 -5
View File
@@ -17,19 +17,19 @@
"\n", "\n",
"We'll use a Navier-Stokes model with velocity $\\mathbf{u}$, no explicit viscosity term, and a smoke marker density $s$ that drives a simple Boussinesq buoyancy term $\\eta d$ adding a force along the y dimension. For the velocity this gives:\n", "We'll use a Navier-Stokes model with velocity $\\mathbf{u}$, no explicit viscosity term, and a smoke marker density $s$ that drives a simple Boussinesq buoyancy term $\\eta d$ adding a force along the y dimension. For the velocity this gives:\n",
"\n", "\n",
"$\\begin{aligned}\n", "$$\\begin{aligned}\n",
" \\frac{\\partial u_x}{\\partial{t}} + \\mathbf{u} \\cdot \\nabla u_x &= - \\frac{1}{\\rho} \\nabla p \n", " \\frac{\\partial u_x}{\\partial{t}} + \\mathbf{u} \\cdot \\nabla u_x &= - \\frac{1}{\\rho} \\nabla p \n",
" \\\\\n", " \\\\\n",
" \\frac{\\partial u_y}{\\partial{t}} + \\mathbf{u} \\cdot \\nabla u_y &= - \\frac{1}{\\rho} \\nabla p + \\eta d\n", " \\frac{\\partial u_y}{\\partial{t}} + \\mathbf{u} \\cdot \\nabla u_y &= - \\frac{1}{\\rho} \\nabla p + \\eta d\n",
" \\\\\n", " \\\\\n",
" \\text{s.t.} \\quad \\nabla \\cdot \\mathbf{u} &= 0,\n", " \\text{s.t.} \\quad \\nabla \\cdot \\mathbf{u} &= 0,\n",
"\\end{aligned}$\n", "\\end{aligned}$$\n",
"\n", "\n",
"With an additional transport equation for the passively advected marker density $s$:\n", "With an additional transport equation for the passively advected marker density $s$:\n",
"\n", "\n",
"$\\begin{aligned}\n", "$$\\begin{aligned}\n",
" \\frac{\\partial s}{\\partial{t}} + \\mathbf{u} \\cdot \\nabla s &= 0 \n", " \\frac{\\partial s}{\\partial{t}} + \\mathbf{u} \\cdot \\nabla s &= 0 \n",
"\\end{aligned}$\n", "\\end{aligned}$$\n",
"\n" "\n"
] ]
}, },
@@ -45,7 +45,7 @@
"With the notation from {doc}`overview-equations` the inverse problem outlined above can be formulated as a minimization problem \n", "With the notation from {doc}`overview-equations` the inverse problem outlined above can be formulated as a minimization problem \n",
"\n", "\n",
"$$\n", "$$\n",
"\\text{arg min}_{\\mathbf{u}_{0}} \\sum_i |f(x_{t_e,i} ; \\mathbf{u}_{0} )-y^*_{t_e,i}|^2 ,\n", "\\text{arg min}_{\\mathbf{u}_{0}} \\sum_i \\big( f(x_{t_e,i} ; \\mathbf{u}_{0} )-y^*_{t_e,i} \\big)^2 ,\n",
"$$\n", "$$\n",
"\n", "\n",
"where $y^*_{t_e,i}$ are samples of the reference solution at a targeted time $t_e$,\n", "where $y^*_{t_e,i}$ are samples of the reference solution at a targeted time $t_e$,\n",
+1 -1
View File
@@ -89,7 +89,7 @@
"$$\n", "$$\n",
"\\newcommand{\\corr}{\\mathcal{C}} \n", "\\newcommand{\\corr}{\\mathcal{C}} \n",
"\\newcommand{\\vr}[1]{\\mathbf{r}_{#1}} \n", "\\newcommand{\\vr}[1]{\\mathbf{r}_{#1}} \n",
"\\text{argmin}_\\theta | ( \\mathcal{P}_{s} \\corr )^n ( \\mathcal{T} \\vr{t} ) - \\mathcal{T} \\vr{t+n}|^2\n", "\\text{arg min}_\\theta \\big( ( \\mathcal{P}_{s} \\corr )^n ( \\mathcal{T} \\vr{t} ) - \\mathcal{T} \\vr{t+n} \\big)^2\n",
"$$\n", "$$\n",
"\n", "\n",
"To simplify the notation, we've dropped the sum over different samples here (the $i$ from previous versions).\n", "To simplify the notation, we've dropped the sum over different samples here (the $i$ from previous versions).\n",
+7 -5
View File
@@ -43,11 +43,11 @@
"\n", "\n",
"Let's illustrate the properties of deep learning via DP with the following example: We'd like to find an unknown function $f^*$ that generates solutions from a space $Y$, taking inputs from $X$, i.e. $f^*: X \\to Y$. In the following, we'll often denote _idealized_, and unknown functions with a $*$ superscript, in contrast to their discretized, realizable counterparts without this superscript. \n", "Let's illustrate the properties of deep learning via DP with the following example: We'd like to find an unknown function $f^*$ that generates solutions from a space $Y$, taking inputs from $X$, i.e. $f^*: X \\to Y$. In the following, we'll often denote _idealized_, and unknown functions with a $*$ superscript, in contrast to their discretized, realizable counterparts without this superscript. \n",
"\n", "\n",
"Let's additionally assume we have a generic differential equation $\\mathcal P^*: Y \\to Z$ (our _model_ equation), that encodes a property of the solutions, e.g. some real world behavior we'd like to match. Later on, $P^*$ will represent time evolutions, but it could also be a constraint for conservation of mass (then $\\mathcal P^*$ would measure divergence). But to keep things as simple as possible here, the model we'll look at in the following is a mapping back to the input space $X$, i.e. $\\mathcal P^*: Y \\to X$.\n", "Let's additionally assume we have a generic differential equation $\\mathcal P^*: Y \\to Z$ (our _model_ equation), that encodes a property of the solutions, e.g. some real world behavior we'd like to match. Later on, $P^*$ will often represent time evolutions, but it could also be a constraint for conservation of mass (then $\\mathcal P^*$ would measure divergence). But to keep things as simple as possible here, the model we'll look at in the following is a mapping back to the input space $X$, i.e. $\\mathcal P^*: Y \\to X$.\n",
"\n", "\n",
"Using a neural network $f$ to learn the unknown and ideal function $f^*$, we could turn to classic _supervised_ training to obtain $f$ by collecting data. This classical setup requires a dataset by sampling $x$ from $X$ and adding the corresponding solutions $y$ from $Y$. We could obtain these, e.g., by classical numerical techniques. Then we train the NN $f$ in the usual way using this dataset. \n", "Using a neural network $f$ to learn the unknown and ideal function $f^*$, we could turn to classic _supervised_ training to obtain $f$ by collecting data. This classical setup requires a dataset by sampling $x$ from $X$ and adding the corresponding solutions $y$ from $Y$. We could obtain these, e.g., by classical numerical techniques. Then we train the NN $f$ in the usual way using this dataset. \n",
"\n", "\n",
"In contrast to this supervised approach, employing differentiable physics takes advantage of the fact that we can directly use a discretized version of the physical model $\\mathcal P$ and employ it to guide the training of $f$. I.e., we want $f$ to _interact_ with our _simulator_ $\\mathcal P$. This can vastly improve the learning, as we'll illustrate below with a very simple example (more complex ones will follow later on).\n", "In contrast to this supervised approach, employing a differentiable physics approach takes advantage of the fact that we can often use a discretized version of the physical model $\\mathcal P$ and employ it to guide the training of $f$. I.e., we want $f$ to be aware of our _simulator_ $\\mathcal P$, and to _interact_ with it. This can vastly improve the learning, as we'll illustrate below with a very simple example (more complex ones will follow later on).\n",
"\n", "\n",
"Note that in order for the DP approach to work, $\\mathcal P$ has to be differentiable, as implied by the name. These differentials, in the form of a gradient, are what's driving the learning process.\n" "Note that in order for the DP approach to work, $\\mathcal P$ has to be differentiable, as implied by the name. These differentials, in the form of a gradient, are what's driving the learning process.\n"
] ]
@@ -65,7 +65,7 @@
"id": "latest-amino", "id": "latest-amino",
"metadata": {}, "metadata": {},
"source": [ "source": [
"To illustrate these two approaches, we consider the following simplified setting: Given the function $\\mathcal P: y\\to y^2$ for $y$ in the intverval $[0,1]$, find the unknown function $f$ such that $\\mathcal P(f(x)) = x$ for all $x$ in $[0,1]$. Note: to make things a bit more interesting, we're using $y^2$ here instead of the more common $x^2$ parabola, and the _discretization_ is simply given by representing the $x$ and $y$ via floating point numbers in the computer for this simple case.\n", "To illustrate the difference of supervised and DP approaches, we consider the following simplified setting: Given the function $\\mathcal P: y\\to y^2$ for $y$ in the interval $[0,1]$, find the unknown function $f$ such that $\\mathcal P(f(x)) = x$ for all $x$ in $[0,1]$. Note: to make things a bit more interesting, we're using $y^2$ here for $\\mathcal P$ instead of the more common $x^2$ parabola, and the _discretization_ is simply given by representing the $x$ and $y$ via floating point numbers in the computer for this simple case.\n",
"\n", "\n",
"We know that possible solutions for $f$ are the positive or negative square root function (for completeness: piecewise combinations would also be possible).\n", "We know that possible solutions for $f$ are the positive or negative square root function (for completeness: piecewise combinations would also be possible).\n",
"Knowing that this is not overly difficult, a solution that suggests itself is to train a neural network to approximate this inverse mapping $f$.\n", "Knowing that this is not overly difficult, a solution that suggests itself is to train a neural network to approximate this inverse mapping $f$.\n",
@@ -385,9 +385,11 @@
"source": [ "source": [
"## Discussion\n", "## Discussion\n",
"\n", "\n",
"It's a very simple example, but it very clearly shows a failure case for supervised learning. While it might seem very artificial at first sight, many practical PDEs exhibit a variety of these modes, and it's often not clear where (and how many) exist in the solution manifold we're interested in. Using supervised learning is very dangerous in such cases - we might simply and unknowingly _blur_ out these different modes.\n", "It's a very simple example, but it very clearly shows a failure case for supervised learning. While it might seem very artificial at first sight, many practical PDEs exhibit a variety of these modes, and it's often not clear where (and how many) exist in the solution manifold we're interested in. Using supervised learning is very dangerous in such cases. We might unknowingly get an average of these different modes.\n",
"\n", "\n",
"Good and obvious examples are bifurcations in fluid flow. Smoke rising above a candle will start out straight, and then, due to tiny perturbations in its motion, start oscillating in a random direction. The images below illustrate this case via _numerical perturbations_: the perfectly symmetric setup will start turning left or right, depending on how the approximation errors build up. Similarly, we'll have different modes in all our numerical solutions, and typically it's important to recover them, rather than averaging them out. Hence, we'll show how to leverage training via _differentiable physics_ in the following chapters for more practical and complex cases.\n", "Good and obvious examples are bifurcations in fluid flow. Smoke rising above a candle will start out straight, and then, due to tiny perturbations in its motion, start oscillating in a random direction. The images below illustrate this case via _numerical perturbations_: the perfectly symmetric setup will start turning left or right, depending on how the approximation errors build up. Averaging the two modes would give an unphysical, straight flow similar to the parabola example above.\n",
"\n",
"Similarly, we have different modes in many numerical solutions, and typically it's important to recover them, rather than averaging them out. Hence, we'll show how to leverage training via _differentiable physics_ in the following chapters for more practical and complex cases.\n",
"\n", "\n",
"```{figure} resources/intro-fluid-bifurcation.jpg\n", "```{figure} resources/intro-fluid-bifurcation.jpg\n",
"---\n", "---\n",
+6 -5
View File
@@ -7,17 +7,18 @@ name: pbdl-logo-large
--- ---
``` ```
Welcome to the _Physics-based Deep Learning Book_ 👋 Welcome to the _Physics-based Deep Learning Book_ (v0.1) 👋
**TL;DR**: **TL;DR**:
This document targets a practical and comprehensive introduction of everything This document contains a practical and comprehensive introduction of everything
related to deep learning in the context of physical simulations. related to deep learning in the context of physical simulations.
As much as possible, all topics come with hands-on code examples in the form of Jupyter notebooks to quickly get started. As much as possible, all topics come with hands-on code examples in the
form of Jupyter notebooks to quickly get started.
Beyond standard _supervised_ learning from data, we'll look at _physical loss_ constraints, Beyond standard _supervised_ learning from data, we'll look at _physical loss_ constraints,
more tightly coupled learning algorithms with _differentiable simulations_, as well as more tightly coupled learning algorithms with _differentiable simulations_, as well as
reinforcement learning and uncertainty modeling. reinforcement learning and uncertainty modeling.
We live in exciting times: these methods have a huge potential to fundamentally change what we can achieve We live in exciting times: these methods have a huge potential to fundamentally
with simulations. change what computer simulations can achieve.
--- ---
+100 -100
View File
@@ -2,11 +2,10 @@
"cells": [ "cells": [
{ {
"cell_type": "markdown", "cell_type": "markdown",
"metadata": {},
"source": [ "source": [
"# Simple Forward Simulation of Burgers Equation with phiflow\n", "# Simple Forward Simulation of Burgers Equation with phiflow\n",
"\n", "\n",
"This chapter will give an introduction for how to run _forward_, i.e., regular simulations starting with a given initial state and approximating a later state numerically, with Φ<sub>Flow</sub>. The Φ<sub>Flow</sub> framework provides a set of differentiable building blocks that directly interface with deep learning frameworks. Before going for deeper and more complicated integrations, this notebook (and the next one), will show how regular simulations can be done with Φ<sub>Flow</sub>. Later on, we can use very similar code to couple them with neural networks.\n", "This chapter will give an introduction for how to run _forward_, i.e., regular simulations starting with a given initial state and approximating a later state numerically, and introduce the Φ<sub>Flow</sub> framework. Φ<sub>Flow</sub> provides a set of differentiable building blocks that directly interface with deep learning frameworks, and hence is a very good basis for the topics of this book. Before going for deeper and more complicated integrations, this notebook (and the next one), will show how regular simulations can be done with Φ<sub>Flow</sub>. Later on, we'll show that these simulations can be easily coupled with neural networks.\n",
"\n", "\n",
"The main repository for Φ<sub>Flow</sub> (in the following \"phiflow\") is [https://github.com/tum-pbs/PhiFlow](https://github.com/tum-pbs/PhiFlow), and additional API documentation and examples can be found at [https://tum-pbs.github.io/PhiFlow/](https://tum-pbs.github.io/PhiFlow/).\n", "The main repository for Φ<sub>Flow</sub> (in the following \"phiflow\") is [https://github.com/tum-pbs/PhiFlow](https://github.com/tum-pbs/PhiFlow), and additional API documentation and examples can be found at [https://tum-pbs.github.io/PhiFlow/](https://tum-pbs.github.io/PhiFlow/).\n",
"\n", "\n",
@@ -23,32 +22,23 @@
" \\nu \\nabla\\cdot \\nabla u\n", " \\nu \\nabla\\cdot \\nabla u\n",
"$$ \n", "$$ \n",
"\n" "\n"
] ],
"metadata": {}
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"metadata": {},
"source": [ "source": [
"## Importing and loading phiflow\n", "## Importing and loading phiflow\n",
"\n", "\n",
"Let's get some preliminaries out of the way: first we'll import the phiflow library, more specifically the `numpy` operators for fluid flow simulations: `phi.flow` (differentiable versions for a DL framework _X_ are loaded via `phi.X.flow` instead).\n", "Let's get some preliminaries out of the way: first we'll import the phiflow library, more specifically the `numpy` operators for fluid flow simulations: `phi.flow` (differentiable versions for a DL framework _X_ are loaded via `phi.X.flow` instead).\n",
"\n", "\n",
"**Note:** Below, the first command with a \"!\" prefix will install the [phiflow python package from GitHub](https://github.com/tum-pbs/PhiFlow) via `pip` in your python environment once you uncomment it. We've assumed that phiflow isn't installed, but if you have already done so, just comment out the first line (the same will hold for all following notebooks)." "**Note:** Below, the first command with a \"!\" prefix will install the [phiflow python package from GitHub](https://github.com/tum-pbs/PhiFlow) via `pip` in your python environment once you uncomment it. We've assumed that phiflow isn't installed, but if you have already done so, just comment out the first line (the same will hold for all following notebooks)."
] ],
"metadata": {}
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 1, "execution_count": 1,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Using phiflow version: 2.0.0rc2\n"
]
}
],
"source": [ "source": [
"#!pip install --upgrade --quiet phiflow\n", "#!pip install --upgrade --quiet phiflow\n",
"!pip install --upgrade --quiet git+https://github.com/tum-pbs/PhiFlow@develop\n", "!pip install --upgrade --quiet git+https://github.com/tum-pbs/PhiFlow@develop\n",
@@ -57,11 +47,20 @@
"\n", "\n",
"from phi import __version__\n", "from phi import __version__\n",
"print(\"Using phiflow version: {}\".format(phi.__version__))" "print(\"Using phiflow version: {}\".format(phi.__version__))"
] ],
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"text": [
"Using phiflow version: 2.0.0rc2\n"
]
}
],
"metadata": {}
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"metadata": {},
"source": [ "source": [
"Next we can define and initialize the necessary constants (denoted by upper-case names):\n", "Next we can define and initialize the necessary constants (denoted by upper-case names):\n",
"our simulation domain will have `N=128` cells as discretization points for the 1D velocity $u$ in a periodic domain $\\Omega$ for the interval $[-1,1]$. We'll use 32 time `STEPS` for a time interval of 1, giving us `DT=1/32`. Additionally, we'll use a viscosity `NU` of $\\nu=0.01/\\pi$.\n", "our simulation domain will have `N=128` cells as discretization points for the 1D velocity $u$ in a periodic domain $\\Omega$ for the interval $[-1,1]$. We'll use 32 time `STEPS` for a time interval of 1, giving us `DT=1/32`. Additionally, we'll use a viscosity `NU` of $\\nu=0.01/\\pi$.\n",
@@ -71,13 +70,12 @@
"Phiflow is object-oriented and centered around field data in the form of grids (internally represented by a tensor object). I.e. you assemble your simulation by constructing a number of grids, and updating them over the course of time steps. \n", "Phiflow is object-oriented and centered around field data in the form of grids (internally represented by a tensor object). I.e. you assemble your simulation by constructing a number of grids, and updating them over the course of time steps. \n",
"\n", "\n",
"Phiflow internally works with tensors that have named dimensions. This will be especially handy later on for 2D simulations with additional batch and channel dimensions, but for now we'll simply convert the 1D array into a phiflow tensor that has a single spatial dimension `'x'`.\n" "Phiflow internally works with tensors that have named dimensions. This will be especially handy later on for 2D simulations with additional batch and channel dimensions, but for now we'll simply convert the 1D array into a phiflow tensor that has a single spatial dimension `'x'`.\n"
] ],
"metadata": {}
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 2, "execution_count": 2,
"metadata": {},
"outputs": [],
"source": [ "source": [
"N = 128\n", "N = 128\n",
"STEPS = 32\n", "STEPS = 32\n",
@@ -88,34 +86,24 @@
"INITIAL_NUMPY = np.asarray( [-np.sin(np.pi * x) * 1. for x in np.linspace(-1,1,N)] ) # 1D numpy array\n", "INITIAL_NUMPY = np.asarray( [-np.sin(np.pi * x) * 1. for x in np.linspace(-1,1,N)] ) # 1D numpy array\n",
"\n", "\n",
"INITIAL = math.tensor(INITIAL_NUMPY, spatial('x') ) # convert to phiflow tensor\n" "INITIAL = math.tensor(INITIAL_NUMPY, spatial('x') ) # convert to phiflow tensor\n"
] ],
"outputs": [],
"metadata": {}
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"metadata": {},
"source": [ "source": [
"\n", "\n",
"Next, we initialize a 1D `velocity` grid from the `INITIAL` numpy array that was converted into a tensor.\n", "Next, we initialize a 1D `velocity` grid from the `INITIAL` numpy array that was converted into a tensor.\n",
"The extent of our domain $\\Omega$ is specifiied via the `bounds` parameter $[-1,1]$, and the grid uses periodic boundary conditions (`extrapolation.PERIODIC`). These two properties are the main difference between a tensor and a grid: the latter has boundary conditions and a physical extent.\n", "The extent of our domain $\\Omega$ is specifiied via the `bounds` parameter $[-1,1]$, and the grid uses periodic boundary conditions (`extrapolation.PERIODIC`). These two properties are the main difference between a tensor and a grid: the latter has boundary conditions and a physical extent.\n",
"\n", "\n",
"Just to illustrate, we'll also print some info about the velocity object: it's a `phi.math` tensor with a size of 128. Note that the actual grid content is contained in the `values` of the grid. Below we're printing five entries by using the `numpy()` function to convert the content of the phiflow tensor into a numpy array. For tensors with more dimensions, we'd need to specify the order here, e.g., `'y,x,vector'` for a 2D velocity field. (If we'd call `numpy('x,vector')` below, this would convert the 1D array into one with an additional dimension for each 1D velocity component.)" "Just to illustrate, we'll also print some info about the velocity object: it's a `phi.math` tensor with a size of 128. Note that the actual grid content is contained in the `values` of the grid. Below we're printing five entries by using the `numpy()` function to convert the content of the phiflow tensor into a numpy array. For tensors with more dimensions, we'd need to specify the order here, e.g., `'y,x,vector'` for a 2D velocity field. (If we'd call `numpy('x,vector')` below, this would convert the 1D array into one with an additional dimension for each 1D velocity component.)"
] ],
"metadata": {}
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 3, "execution_count": 3,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Velocity tensor shape: (xˢ=128)\n",
"Velocity tensor type: <class 'phi.math._tensors.CollapsedTensor'>\n",
"Velocity tensor entries 10 to 14: [0.47480196 0.51774486 0.55942075 0.59972764 0.6385669 ]\n"
]
}
],
"source": [ "source": [
"velocity = CenteredGrid(INITIAL, extrapolation.PERIODIC, x=N, bounds=Box[-1:1])\n", "velocity = CenteredGrid(INITIAL, extrapolation.PERIODIC, x=N, bounds=Box[-1:1])\n",
"#velocity = CenteredGrid(Noise(), extrapolation.PERIODIC, x=N, bounds=Box[-1:1]) # random init\n", "#velocity = CenteredGrid(Noise(), extrapolation.PERIODIC, x=N, bounds=Box[-1:1]) # random init\n",
@@ -123,30 +111,32 @@
"print(\"Velocity tensor shape: \" + format( velocity.shape )) # == velocity.values.shape\n", "print(\"Velocity tensor shape: \" + format( velocity.shape )) # == velocity.values.shape\n",
"print(\"Velocity tensor type: \" + format( type(velocity.values) ))\n", "print(\"Velocity tensor type: \" + format( type(velocity.values) ))\n",
"print(\"Velocity tensor entries 10 to 14: \" + format( velocity.values.numpy()[10:15] ))" "print(\"Velocity tensor entries 10 to 14: \" + format( velocity.values.numpy()[10:15] ))"
] ],
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"text": [
"Velocity tensor shape: (xˢ=128)\n",
"Velocity tensor type: <class 'phi.math._tensors.CollapsedTensor'>\n",
"Velocity tensor entries 10 to 14: [0.47480196 0.51774486 0.55942075 0.59972764 0.6385669 ]\n"
]
}
],
"metadata": {}
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"metadata": {},
"source": [ "source": [
"## Running the simulation\n", "## Running the simulation\n",
"\n", "\n",
"Now we're ready to run the simulation itself. To ccompute the diffusion and advection components of our model equation we can simply call the existing `diffusion` and `semi_lagrangian` operators in phiflow: `diffuse.explicit(u,...)` computes an explicit diffusion step via central differences for the term $\\nu \\nabla\\cdot \\nabla u$ of our model. Next, `advect.semi_lagrangian(f,u)` is used for a stable first-order approximation of the transport of an arbitrary field `f` by a velocity `u`. In our model we have $\\partial u / \\partial{t} + u \\nabla f$, hence we use the `semi_lagrangian` function to transport the velocity with itself in the implementation:" "Now we're ready to run the simulation itself. To ccompute the diffusion and advection components of our model equation we can simply call the existing `diffusion` and `semi_lagrangian` operators in phiflow: `diffuse.explicit(u,...)` computes an explicit diffusion step via central differences for the term $\\nu \\nabla\\cdot \\nabla u$ of our model. Next, `advect.semi_lagrangian(f,u)` is used for a stable first-order approximation of the transport of an arbitrary field `f` by a velocity `u`. In our model we have $\\partial u / \\partial{t} + u \\nabla f$, hence we use the `semi_lagrangian` function to transport the velocity with itself in the implementation:"
] ],
"metadata": {}
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 4, "execution_count": 4,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"New velocity content at t=1.0: [0.00274862 0.01272991 0.02360343 0.03478042 0.0460869 ]\n"
]
}
],
"source": [ "source": [
"velocities = [velocity]\n", "velocities = [velocity]\n",
"age = 0.\n", "age = 0.\n",
@@ -157,11 +147,20 @@
" velocities.append(v2)\n", " velocities.append(v2)\n",
"\n", "\n",
"print(\"New velocity content at t={}: {}\".format( age, velocities[-1].values.numpy()[0:5] ))" "print(\"New velocity content at t={}: {}\".format( age, velocities[-1].values.numpy()[0:5] ))"
] ],
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"text": [
"New velocity content at t=1.0: [0.00274862 0.01272991 0.02360343 0.03478042 0.0460869 ]\n"
]
}
],
"metadata": {}
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"metadata": {},
"source": [ "source": [
"Here we're actually collecting all time steps in the list `velocities`. This is not necessary in general (and could consume lots of memory for long-running sims), but useful here to plot the evolution of the velocity states later on.\n", "Here we're actually collecting all time steps in the list `velocities`. This is not necessary in general (and could consume lots of memory for long-running sims), but useful here to plot the evolution of the velocity states later on.\n",
"\n", "\n",
@@ -170,36 +169,12 @@
"## Visualization\n", "## Visualization\n",
"\n", "\n",
"We can visualize this 1D case easily in a graph: the following code shows the initial state in blue, and then times $10/32, 20/32, 1$ in green, cyan and purple. " "We can visualize this 1D case easily in a graph: the following code shows the initial state in blue, and then times $10/32, 20/32, 1$ in green, cyan and purple. "
] ],
"metadata": {}
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 5, "execution_count": 5,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"<matplotlib.legend.Legend at 0x7f9ca2d4ef70>"
]
},
"execution_count": 5,
"metadata": {},
"output_type": "execute_result"
},
{
"data": {
"image/png": "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 truncated
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [ "source": [
"# get \"velocity.values\" from each phiflow state with a channel dimensions, i.e. \"vector\"\n", "# get \"velocity.values\" from each phiflow state with a channel dimensions, i.e. \"vector\"\n",
"vels = [v.values.numpy('x,vector') for v in velocities] # gives a list of 2D arrays \n", "vels = [v.values.numpy('x,vector') for v in velocities] # gives a list of 2D arrays \n",
@@ -212,37 +187,47 @@
"fig.plot(np.linspace(-1,1,len(vels[20].flatten())), vels[20].flatten(), lw=2, color='cyan', label=\"t=0.625\")\n", "fig.plot(np.linspace(-1,1,len(vels[20].flatten())), vels[20].flatten(), lw=2, color='cyan', label=\"t=0.625\")\n",
"fig.plot(np.linspace(-1,1,len(vels[32].flatten())), vels[32].flatten(), lw=2, color='purple',label=\"t=1\")\n", "fig.plot(np.linspace(-1,1,len(vels[32].flatten())), vels[32].flatten(), lw=2, color='purple',label=\"t=1\")\n",
"pylab.xlabel('x'); pylab.ylabel('u'); pylab.legend()\n" "pylab.xlabel('x'); pylab.ylabel('u'); pylab.legend()\n"
] ],
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": [
"<matplotlib.legend.Legend at 0x7f9ca2d4ef70>"
]
},
"metadata": {},
"execution_count": 5
},
{
"output_type": "display_data",
"data": {
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
],
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAZAAAAEGCAYAAABLgMOSAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjMuMywgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/Il7ecAAAACXBIWXMAAAsTAAALEwEAmpwYAABt+klEQVR4nO2dd3yN1//A3ycbMWOL2GrHiJGEtihKa7XUKkqNTmpTihq/GkW1qD1rFTWqLTXq24rE3nsTW4gVWfee3x/nJrnIzh0J5/163Vfu8zznOedzn3vzfJ5zPktIKdFoNBqNJqU42FsAjUaj0WRMtALRaDQaTarQCkSj0Wg0qUIrEI1Go9GkCq1ANBqNRpMqnOwtgC3JnTu3LFq0qL3F0Gg0mgzF/v3770op8zy//5VSIEWLFmXfvn32FkOj0WgyFEKIy/Ht10tYGo1Go0kVWoFoNBqNJlVoBaLRaDSaVPFK2UA0Gs3LSVRUFMHBwYSHh9tblAyNm5sbnp6eODs7J6u9ViAajSbDExwcTNasWSlatChCCHuLkyGRUhISEkJwcDDFihVL1jl2XcISQswXQtwWQhxL4LgQQvwohDgnhDgihKhqdqyzEOKs6dXZdlJrNJr0Rnh4OB4eHlp5pAEhBB4eHimaxdnbBrIQeDuR442BUqZXD+BnACFELmAEUBOoAYwQQuS0qqQajSZdo5VH2knpNbTrEpaU8l8hRNFEmjQHFkuVcz5ICJFDCFEAeBPYIqW8ByCE2IJSRMutLLLmOW7ehMBAOHkSLl2CGzcgPBwiIyFrVvDwgEKFoEIFqFQJypUDB3s/tphx/dF1goKDOBNyhov3L3LryS2M0ghAwawFKZGzBJXzV+aNom/g4uhiZ2k1mvRFereBFAKumm0Hm/YltP8FhBA9ULMXvLy8rCPlK4TRCLt2werV8PvvcOFCys7PnRsaNIDmzdXLzc06ciZEeHQ42y9uZ8PpDWw6t4nLD+KNj3qB7K7ZafZaMwb4DaBivopWllKT0QgNDWXZsmV89tlnyWp/8eJF2rZtS0hICNWqVWPJkiW4uGS8B5T0rkDSjJRyNjAbwMfHR1fPSiX37sG8eTBjhpppxODuDrVqgbc3FCsGnp6QKRM4OcHjxxASAhcvwtGjsH8/XL0Ky5erV44c0K4d9OkDpUpZT3YpJXuu7WHhoYWsOL6C0PDQ2GPZXLNRs1BNKuatSLGcxSjgXgAnByeM0kjww2DO3jvL9ovbOX7nOEuOLGHp0aV0rdyV0fVGk989v/WE1mQoQkNDmTFjRrIVyKBBg+jTpw9t27blk08+Yd68eXz66adWltIKSCnt+gKKAscSODYLaGe2fRooALQDZiXULqFXtWrVpCZl3Lsn5eDBUmbOLCWoV5EiUg4YIGVQkJTR0cnvy2iU8tQpKadMkbJatbj+hJDygw+kPHbMsrJHREfIJYeXSJ/ZPpKRxL68f/aWI/8ZKfdf3y+jDcn7AKfunJJf/PGFdPzWUTISmf/7/HLvtb2WFViTak6cOGHX8du0aSPd3Nykt7e37N+/f6JtjUaj9PDwkFFRUVJKKXft2iUbNmxoCzGTRXzXEtgn47tHx7fTlq8kFMg7wF+AAGoBe0z7cwEXgZym10UgV1JjaQWSfKKipJw8Wcrs2eNu9A0bSrlxY8qURmIcOSJlt25SOjur/h0cpPzsMynv3Elbv0+jnsqfdv8kPSd7xioNj/Eesu+mvvLIzSNp6vvUnVPyjQVvSEYiM4/NLNefWp82YTUWwfymF/N7tfQrMS5evCjLly8vpZTy4cOH0tvbO97X8ePH5Z07d2SJEiViz71y5UrsuemBDKNAUEbvG0AUyo7xMfAJ8InpuACmA+eBo4CP2bldgXOmV5fkjKcVSPLYs0fKypXj/nHq1VOzDWtx9apSHI6OarxcuaT85Rc1Y0kJ0YZoOXf/XFlwUsFYxVF2Wlk5Z/8cGRYZZjF5I6IjZOe1nSUjkQ7fOsg/z/xpsb41qSM9KZCkeJkUiL29sNolcVwCnydwbD4w3xpyvapER8PYsTB6NBgMUKQITJsG775r3XE9PWH6dPjsM+jdG7Ztgw8/VIb6WbMgb97Ez5dSsvn8ZgZuGcjR20cBqJy/Mt+8/g0tyrTAQVjW7cvF0YUFzReQ3z0/4wPG0+G3DuzvsZ9iOZMXfBVDNLAeyELivuyalCHtbOl89OgRderUiffYsmXLKFu2LKGhoURHR+Pk5ERwcDCFCsXrA5T+iU+rvKwvPQNJmKtXpfT3l7E2iX79pHz82PZyGI1Szp0rZbZsSpaCBaX877+E2x++eVi+tfit2BlHkSlF5LIjy6TBaLC6rAajQTZd1lQyElllZpVkz3KeSilnSCmLSfXDdJVSRlpPzFcCe9tA7t69K728vJLdvlWrVnL58uVSSil79uwpp0+fbi3RUkyGWcKy9UsrkPj57z8p8+aNu2Fv22ZviaS8fFnK2rWVTI6Oyh5jvqT1KOKR7Le5X6xRO/t32eXEgInyadRTm8p5/+l9WWJqCclI5Jd/fplo2wdSynFSynzyxR/nE2sL+pJjbwUipZTt2rWT5cuXT9KILqWU58+fl9WrV5clSpSQrVq1kuHh4TaQMHloBaIVSLKZOzfOiF2/ftoN2JYkMlLK/v1l7Bp0jx5q3++nf5deU7xibRBf/PGFvPvkrt3kPHjjoHT41kE6jXKSp++efuH4AynlGCllThn3Y6wipfxVSpnFtP3QduK+lKQHBfKykBIFko5igjW2REr49lvo1g2iolQsxqZNKtAvveDsDBMnwsqV4OoKs5dfx7NvK5oub8qVB1eoWqAqu7vt5qcmP+GR2cNuclbOX5kulbsQbYzm621fx+5/CIxFuRkOA+4DdYBNwH6gNXGBWNG2FFijsRAvfSCh5kUMBvjiC5g5U6UV+fln6NHD3lIlTOvWkpNOy/h27xfcdgvFIdqdMXXHMODNz3FySB8/4W/f/JZlR5ex5uQatl3bS1Ch6kxCKQ1QiuNbVA4e82xDjqa/BtuJqtFYjPTx36exGQYDdOkCS5aoNCLLl0OLFvaWKmHuPLnDp398ypqTa8ANMl1twtNVM1m2rjBdtkD+dBIMXihbIT7zG8AkYyRv534tdkaRkOKIIeYfUCsQTUZEK5BXCIMBOneGpUshSxb44w944w17S5Uw60+tp8fGHtx+cpusLln54e0faJinCw0CBMeOQb16sGNH0m6+1iYKmAv88uYIEA5EA1UiHjHJNWuCiiOGmBmIXsLSZES0DeQVwWiErl2V8nB3V/aO9Ko8nkQ+ofuG7rRY2YLbT27zZtE3OfLpEbpW6Yqnp+Dff1V235MnVWLGe/fsI6cRWAmUAz4DbgkH8oVehsVvUWvrYOqSuPIAvYSlydhoBfIKICX07QuLF6uZx6ZNULu2vaWKn8M3D+Mzx4e5B+fi6ujKD41+YFunbRTNUTS2TZ48sHUrvPYaHDkCDRvCo0e2lXMLUB1oi0qFUBpYBWwKD4WL21h+bBlPo54m2Y9WIJqMjFYgrwBjxsDUqeDiAuvWgb+/vSV6ESkl0/ZMo+bcmpy6e4pyecqxt/teetfqHW8keb58KmK9eHGV5bdVK1WDxNrsBd4CGgIHgIKoVM/HgVZA5fzeVCtQjdDwUNadWpdkf9oL6+UgJhtvcrl48SI1a9akZMmStGnThsh4frx79uyhcuXKVK5cGW9vb9auXRt7rGvXruTNm5cKFSo8c86AAQMoU6YMlSpVomXLloSGhgJw6dIlMmXKFNvfJ598kroP+jzx+fa+rK9XMQ5kwQIZm6hwzRp7SxM/IWEhstnyZrHR5D1/7ymfRCYvtO7cubggyI4dU54/K7mclVK2knE/phxSBQXGJ+WMPTMkI5H1F9VPst/Spv5OWk7UVxJ7x4GkJBeWlFK2bt36mUj0GTNmvNDmyZMnsRl7r1+/LvPkyRO7/b///U/u37//hTE3b94c22bgwIFy4MCBKZZPx4FoANi+Hbp3V++nTYP33rOvPPFx4MYBqs2uxobTG8jhloNVrVcx892ZZHbOnKzzS5RQzgBZsijPshEjLCvffaAvys6xGnADBgIXgEFAfFK2q9gONyc3tl3cxqXQS4n2r5ewXg4GDx7M+fPnqVy5MgMGDEi0rZSS7du306pVKwA6d+7MunXrXmiXOXNmnJzUHDU8PPyZcrOvv/46uXLleuGchg0bxp5Tq1YtgoODU/uRkoX2wnpJOXUK3n9fJUjs1w/SY62aeQfm8fmfnxNhiMCnoA+rWq96xtaRXHx8YNUqlfRx9GhVNrdt27TJFgX8jHLBvYcyhncBRgGeSZybwy0H75V9j2VHl7Hi2AoG1x6cYFu9hGV5xLfWqY0uRyScpXHcuHEcO3aMQ4cO8ejRIypXrhxvu2XLlpE3b15y5MgRe6P39PTk2rVr8bbfvXs3Xbt25fLlyyxZsiT2nOQwf/582rRpE7t98eJFqlSpQrZs2RgzZkyCCR9TglYgLyEPHqhysaGhKsZj/Hh7S/Qs4dHhfPHnF8w7OA+AHlV7MLXxVNycUl/ftnFjmDwZvvpKxbkULw41aqS8HwlsBPoDZ0z76gKTgCop6Kf5a81ZdnQZf5//O1EFomcgLx9Zs2bl0KFDCR6/e/dusvuqWbMmx48f5+TJk3Tu3JnGjRvjlow60GPHjsXJyYkOHToAUKBAAa5cuYKHhwf79++nRYsWHD9+nGzZsiVblvjQCuQlw2iEDh3gzBmoWFEt6zg6Jn2erbh4/yKtVrXiwI0DuDm58fM7P/NR5Y8s0nevXnD8OMyZAy1bwoEDytieXA4D/YBtpu1SwPdAU5J2x32e+sXqIxAEXA0gLCoswSU5rUAsT2IzBVtgjXTuZcuWxd3dnWPHjuHj45No24ULF7Jx40a2bdsWu+zl6uqKq6srANWqVaNEiRKcOXMmyb6SQiuQl4yRI5VNIFcu5XHl7m5vieL46+xfdPiLine truncated
},
"metadata": {
"needs_background": "light"
}
}
],
"metadata": {}
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"metadata": {},
"source": [ "source": [
"This nicely shows the shock developing in the center of our domain, which forms from the collision of the two initial velocity \"bumps\", the positive one on left (moving right) and the negative one right of the center (moving left).\n", "This nicely shows the shock developing in the center of our domain, which forms from the collision of the two initial velocity \"bumps\", the positive one on left (moving right) and the negative one right of the center (moving left).\n",
"\n", "\n",
"As these lines can overlap quite a bit we'll also use a different visualization in the following chapters that shows the evolution over the course of all time steps in a 2D image. Our 1D domain will be shown along the Y-axis, and each point along X will represent one time step.\n", "As these lines can overlap quite a bit we'll also use a different visualization in the following chapters that shows the evolution over the course of all time steps in a 2D image. Our 1D domain will be shown along the Y-axis, and each point along X will represent one time step.\n",
"\n", "\n",
"The code below converts our collection of velocity states into a 2D array, repeating individual time steps 8 times to make the image a bit wider. This is purely optional, of course, but makes it easier to see what's happening in our Burgers simulation." "The code below converts our collection of velocity states into a 2D array, repeating individual time steps 8 times to make the image a bit wider. This is purely optional, of course, but makes it easier to see what's happening in our Burgers simulation."
] ],
"metadata": {}
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 6, "execution_count": 6,
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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 truncated
"text/plain": [
"<Figure size 1152x360 with 2 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [ "source": [
"def show_state(a, title):\n", "def show_state(a, title):\n",
" # we only have 33 time steps, blow up by a factor of 2^4 to make it easier to see\n", " # we only have 33 time steps, blow up by a factor of 2^4 to make it easier to see\n",
@@ -265,18 +250,32 @@
"np.savez_compressed(\"./temp/burgers-groundtruth-solution.npz\", np.reshape(vels_img,[N,STEPS+1])) # remove batch & channel dimension\n", "np.savez_compressed(\"./temp/burgers-groundtruth-solution.npz\", np.reshape(vels_img,[N,STEPS+1])) # remove batch & channel dimension\n",
"\n", "\n",
"show_state(vels_img, \"Velocity\")" "show_state(vels_img, \"Velocity\")"
] ],
"outputs": [
{
"output_type": "display_data",
"data": {
"text/plain": [
"<Figure size 1152x360 with 2 Axes>"
],
"image/png": "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 truncated
},
"metadata": {
"needs_background": "light"
}
}
],
"metadata": {}
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"metadata": {},
"source": [ "source": [
"This concludes a first simulation in phiflow. It's not overly complex, but because of that it's a good starting point for evaluating and comparing different physics-based deep learning approaches in the next chapter. But before that, we'll target a more complex simulation type in the next section." "This concludes a first simulation in phiflow. It's not overly complex, but because of that it's a good starting point for evaluating and comparing different physics-based deep learning approaches in the next chapter. But before that, we'll target a more complex simulation type in the next section."
] ],
"metadata": {}
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"metadata": {},
"source": [ "source": [
"## Next steps\n", "## Next steps\n",
"\n", "\n",
@@ -285,7 +284,8 @@
"- Feel free to experiment - the setup above is very simple, you can change the simulation parameters, or the initialization. E.g., you can use a noise field via `Noise()` to get more chaotic results (cf. the comment in the `velocity` cell above).\n", "- Feel free to experiment - the setup above is very simple, you can change the simulation parameters, or the initialization. E.g., you can use a noise field via `Noise()` to get more chaotic results (cf. the comment in the `velocity` cell above).\n",
"\n", "\n",
"- A bit more complicated: extend the simulation to 2D (or higher). This will require changes throughout, but all operators above support higher dimensions. Before trying this, you probably will want to check out the next example, which covers a 2D Navier-Stokes case." "- A bit more complicated: extend the simulation to 2D (or higher). This will require changes throughout, but all operators above support higher dimensions. Before trying this, you probably will want to check out the next example, which covers a 2D Navier-Stokes case."
] ],
"metadata": {}
} }
], ],
"metadata": { "metadata": {
@@ -309,4 +309,4 @@
}, },
"nbformat": 4, "nbformat": 4,
"nbformat_minor": 4 "nbformat_minor": 4
} }
+4 -3
View File
@@ -27,7 +27,7 @@ $$
$$ (learn-l2) $$ (learn-l2)
We typically optimize, i.e. _train_, We typically optimize, i.e. _train_,
with a stochastic gradient descent (SGD) optimizer of your choice, e.g. Adam {cite}`kingma2014adam`. with a stochastic gradient descent (SGD) optimizer of choice, e.g. Adam {cite}`kingma2014adam`.
We'll rely on auto-diff to compute the gradient w.r.t. weights, $\partial f / \partial \theta$, We'll rely on auto-diff to compute the gradient w.r.t. weights, $\partial f / \partial \theta$,
We will also assume that $e$ denotes a _scalar_ error function (also We will also assume that $e$ denotes a _scalar_ error function (also
called cost, or objective function). called cost, or objective function).
@@ -39,7 +39,7 @@ introduce scalar loss, always(!) scalar... (also called *cost* or *objective* f
For training we distinguish: the **training** data set drawn from some distribution, For training we distinguish: the **training** data set drawn from some distribution,
the **validation** set (from the same distribution, but different data), the **validation** set (from the same distribution, but different data),
and **test** data sets with _some_ different distribution than the training one. and **test** data sets with _some_ different distribution than the training one.
The latter distinction is important! For the test set we want The latter distinction is important. For the test set we want
_out of distribution_ (OOD) data to check how well our trained model generalizes. _out of distribution_ (OOD) data to check how well our trained model generalizes.
Note that this gives a huge range of possibilities for the test data set: Note that this gives a huge range of possibilities for the test data set:
from tiny changes that will certainly work, from tiny changes that will certainly work,
@@ -131,7 +131,8 @@ and the abbreviations used in: {doc}`notation`.
We solve a discretized PDE $\mathcal{P}$ by performing steps of size $\Delta t$. We solve a discretized PDE $\mathcal{P}$ by performing steps of size $\Delta t$.
The solution can be expressed as a function of $\mathbf{u}$ and its derivatives: The solution can be expressed as a function of $\mathbf{u}$ and its derivatives:
$\mathbf{u}(\mathbf{x},t+\Delta t) = $\mathbf{u}(\mathbf{x},t+\Delta t) =
\mathcal{P}(\mathbf{u}(\mathbf{x},t), \mathbf{u}(\mathbf{x},t)',\mathbf{u}(\mathbf{x},t)'',...)$. \mathcal{P}( \mathbf{u}_{x}, \mathbf{u}_{xx}, ... \mathbf{u}_{xx...x} )$, where
$\mathbf{u}_{x}$ denotes the spatial derivatives $\partial \mathbf{u}(\mathbf{x},t) / \partial \mathbf{x}$.
For all PDEs, we will assume non-dimensional parametrizations as outlined below, For all PDEs, we will assume non-dimensional parametrizations as outlined below,
which could be re-scaled to real world quantities with suitable scaling factors. which could be re-scaled to real world quantities with suitable scaling factors.
+230 -230
View File
@@ -2,13 +2,10 @@
"cells": [ "cells": [
{ {
"cell_type": "markdown", "cell_type": "markdown",
"metadata": {
"id": "o4JZ84moBKMr"
},
"source": [ "source": [
"# Navier-Stokes Forward Simulation\n", "# Navier-Stokes Forward Simulation\n",
"\n", "\n",
"Now let's target a somewhat more complex example: a fluid simulation based on the Navier-Stokes equations. This is still very simple with Φ<sub>Flow</sub> (phiflow), as differentiable operators for all steps exist. The Navier-Stokes equations (in their incompressible form) introduce an additional pressure field $p$, and a constraint for conservation of mass, as introduced in equation {eq}`model-boussinesq2d`. We're also moving a marker field, denoted by $d$ here, with the flow. It indicates regions of higher temperature, and exerts a force via a buouyancy factor $\\xi$:\n", "Now let's target a somewhat more complex example: a fluid simulation based on the Navier-Stokes equations. This is still very simple with Φ<sub>Flow</sub> (phiflow), as differentiable operators for all steps exist there. The Navier-Stokes equations (in their incompressible form) introduce an additional pressure field $p$, and a constraint for conservation of mass, as introduced in equation {eq}`model-boussinesq2d`. We're also moving a marker field, denoted by $d$ here, with the flow. It indicates regions of higher temperature, and exerts a force via a buouyancy factor $\\xi$:\n",
"\n", "\n",
"$$\\begin{aligned}\n", "$$\\begin{aligned}\n",
" \\frac{\\partial \\mathbf{u}}{\\partial{t}} + \\mathbf{u} \\cdot \\nabla \\mathbf{u} &= - \\frac{1}{\\rho} \\nabla p + \\nu \\nabla\\cdot \\nabla \\mathbf{u} + (0,1)^T \\xi d\n", " \\frac{\\partial \\mathbf{u}}{\\partial{t}} + \\mathbf{u} \\cdot \\nabla \\mathbf{u} &= - \\frac{1}{\\rho} \\nabla p + \\nu \\nabla\\cdot \\nabla \\mathbf{u} + (0,1)^T \\xi d\n",
@@ -22,137 +19,101 @@
"We'll solve this PDE on a closed domain with Dirichlet boundary conditions $\\mathbf{u}=0$ for the velocity, and Neumann boundaries $\\frac{\\partial p}{\\partial x}=0$ for pressure, on a domain $\\Omega$ with a physical size of $100 \\times 80$ units. \n", "We'll solve this PDE on a closed domain with Dirichlet boundary conditions $\\mathbf{u}=0$ for the velocity, and Neumann boundaries $\\frac{\\partial p}{\\partial x}=0$ for pressure, on a domain $\\Omega$ with a physical size of $100 \\times 80$ units. \n",
"[[run in colab]](https://colab.research.google.com/github/tum-pbs/pbdl-book/blob/main/overview-ns-forw.ipynb)\n", "[[run in colab]](https://colab.research.google.com/github/tum-pbs/pbdl-book/blob/main/overview-ns-forw.ipynb)\n",
"\n" "\n"
] ],
"metadata": {
"id": "o4JZ84moBKMr"
}
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"metadata": {},
"source": [ "source": [
"## Implementation\n", "## Implementation\n",
"\n", "\n",
"As in the previous section, the first command with a \"!\" prefix installs the [phiflow python package from GitHub](https://github.com/tum-pbs/PhiFlow) via `pip` in your python environment. (Skip or modify this command if necessary.)" "As in the previous section, the first command with a \"!\" prefix installs the [phiflow python package from GitHub](https://github.com/tum-pbs/PhiFlow) via `pip` in your python environment. (Skip or modify this command if necessary.)"
] ],
"metadata": {}
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 1, "execution_count": 1,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "da1uZcDXdVcF",
"outputId": "1082dc87-796c-4b57-e72e-5790fc1444c9"
},
"outputs": [],
"source": [ "source": [
"#!pip install --upgrade --quiet phiflow \n", "#!pip install --upgrade --quiet phiflow \n",
"!pip install --upgrade --quiet git+https://github.com/tum-pbs/PhiFlow@develop\n", "!pip install --upgrade --quiet git+https://github.com/tum-pbs/PhiFlow@develop\n",
"\n", "\n",
"from phi.flow import * # The Dash GUI is not supported on Google colab, ignore the warning\n", "from phi.flow import * # The Dash GUI is not supported on Google colab, ignore the warning\n",
"import pylab" "import pylab"
] ],
"outputs": [],
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "da1uZcDXdVcF",
"outputId": "1082dc87-796c-4b57-e72e-5790fc1444c9"
}
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"metadata": {
"id": "BVV1IKVqDfLl"
},
"source": [ "source": [
"## Setting up the simulation\n", "## Setting up the simulation\n",
"\n", "\n",
"The following code sets up a few constants, which are denoted by upper case names. We'll use $40\\times32$ cells to discretize our domain, introduce a slight viscosity via $\\nu$, and define the time step to be $\\Delta t=1.5$. \n", "The following code sets up a few constants, which are denoted by upper case names. We'll use $40\\times32$ cells to discretize our domain, introduce a slight viscosity via $\\nu$, and define the time step to be $\\Delta t=1.5$. \n",
"\n", "\n",
"We're creating a first `CenteredGrid` here, which is initialized by a `Sphere` geometry object. This will represent the inflow region `INFLOW` where hot smoke is generated." "We're creating a first `CenteredGrid` here, which is initialized by a `Sphere` geometry object. This will represent the inflow region `INFLOW` where hot smoke is generated."
] ],
"metadata": {
"id": "BVV1IKVqDfLl"
}
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 2, "execution_count": 2,
"metadata": {
"id": "WrA3IXDxv31P"
},
"outputs": [],
"source": [ "source": [
"DT = 1.5\n", "DT = 1.5\n",
"NU = 0.01\n", "NU = 0.01\n",
"\n", "\n",
"INFLOW = CenteredGrid(Sphere(center=(30,15), radius=10), extrapolation.BOUNDARY, x=32, y=40, bounds=Box[0:80, 0:100]) * 0.2\n" "INFLOW = CenteredGrid(Sphere(center=(30,15), radius=10), extrapolation.BOUNDARY, x=32, y=40, bounds=Box[0:80, 0:100]) * 0.2\n"
] ],
"outputs": [],
"metadata": {
"id": "WrA3IXDxv31P"
}
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"metadata": {
"id": "ExA0Pi2sFVka"
},
"source": [ "source": [
"The inflow will be used to inject smoke into a second centered grid `smoke` that represents the marker field $d$ from above. Note that we've defined a `Box` of size $100x80$ above. This is the physical scale in terms of spatial units in our simulation, i.e., a velocity of magnitude $1$ will move the smoke density by 1 unit per 1 time unit, which may be larger or smaller than a cell in the discretized grid, depending on the settings for `x,y`. You could parametrize your simulation grid to directly resemble real-world units, or keep appropriate conversion factors in mind. \n", "The inflow will be used to inject smoke into a second centered grid `smoke` that represents the marker field $d$ from above. Note that we've defined a `Box` of size $100x80$ above. This is the physical scale in terms of spatial units in our simulation, i.e., a velocity of magnitude $1$ will move the smoke density by 1 unit per 1 time unit, which may be larger or smaller than a cell in the discretized grid, depending on the settings for `x,y`. You could parametrize your simulation grid to directly resemble real-world units, or keep appropriate conversion factors in mind. \n",
"\n", "\n",
"The inflow sphere above is already using the \"world\" coordinates: it is located at $x=30$ along the first axis, and $y=15$ (within the $100x80$ domain box).\n", "The inflow sphere above is already using the \"world\" coordinates: it is located at $x=30$ along the first axis, and $y=15$ (within the $100x80$ domain box).\n",
"\n", "\n",
"Next, we create grids for the quantities we want to simulate. For this example, we require a velocity field and a smoke density field." "Next, we create grids for the quantities we want to simulate. For this example, we require a velocity field and a smoke density field."
] ],
"metadata": {
"id": "ExA0Pi2sFVka"
}
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 3, "execution_count": 3,
"metadata": {},
"outputs": [],
"source": [ "source": [
"smoke = CenteredGrid(0, extrapolation.BOUNDARY, x=32, y=40, bounds=Box[0:80, 0:100]) # sampled at cell centers\n", "smoke = CenteredGrid(0, extrapolation.BOUNDARY, x=32, y=40, bounds=Box[0:80, 0:100]) # sampled at cell centers\n",
"velocity = StaggeredGrid(0, extrapolation.ZERO, x=32, y=40, bounds=Box[0:80, 0:100]) # sampled in staggered form at face centers " "velocity = StaggeredGrid(0, extrapolation.ZERO, x=32, y=40, bounds=Box[0:80, 0:100]) # sampled in staggered form at face centers "
] ],
"outputs": [],
"metadata": {}
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"metadata": {},
"source": [ "source": [
"We sample the smoke field at the cell centers and the velocity in [staggered form](https://tum-pbs.github.io/PhiFlow/Staggered_Grids.html). The staggered grid internally contains 2 centered grids with different dimensions, and can be converted into centered grids (or simply numpy arrays) via the `unstack` function, as explained in the link above.\n", "We sample the smoke field at the cell centers and the velocity in [staggered form](https://tum-pbs.github.io/PhiFlow/Staggered_Grids.html). The staggered grid internally contains 2 centered grids with different dimensions, and can be converted into centered grids (or simply numpy arrays) via the `unstack` function, as explained in the link above.\n",
"\n", "\n",
"Next we define the update step of the simulation, which calls the necessary functions to advance the state of our fluid system by `dt`. The next cell computes one such step, and plots the marker density after one simulation frame." "Next we define the update step of the simulation, which calls the necessary functions to advance the state of our fluid system by `dt`. The next cell computes one such step, and plots the marker density after one simulation frame."
] ],
"metadata": {}
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 4, "execution_count": 4,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 282
},
"id": "WmGZdOwswOva",
"outputId": "3ae4d68d-b586-4bbe-eca9-a223d7720949"
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Max. velocity and mean marker density: [0.15530995, 0.008125]\n"
]
},
{
"data": {
"text/plain": [
"<matplotlib.image.AxesImage at 0x7fa2f8d16eb0>"
]
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
},
{
"data": {
"image/png": "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\n",
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [ "source": [
"def step(velocity, smoke, pressure, dt=1.0, buoyancy_factor=1.0):\n", "def step(velocity, smoke, pressure, dt=1.0, buoyancy_factor=1.0):\n",
" smoke = advect.semi_lagrangian(smoke, velocity, dt) + INFLOW\n", " smoke = advect.semi_lagrangian(smoke, velocity, dt) + INFLOW\n",
@@ -167,11 +128,49 @@
"print(\"Max. velocity and mean marker density: \" + format( [ math.max(velocity.values) , math.mean(smoke.values) ] ))\n", "print(\"Max. velocity and mean marker density: \" + format( [ math.max(velocity.values) , math.mean(smoke.values) ] ))\n",
"\n", "\n",
"pylab.imshow(np.asarray(smoke.values.numpy('y,x')), origin='lower', cmap='magma')" "pylab.imshow(np.asarray(smoke.values.numpy('y,x')), origin='lower', cmap='magma')"
] ],
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"text": [
"Max. velocity and mean marker density: [0.15530995, 0.008125]\n"
]
},
{
"output_type": "execute_result",
"data": {
"text/plain": [
"<matplotlib.image.AxesImage at 0x7fa2f8d16eb0>"
]
},
"metadata": {},
"execution_count": 4
},
{
"output_type": "display_data",
"data": {
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
],
"image/png": "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"
},
"metadata": {
"needs_background": "light"
}
}
],
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 282
},
"id": "WmGZdOwswOva",
"outputId": "3ae4d68d-b586-4bbe-eca9-a223d7720949"
}
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"metadata": {},
"source": [ "source": [
"A lot has happened in this `step()` call: we've advected the smoke field, added an upwards force via a Boussinesq model, advected the velocity field, and finally made it divergence free via a pressure solve.\n", "A lot has happened in this `step()` call: we've advected the smoke field, added an upwards force via a Boussinesq model, advected the velocity field, and finally made it divergence free via a pressure solve.\n",
"\n", "\n",
@@ -187,16 +186,21 @@
"The variables we created for the fields of the simulation here are instances of the class `Grid`.\n", "The variables we created for the fields of the simulation here are instances of the class `Grid`.\n",
"Like tensors, grids also have the `shape` attribute which lists all batch, spatial and channel dimensions.\n", "Like tensors, grids also have the `shape` attribute which lists all batch, spatial and channel dimensions.\n",
"[Shapes in phiflow](https://tum-pbs.github.io/PhiFlow/Math.html#shapes) store not only the sizes of the dimensions but also their names and types." "[Shapes in phiflow](https://tum-pbs.github.io/PhiFlow/Math.html#shapes) store not only the sizes of the dimensions but also their names and types."
] ],
"metadata": {}
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 5, "execution_count": 5,
"metadata": {}, "source": [
"print(f\"Smoke: {smoke.shape}\")\n",
"print(f\"Velocity: {velocity.shape}\")\n",
"print(f\"Inflow: {INFLOW.shape}, spatial only: {INFLOW.shape.spatial}\")\n"
],
"outputs": [ "outputs": [
{ {
"name": "stdout",
"output_type": "stream", "output_type": "stream",
"name": "stdout",
"text": [ "text": [
"Smoke: (xˢ=32, yˢ=40)\n", "Smoke: (xˢ=32, yˢ=40)\n",
"Velocity: (xˢ=32, yˢ=40, vectorᵛ=2)\n", "Velocity: (xˢ=32, yˢ=40, vectorᵛ=2)\n",
@@ -204,63 +208,46 @@
] ]
} }
], ],
"source": [ "metadata": {}
"print(f\"Smoke: {smoke.shape}\")\n",
"print(f\"Velocity: {velocity.shape}\")\n",
"print(f\"Inflow: {INFLOW.shape}, spatial only: {INFLOW.shape.spatial}\")\n"
]
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"metadata": {},
"source": [ "source": [
"Note that the phiflow output here indicates the type of a dimension, e.g., $^S$ for a spatial, and $^V$ for a vector dimension. Later on for learning, we'll also introduce batch dimensions.\n", "Note that the phiflow output here indicates the type of a dimension, e.g., $^S$ for a spatial, and $^V$ for a vector dimension. Later on for learning, we'll also introduce batch dimensions.\n",
"\n", "\n",
"The actual content of a shape object can be obtained via `.sizes`, or alternatively we can query the size of a specific dimension `dim` via `.get_size('dim')`. Here are two examples:" "The actual content of a shape object can be obtained via `.sizes`, or alternatively we can query the size of a specific dimension `dim` via `.get_size('dim')`. Here are two examples:"
] ],
"metadata": {}
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 6, "execution_count": 6,
"metadata": {}, "source": [
"print(f\"Shape content: {velocity.shape.sizes}\")\n",
"print(f\"Vector dimension: {velocity.shape.get_size('vector')}\")"
],
"outputs": [ "outputs": [
{ {
"name": "stdout",
"output_type": "stream", "output_type": "stream",
"name": "stdout",
"text": [ "text": [
"Shape content: (32, 40, 2)\n", "Shape content: (32, 40, 2)\n",
"Vector dimension: 2\n" "Vector dimension: 2\n"
] ]
} }
], ],
"source": [ "metadata": {}
"print(f\"Shape content: {velocity.shape.sizes}\")\n",
"print(f\"Vector dimension: {velocity.shape.get_size('vector')}\")"
]
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"metadata": {},
"source": [ "source": [
"The grid values can be accessed using the `values` property. This is an important difference to a phiflow tensor object, which does not have `values`, as illustrated in the code example below." "The grid values can be accessed using the `values` property. This is an important difference to a phiflow tensor object, which does not have `values`, as illustrated in the code example below."
] ],
"metadata": {}
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 7, "execution_count": 7,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Statistics of the different simulation grids:\n",
"(xˢ=32, yˢ=40) float32 0.0 < ... < 0.20000000298023224\n",
"(xˢ=(31, 32), yˢ=(40, 39), vectorᵛ=2) float32 -0.12352858483791351 < ... < 0.15530994534492493\n",
"Reordered test tensor shape: (3, 5, 2)\n"
]
}
],
"source": [ "source": [
"print(\"Statistics of the different simulation grids:\")\n", "print(\"Statistics of the different simulation grids:\")\n",
"print(smoke.values)\n", "print(smoke.values)\n",
@@ -270,39 +257,50 @@
"test_tensor = math.tensor(numpy.zeros([2, 5, 3]), spatial('x,y'), channel('vector'))\n", "test_tensor = math.tensor(numpy.zeros([2, 5, 3]), spatial('x,y'), channel('vector'))\n",
"print(\"Reordered test tensor shape: \" + format(test_tensor.numpy('vector,y,x').shape) )\n", "print(\"Reordered test tensor shape: \" + format(test_tensor.numpy('vector,y,x').shape) )\n",
"#print(test_tensor.values.numpy('y,x')) # error! tensors don't return their content via \".values\"\n" "#print(test_tensor.values.numpy('y,x')) # error! tensors don't return their content via \".values\"\n"
] ],
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"text": [
"Statistics of the different simulation grids:\n",
"(xˢ=32, yˢ=40) float32 0.0 < ... < 0.20000000298023224\n",
"(xˢ=(31, 32), yˢ=(40, 39), vectorᵛ=2) float32 -0.12352858483791351 < ... < 0.15530994534492493\n",
"Reordered test tensor shape: (3, 5, 2)\n"
]
}
],
"metadata": {}
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"metadata": {},
"source": [ "source": [
"Grids have many more properties which are documented [here](https://tum-pbs.github.io/PhiFlow/phi/field/#phi.field.Grid).\n", "Grids have many more properties which are documented [here](https://tum-pbs.github.io/PhiFlow/phi/field/#phi.field.Grid).\n",
"Also note that the staggered grid has a [non-uniform shape](https://tum-pbs.github.io/PhiFlow/Math.html#non-uniform-tensors) because the number of faces is not equal to the number of cells (in this example the x component has $31 \\times 40$ cells, while y has $32 \\times 39$). The `INFLOW` grid naturally has the same dimensions as the `smoke` grid.\n" "Also note that the staggered grid has a [non-uniform shape](https://tum-pbs.github.io/PhiFlow/Math.html#non-uniform-tensors) because the number of faces is not equal to the number of cells (in this example the x component has $31 \\times 40$ cells, while y has $32 \\times 39$). The `INFLOW` grid naturally has the same dimensions as the `smoke` grid.\n"
] ],
"metadata": {}
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"metadata": {},
"source": [ "source": [
"## Time evolution\n", "## Time evolution\n",
"\n", "\n",
"With this setup, we can easily advance the simulation forward in time a bit more by repeatedly calling the `step` function." "With this setup, we can easily advance the simulation forward in time a bit more by repeatedly calling the `step` function."
] ],
"metadata": {}
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 8, "execution_count": 8,
"metadata": { "source": [
"colab": { "for time_step in range(10):\n",
"base_uri": "https://localhost:8080/" " velocity, smoke, pressure = step(velocity, smoke, pressure, dt=DT)\n",
}, " print('Computed frame {}, max velocity {}'.format(time_step , np.asarray(math.max(velocity.values)) ))\n"
"id": "0hZk5HX3w4Or", ],
"outputId": "f7811af7-4b58-4ff6-a8b6-6e7bedefaa6e"
},
"outputs": [ "outputs": [
{ {
"name": "stdout",
"output_type": "stream", "output_type": "stream",
"name": "stdout",
"text": [ "text": [
"Computed frame 0, max velocity 0.4609803557395935\n", "Computed frame 0, max velocity 0.4609803557395935\n",
"Computed frame 1, max velocity 0.8926814794540405\n", "Computed frame 1, max velocity 0.8926814794540405\n",
@@ -317,24 +315,53 @@
] ]
} }
], ],
"source": [ "metadata": {
"for time_step in range(10):\n", "colab": {
" velocity, smoke, pressure = step(velocity, smoke, pressure, dt=DT)\n", "base_uri": "https://localhost:8080/"
" print('Computed frame {}, max velocity {}'.format(time_step , np.asarray(math.max(velocity.values)) ))\n" },
] "id": "0hZk5HX3w4Or",
"outputId": "f7811af7-4b58-4ff6-a8b6-6e7bedefaa6e"
}
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"metadata": {
"id": "GMKKWQBLHIwP"
},
"source": [ "source": [
"Now the hot plume is starting to rise:" "Now the hot plume is starting to rise:"
] ],
"metadata": {
"id": "GMKKWQBLHIwP"
}
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 9, "execution_count": 9,
"source": [
"pylab.imshow(smoke.values.numpy('y,x'), origin='lower', cmap='magma')"
],
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": [
"<matplotlib.image.AxesImage at 0x7fa2f902cf40>"
]
},
"metadata": {},
"execution_count": 9
},
{
"output_type": "display_data",
"data": {
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
],
"image/png": "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 truncated
},
"metadata": {
"needs_background": "light"
}
}
],
"metadata": { "metadata": {
"colab": { "colab": {
"base_uri": "https://localhost:8080/", "base_uri": "https://localhost:8080/",
@@ -342,79 +369,20 @@
}, },
"id": "Mfl80CjZxZcL", "id": "Mfl80CjZxZcL",
"outputId": "92f3a9ba-d403-4799-a543-132ee8ed234c" "outputId": "92f3a9ba-d403-4799-a543-132ee8ed234c"
}, }
"outputs": [
{
"data": {
"text/plain": [
"<matplotlib.image.AxesImage at 0x7fa2f902cf40>"
]
},
"execution_count": 9,
"metadata": {},
"output_type": "execute_result"
},
{
"data": {
"image/png": "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 truncated
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [
"pylab.imshow(smoke.values.numpy('y,x'), origin='lower', cmap='magma')"
]
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"metadata": {
"id": "wnbQJvA-HPSL"
},
"source": [ "source": [
"Let's compute and show a few more steps of the simulation. Because of the inflow being located off-center to the left (with x position 30), the plume will curve towards the right when it hits the top wall of the domain." "Let's compute and show a few more steps of the simulation. Because of the inflow being located off-center to the left (with x position 30), the plume will curve towards the right when it hits the top wall of the domain."
] ],
"metadata": {
"id": "wnbQJvA-HPSL"
}
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 10, "execution_count": 10,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 489
},
"id": "tkhCOzc0ITsj",
"outputId": "f6366c12-1eb5-4ff6-e0d7-94b806bfd8e4"
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Computing time step 0\n",
"Computing time step 1\n",
"Computing time step 2\n",
"Computing time step 10\n"
]
},
{
"data": {
"image/png": "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 truncated
"text/plain": [
"<Figure size 1152x360 with 5 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [ "source": [
"steps = [[ smoke.values, velocity.values.vector[0], velocity.values.vector[1] ]]\n", "steps = [[ smoke.values, velocity.values.vector[0], velocity.values.vector[1] ]]\n",
"for time_step in range(20):\n", "for time_step in range(20):\n",
@@ -428,45 +396,50 @@
"for i in range(len(steps)):\n", "for i in range(len(steps)):\n",
" axes[i].imshow(steps[i][0].numpy('y,x'), origin='lower', cmap='magma')\n", " axes[i].imshow(steps[i][0].numpy('y,x'), origin='lower', cmap='magma')\n",
" axes[i].set_title(f\"d at t={i*5}\")" " axes[i].set_title(f\"d at t={i*5}\")"
] ],
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"text": [
"Computing time step 0\n",
"Computing time step 1\n",
"Computing time step 2\n",
"Computing time step 10\n"
]
},
{
"output_type": "display_data",
"data": {
"text/plain": [
"<Figure size 1152x360 with 5 Axes>"
],
"image/png": "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 truncated
},
"metadata": {
"needs_background": "light"
}
}
],
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 489
},
"id": "tkhCOzc0ITsj",
"outputId": "f6366c12-1eb5-4ff6-e0d7-94b806bfd8e4"
}
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"metadata": {},
"source": [ "source": [
"We can also take a look at the velocities. The `steps` list above already stores `vector[0]` and `vector[1]` components of the velocities as numpy arrays, which we can show next." "We can also take a look at the velocities. The `steps` list above already stores `vector[0]` and `vector[1]` components of the velocities as numpy arrays, which we can show next."
] ],
"metadata": {}
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 11, "execution_count": 11,
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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 truncated
"text/plain": [
"<Figure size 1152x360 with 5 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
},
{
"data": {
"image/png": "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 truncated
"text/plain": [
"<Figure size 1152x360 with 5 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [ "source": [
"fig, axes = pylab.subplots(1, len(steps), figsize=(16, 5))\n", "fig, axes = pylab.subplots(1, len(steps), figsize=(16, 5))\n",
"for i in range(len(steps)):\n", "for i in range(len(steps)):\n",
@@ -478,27 +451,54 @@
" axes[i].imshow(steps[i][2].numpy('y,x'), origin='lower', cmap='magma')\n", " axes[i].imshow(steps[i][2].numpy('y,x'), origin='lower', cmap='magma')\n",
" axes[i].set_title(f\"u_y at t={i*5}\")\n", " axes[i].set_title(f\"u_y at t={i*5}\")\n",
" " " "
] ],
"outputs": [
{
"output_type": "display_data",
"data": {
"text/plain": [
"<Figure size 1152x360 with 5 Axes>"
],
"image/png": "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 truncated
},
"metadata": {
"needs_background": "light"
}
},
{
"output_type": "display_data",
"data": {
"text/plain": [
"<Figure size 1152x360 with 5 Axes>"
],
"image/png": "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 truncated
},
"metadata": {
"needs_background": "light"
}
}
],
"metadata": {}
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"metadata": {
"id": "ooqVxCPM8PXl"
},
"source": [ "source": [
"It looks simple here, but this simulation setup is a powerful tool. The simulation could easily be extended to more complex cases or 3D, and it is already fully compatible with backpropagation pipelines of deep learning frameworks. \n", "It looks simple here, but this simulation setup is a powerful tool. The simulation could easily be extended to more complex cases or 3D, and it is already fully compatible with backpropagation pipelines of deep learning frameworks. \n",
"\n", "\n",
"In the next chapters we'll show how to use these simulations for training NNs, and how to steer and modify them via trained NNs. This will illustrate how much we can improve the training process by having a solver in the loop, especially when the solver is _differentiable_. Before moving to these more complex training processes, we will cover a simpler supervised approach in the next chapter. This is very fundamental: even when aiming for advanced physics-based learning setups, a working supervised training is always the first step." "In the next chapters we'll show how to use these simulations for training NNs, and how to steer and modify them via trained NNs. This will illustrate how much we can improve the training process by having a solver in the loop, especially when the solver is _differentiable_. Before moving to these more complex training processes, we will cover a simpler supervised approach in the next chapter. This is very fundamental: even when aiming for advanced physics-based learning setups, a working supervised training is always the first step."
] ],
"metadata": {
"id": "ooqVxCPM8PXl"
}
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"metadata": {},
"source": [ "source": [
"## Next steps\n", "## Next steps\n",
"\n", "\n",
"You could create a variety of nice fluid simulations based on this setup. E.g., try changing the spatial resolution, the buoyancy factors, and the overall length of the simulation run." "You could create a variety of nice fluid simulations based on this setup. E.g., try changing the spatial resolution, the buoyancy factors, and the overall length of the simulation run."
] ],
"metadata": {}
} }
], ],
"metadata": { "metadata": {
@@ -527,4 +527,4 @@
}, },
"nbformat": 4, "nbformat": 4,
"nbformat_minor": 1 "nbformat_minor": 1
} }
+13 -13
View File
@@ -66,12 +66,13 @@ as the Navier-Stokes, Maxwell's, or Schroedinger's equations.
Seemingly trivial changes to the discretization can determine Seemingly trivial changes to the discretization can determine
whether key phenomena are visible in the solutions or not. whether key phenomena are visible in the solutions or not.
Rather than discarding the powerful methods that have been Rather than discarding the powerful methods that have been
developed in the field of numerical mathematics, it developed in the field of numerical mathematics, this book will
is highly beneficial for DL to use them as much as possible. show that it is highly beneficial to use them as much as possible
when applying DL.
### Black boxes and magic? ### Black boxes and magic?
People who are unfamiliear with DL methods often associate neural networks People who are unfamiliar with DL methods often associate neural networks
with _black boxes_, and see the training processes as something that is beyond the grasp with _black boxes_, and see the training processes as something that is beyond the grasp
of human understanding. However, these viewpoints typically stem from of human understanding. However, these viewpoints typically stem from
relying on hearsay and not dealing with the topic enough. relying on hearsay and not dealing with the topic enough.
@@ -81,10 +82,10 @@ and "all the gritty details" are not yet fully worked out. However, this is pret
for scientific advances. for scientific advances.
Numerical methods themselves are a good example. Around 1950, numerical approximations Numerical methods themselves are a good example. Around 1950, numerical approximations
and solvers had a tough standing. E.g., to cite H. Goldstine, and solvers had a tough standing. E.g., to cite H. Goldstine,
numerical instabilies were considered to be a "constant source of numerical instabilities were considered to be a "constant source of
anxiety in the future" {cite}`goldstine1990history`. anxiety in the future" {cite}`goldstine1990history`.
By now we have a pretty good grasp of these instabilities, and numerical methods By now we have a pretty good grasp of these instabilities, and numerical methods
are ubiquitous, and well established. are ubiquitous and well established.
Thus, it is important to be aware of the fact that -- in a way -- there is nothing Thus, it is important to be aware of the fact that -- in a way -- there is nothing
magical or otherworldly to deep learning methods. They're simply another set of magical or otherworldly to deep learning methods. They're simply another set of
@@ -142,8 +143,8 @@ the most crucial differentiation for the following topics lies in the
nature of the integration between DL techniques nature of the integration between DL techniques
and the domain knowledge, typically in the form of model equations and the domain knowledge, typically in the form of model equations
via partial differential equations (PDEs). via partial differential equations (PDEs).
Taking a global perspective, the following three categories can be The following three categories can be
identified to categorize _physics-based deep learning_ (PBDL) identified to roughly categorize _physics-based deep learning_ (PBDL)
techniques: techniques:
- _Supervised_: the data is produced by a physical system (real or simulated), - _Supervised_: the data is produced by a physical system (real or simulated),
@@ -162,12 +163,11 @@ techniques:
temporal evolutions, where they can yield an estimate of the future behavior of the temporal evolutions, where they can yield an estimate of the future behavior of the
dynamics. dynamics.
Thus, methods can be roughly categorized in terms of forward versus inverse Thus, methods can be categorized in terms of forward versus inverse
solve, and how tightly the physical model is integrated into the solve, and how tightly the physical model is integrated into the
optimization loop that trains the deep neural network. Here, especially optimization loop that trains the deep neural network. Here, especially
the interleaved approaches interleaved approaches that leverage _differentiable physics_ allow for
that leverage _differentiable physics_ allow for very tight integration very tight integration of deep learning and numerical simulation methods.
of deep learning and numerical simulation methods.
## Looking ahead ## Looking ahead
@@ -176,8 +176,8 @@ _Physical simulations_ are a huge field, and we won't be able to cover all possi
```{note} Rather, the focus of this book lies on: ```{note} Rather, the focus of this book lies on:
- _Field-based simulations_ (no Lagrangian methods) - _Field-based simulations_ (no Lagrangian methods)
- Combinations with _deep learning_ (plenty of other interesting ML techniques, but not here) - Combinations with _deep learning_ (plenty of other interesting ML techniques exist, but won't be discussed here)
- Experiments as _outlook_ (i.e., replace synthetic data with real-world observations) - Experiments are left as an _outlook_ (i.e., replacing synthetic data with real-world observations)
``` ```
It's also worth noting that we're starting to build the methods from some very It's also worth noting that we're starting to build the methods from some very
+1 -1
View File
@@ -33,7 +33,7 @@
"In terms of the $x,y^*$ notation from {doc}`overview-equations` and the previous section, this reconstruction problem means we are solving\n", "In terms of the $x,y^*$ notation from {doc}`overview-equations` and the previous section, this reconstruction problem means we are solving\n",
"\n", "\n",
"$$\n", "$$\n",
"\\text{arg min}_{\\theta} \\sum_i |f(x_i ; \\theta)-y^*_i|^2 + R(x_i) ,\n", "\\text{arg min}_{\\theta} \\sum_i ( f(x_i ; \\theta)-y^*_i )^2 + R(x_i) ,\n",
"$$\n", "$$\n",
"\n", "\n",
"where $x$ and $y^*$ are solutions of $u$ at different locations in space and time. As we're dealing with a 1D velocity, $x,y^* \\in \\mathbb{R}$.\n", "where $x$ and $y^*$ are solutions of $u$ at different locations in space and time. As we're dealing with a 1D velocity, $x,y^* \\in \\mathbb{R}$.\n",
+7 -6
View File
@@ -3,7 +3,7 @@ Physical Loss Terms
The supervised setting of the previous sections can quickly The supervised setting of the previous sections can quickly
yield approximate solutions with a fairly simple training process. However, what's yield approximate solutions with a fairly simple training process. However, what's
quite sad to see here is that we only use physical models and numerics quite sad to see here is that we only use physical models and numerical methods
as an "external" tool to produce a big pile of data 😢. as an "external" tool to produce a big pile of data 😢.
We as humans have a lot of knowledge about how to describe physical processes We as humans have a lot of knowledge about how to describe physical processes
@@ -29,16 +29,17 @@ $$
$$ $$
where the $_{\mathbf{x}}$ subscripts denote spatial derivatives with respect to one of the spatial dimensions where the $_{\mathbf{x}}$ subscripts denote spatial derivatives with respect to one of the spatial dimensions
of higher and higher order (this can of course also include mixed derivatives with respect to different axes). of higher and higher order (this can of course also include mixed derivatives with respect to different axes). \mathbf{u}_t denotes the changes over time.
In this context, we can approximate the unknown u itself with a neural network. If the approximation, which we call $\tilde{\mathbf{u}}$, is accurate, the PDE should be satisfied naturally. In other words, the residual R should be equal to zero: In this context, we can approximate the unknown $\mathbf{u}$ itself with a neural network. If the approximation, which we call $\tilde{\mathbf{u}}$, is accurate, the PDE should be satisfied naturally. In other words, the residual R should be equal to zero:
$$ $$
R = \mathbf{u}_t - \mathcal F ( \mathbf{u}_{x}, \mathbf{u}_{xx}, ... \mathbf{u}_{xx...x} ) = 0 . R = \mathbf{u}_t - \mathcal F ( \mathbf{u}_{x}, \mathbf{u}_{xx}, ... \mathbf{u}_{xx...x} ) = 0 .
$$ $$
This nicely integrates with the objective for training a neural network: similar to before This nicely integrates with the objective for training a neural network: we can train for
we can collect sample solutions minimizing this residual in combination with direct loss terms.
Similar to before, we can make use of sample solutions
$[x_0,y_0], ...[x_n,y_n]$ for $\mathbf{u}$ with $\mathbf{u}(\mathbf{x})=y$. $[x_0,y_0], ...[x_n,y_n]$ for $\mathbf{u}$ with $\mathbf{u}(\mathbf{x})=y$.
This is typically important, as most practical PDEs we encounter do not have unique solutions This is typically important, as most practical PDEs we encounter do not have unique solutions
unless initial and boundary conditions are specified. Hence, if we only consider $R$ we might unless initial and boundary conditions are specified. Hence, if we only consider $R$ we might
@@ -47,7 +48,7 @@ therefore help to _pin down_ the solution in certain places.
Now our training objective becomes Now our training objective becomes
$$ $$
\text{arg min}_{\theta} \ \alpha_0 \sum_i (f(x_i ; \theta)-y_i)^2 + \alpha_1 R(x_i) , \text{arg min}_{\theta} \ \alpha_0 \sum_i \big( f(x_i ; \theta)-y_i \big)^2 + \alpha_1 R(x_i) ,
$$ (physloss-training) $$ (physloss-training)
where $\alpha_{0,1}$ denote hyperparameters that scale the contribution of the supervised term and where $\alpha_{0,1}$ denote hyperparameters that scale the contribution of the supervised term and
+1 -1
View File
@@ -36,7 +36,7 @@
"With the supervised formulation from {doc}`supervised`, our learning task is pretty straight-forward, and can be written as \n", "With the supervised formulation from {doc}`supervised`, our learning task is pretty straight-forward, and can be written as \n",
"\n", "\n",
"$$\\begin{aligned}\n", "$$\\begin{aligned}\n",
"\\text{arg min}_{\\theta} \\sum_i |f(x_i ; \\theta)-y^*_i|^2 ,\n", "\\text{arg min}_{\\theta} \\sum_i ( f(x_i ; \\theta)-y^*_i )^2 ,\n",
"\\end{aligned}$$\n", "\\end{aligned}$$\n",
"\n", "\n",
"where $x$ and $y^*$ each consist of a set of physical fields,\n", "where $x$ and $y^*$ each consist of a set of physical fields,\n",
+4 -4
View File
@@ -92,8 +92,8 @@ models at training time later on, the NNs just adjust their weights to represent
they receive, and reproduce it. they receive, and reproduce it.
Due to the hype and numerous success stories, people not familiar with DL often have Due to the hype and numerous success stories, people not familiar with DL often have
the impression that DL works like a human mind, and is able to detect fundamental the impression that DL works like a human mind, and is able to extract fundamental
and general principles in data sets (["messages from god"](https://dilbert.com/strip/2000-01-03) anyone?). and general principles from data sets (["messages from god"](https://dilbert.com/strip/2000-01-03) anyone?).
That's not what happens with the current state of the art. Nonetheless, it's That's not what happens with the current state of the art. Nonetheless, it's
the most powerful tool we have to approximate complex, non-linear functions. the most powerful tool we have to approximate complex, non-linear functions.
It is a great tool, but it's important to keep in mind, that once we set up the training It is a great tool, but it's important to keep in mind, that once we set up the training
@@ -119,8 +119,8 @@ As a rule of thumb: make sure you actually train the NN on the
inputs that are as similar as possible to those you want to use at inference time. inputs that are as similar as possible to those you want to use at inference time.
This is important to keep in mind during the next chapters: e.g., if we This is important to keep in mind during the next chapters: e.g., if we
want an NN to work in conjunction with another solver or simulation environment, want an NN to work in conjunction with a certain simulation environment,
it's important to actually bring the solver into the training process, otherwise it's important to actually include the simulator in the training process. Otherwise,
the network might specialize on pre-computed data that differs from what is produced the network might specialize on pre-computed data that differs from what is produced
when combining the NN with the solver, i.e it will suffer from _distribution shift_. when combining the NN with the solver, i.e it will suffer from _distribution shift_.
+2 -2
View File
@@ -78,5 +78,5 @@ is a very attractive and interesting direction.
## Show me some code! ## Show me some code!
Let's directly look at an example for this: we'll replace a full solver for Let's finally look at a code example that trains a neural network:
_turbulent flows around airfoils_ with a surrogate model from {cite}`thuerey2020dfp`. we'll replace a full solver for _turbulent flows around airfoils_ with a surrogate model from {cite}`thuerey2020dfp`.