Equation Class Tutorial (#287)
* Tutorial Equation 12 * .rst and readme fix for tutorial12 * small fix * modified rst --------- Co-authored-by: Dario Coscia <dariocoscia@Dario-Coscia.local>
This commit is contained in:
committed by
GitHub
parent
e2d000ab22
commit
7b86661c6e
@@ -10,9 +10,11 @@ Getting started with PINA
|
|||||||
:titlesonly:
|
:titlesonly:
|
||||||
|
|
||||||
Introduction to PINA for Physics Informed Neural Networks training <tutorials/tutorial1/tutorial.rst>
|
Introduction to PINA for Physics Informed Neural Networks training <tutorials/tutorial1/tutorial.rst>
|
||||||
|
Introduction to PINA Equation class <tutorials/tutorial12/tutorial.rst>
|
||||||
PINA and PyTorch Lightning, training tips and visualizations <tutorials/tutorial11/tutorial.rst>
|
PINA and PyTorch Lightning, training tips and visualizations <tutorials/tutorial11/tutorial.rst>
|
||||||
Building custom geometries with PINA Location class <tutorials/tutorial6/tutorial.rst>
|
Building custom geometries with PINA Location class <tutorials/tutorial6/tutorial.rst>
|
||||||
|
|
||||||
|
|
||||||
Physics Informed Neural Networks
|
Physics Informed Neural Networks
|
||||||
--------------------------------
|
--------------------------------
|
||||||
.. toctree::
|
.. toctree::
|
||||||
|
|||||||
162
docs/source/_rst/tutorials/tutorial12/tutorial.rst
Normal file
162
docs/source/_rst/tutorials/tutorial12/tutorial.rst
Normal file
@@ -0,0 +1,162 @@
|
|||||||
|
Tutorial: The ``Equation`` Class
|
||||||
|
================================
|
||||||
|
|
||||||
|
In this tutorial, we will show how to use the ``Equation`` Class in
|
||||||
|
PINA. Specifically, we will see how use the Class and its inherited
|
||||||
|
classes to enforce residuals minimization in PINNs.
|
||||||
|
|
||||||
|
Example: The Burgers 1D equation
|
||||||
|
--------------------------------
|
||||||
|
|
||||||
|
We will start implementing the viscous Burgers 1D problem Class,
|
||||||
|
described as follows:
|
||||||
|
|
||||||
|
.. math::
|
||||||
|
|
||||||
|
|
||||||
|
\begin{equation}
|
||||||
|
\begin{cases}
|
||||||
|
\frac{\partial u}{\partial t} + u \frac{\partial u}{\partial x} &= \nu \frac{\partial^2 u}{ \partial x^2}, \quad x\in(0,1), \quad t>0\\
|
||||||
|
u(x,0) &= -\sin (\pi x)\\
|
||||||
|
u(x,t) &= 0 \quad x = \pm 1\\
|
||||||
|
\end{cases}
|
||||||
|
\end{equation}
|
||||||
|
|
||||||
|
where we set :math:`\nu = \frac{0.01}{\pi}` .
|
||||||
|
|
||||||
|
In the class that models this problem we will see in action the
|
||||||
|
``Equation`` class and one of its inherited classes, the ``FixedValue``
|
||||||
|
class.
|
||||||
|
|
||||||
|
.. code:: ipython3
|
||||||
|
|
||||||
|
#useful imports
|
||||||
|
from pina.problem import SpatialProblem, TimeDependentProblem
|
||||||
|
from pina.equation import Equation, FixedValue, FixedGradient, FixedFlux
|
||||||
|
from pina.geometry import CartesianDomain
|
||||||
|
import torch
|
||||||
|
from pina.operators import grad, laplacian
|
||||||
|
from pina import Condition
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
.. code:: ipython3
|
||||||
|
|
||||||
|
class Burgers1D(TimeDependentProblem, SpatialProblem):
|
||||||
|
|
||||||
|
# define the burger equation
|
||||||
|
def burger_equation(input_, output_):
|
||||||
|
du = grad(output_, input_)
|
||||||
|
ddu = grad(du, input_, components=['dudx'])
|
||||||
|
return (
|
||||||
|
du.extract(['dudt']) +
|
||||||
|
output_.extract(['u'])*du.extract(['dudx']) -
|
||||||
|
(0.01/torch.pi)*ddu.extract(['ddudxdx'])
|
||||||
|
)
|
||||||
|
|
||||||
|
# define initial condition
|
||||||
|
def initial_condition(input_, output_):
|
||||||
|
u_expected = -torch.sin(torch.pi*input_.extract(['x']))
|
||||||
|
return output_.extract(['u']) - u_expected
|
||||||
|
|
||||||
|
# assign output/ spatial and temporal variables
|
||||||
|
output_variables = ['u']
|
||||||
|
spatial_domain = CartesianDomain({'x': [-1, 1]})
|
||||||
|
temporal_domain = CartesianDomain({'t': [0, 1]})
|
||||||
|
|
||||||
|
# problem condition statement
|
||||||
|
conditions = {
|
||||||
|
'gamma1': Condition(location=CartesianDomain({'x': -1, 't': [0, 1]}), equation=FixedValue(0.)),
|
||||||
|
'gamma2': Condition(location=CartesianDomain({'x': 1, 't': [0, 1]}), equation=FixedValue(0.)),
|
||||||
|
't0': Condition(location=CartesianDomain({'x': [-1, 1], 't': 0}), equation=Equation(initial_condition)),
|
||||||
|
'D': Condition(location=CartesianDomain({'x': [-1, 1], 't': [0, 1]}), equation=Equation(burger_equation)),
|
||||||
|
}
|
||||||
|
|
||||||
|
The ``Equation`` class takes as input a function (in this case it
|
||||||
|
happens twice, with ``initial_condition`` and ``burger_equation``) which
|
||||||
|
computes a residual of an equation, such as a PDE. In a problem class
|
||||||
|
such as the one above, the ``Equation`` class with such a given input is
|
||||||
|
passed as a parameter in the specified ``Condition``.
|
||||||
|
|
||||||
|
The ``FixedValue`` class takes as input a value of same dimensions of
|
||||||
|
the output functions; this class can be used to enforced a fixed value
|
||||||
|
for a specific condition, e.g. Dirichlet boundary conditions, as it
|
||||||
|
happens for instance in our example.
|
||||||
|
|
||||||
|
Once the equations are set as above in the problem conditions, the PINN
|
||||||
|
solver will aim to minimize the residuals described in each equation in
|
||||||
|
the training phase.
|
||||||
|
|
||||||
|
Available classes of equations include also: - ``FixedGradient`` and
|
||||||
|
``FixedFlux``: they work analogously to ``FixedValue`` class, where we
|
||||||
|
can require a constant value to be enforced, respectively, on the
|
||||||
|
gradient of the solution or the divergence of the solution; -
|
||||||
|
``Laplace``: it can be used to enforce the laplacian of the solution to
|
||||||
|
be zero; - ``SystemEquation``: we can enforce multiple conditions on the
|
||||||
|
same subdomain through this class, passing a list of residual equations
|
||||||
|
defined in the problem.
|
||||||
|
|
||||||
|
Defining a new Equation class
|
||||||
|
-----------------------------
|
||||||
|
|
||||||
|
``Equation`` classes can be also inherited to define a new class. As
|
||||||
|
example, we can see how to rewrite the above problem introducing a new
|
||||||
|
class ``Burgers1D``; during the class call, we can pass the viscosity
|
||||||
|
parameter :math:`\nu`:
|
||||||
|
|
||||||
|
.. code:: ipython3
|
||||||
|
|
||||||
|
class Burgers1DEquation(Equation):
|
||||||
|
|
||||||
|
def __init__(self, nu = 0.):
|
||||||
|
"""
|
||||||
|
Burgers1D class. This class can be
|
||||||
|
used to enforce the solution u to solve the viscous Burgers 1D Equation.
|
||||||
|
|
||||||
|
:param torch.float32 nu: the viscosity coefficient. Default value is set to 0.
|
||||||
|
"""
|
||||||
|
self.nu = nu
|
||||||
|
|
||||||
|
def equation(input_, output_):
|
||||||
|
return grad(output_, input_, d='x') +\
|
||||||
|
output_*grad(output_, input_, d='t') -\
|
||||||
|
self.nu*laplacian(output_, input_, d='x')
|
||||||
|
|
||||||
|
|
||||||
|
super().__init__(equation)
|
||||||
|
|
||||||
|
Now we can just pass the above class as input for the last condition,
|
||||||
|
setting :math:`\nu= \frac{0.01}{\pi}`:
|
||||||
|
|
||||||
|
.. code:: ipython3
|
||||||
|
|
||||||
|
class Burgers1D(TimeDependentProblem, SpatialProblem):
|
||||||
|
|
||||||
|
# define initial condition
|
||||||
|
def initial_condition(input_, output_):
|
||||||
|
u_expected = -torch.sin(torch.pi*input_.extract(['x']))
|
||||||
|
return output_.extract(['u']) - u_expected
|
||||||
|
|
||||||
|
# assign output/ spatial and temporal variables
|
||||||
|
output_variables = ['u']
|
||||||
|
spatial_domain = CartesianDomain({'x': [-1, 1]})
|
||||||
|
temporal_domain = CartesianDomain({'t': [0, 1]})
|
||||||
|
|
||||||
|
# problem condition statement
|
||||||
|
conditions = {
|
||||||
|
'gamma1': Condition(location=CartesianDomain({'x': -1, 't': [0, 1]}), equation=FixedValue(0.)),
|
||||||
|
'gamma2': Condition(location=CartesianDomain({'x': 1, 't': [0, 1]}), equation=FixedValue(0.)),
|
||||||
|
't0': Condition(location=CartesianDomain({'x': [-1, 1], 't': 0}), equation=Equation(initial_condition)),
|
||||||
|
'D': Condition(location=CartesianDomain({'x': [-1, 1], 't': [0, 1]}), equation=Burgers1DEquation(0.01/torch.pi)),
|
||||||
|
}
|
||||||
|
|
||||||
|
What’s next?
|
||||||
|
------------
|
||||||
|
|
||||||
|
Congratulations on completing the ``Equation`` class tutorial of
|
||||||
|
**PINA**! As we have seen, you can build new classes that inherits
|
||||||
|
``Equation`` to store more complex equations, as the Burgers 1D
|
||||||
|
equation, only requiring to pass the characteristic coefficients of the
|
||||||
|
problem. From now on, you can: - define additional complex equation
|
||||||
|
classes (e.g. ``SchrodingerEquation``, ``NavierStokeEquation``..) -
|
||||||
|
define more ``FixedOperator`` (e.g. ``FixedCurl``)
|
||||||
1
tutorials/README.md
vendored
1
tutorials/README.md
vendored
@@ -7,6 +7,7 @@ In this folder we collect useful tutorials in order to understand the principles
|
|||||||
| Description | Tutorial |
|
| Description | Tutorial |
|
||||||
|---------------|-----------|
|
|---------------|-----------|
|
||||||
Introduction to PINA for Physics Informed Neural Networks training|[[.ipynb](tutorial1/tutorial.ipynb), [.py](tutorial1/tutorial.py), [.html](http://mathlab.github.io/PINA/_rst/tutorials/tutorial1/tutorial.html)]|
|
Introduction to PINA for Physics Informed Neural Networks training|[[.ipynb](tutorial1/tutorial.ipynb), [.py](tutorial1/tutorial.py), [.html](http://mathlab.github.io/PINA/_rst/tutorials/tutorial1/tutorial.html)]|
|
||||||
|
Introduction to PINA `Equation` class|[[.ipynb](tutorial12/tutorial.ipynb), [.py](tutorial12/tutorial.py), [.html](http://mathlab.github.io/PINA/_rst/tutorials/tutorial12/tutorial.html)]|
|
||||||
PINA and PyTorch Lightning, training tips and visualizations|[[.ipynb](tutorial11/tutorial.ipynb), [.py](tutorial11/tutorial.py), [.html](http://mathlab.github.io/PINA/_rst/tutorials/tutorial11/tutorial.html)]|
|
PINA and PyTorch Lightning, training tips and visualizations|[[.ipynb](tutorial11/tutorial.ipynb), [.py](tutorial11/tutorial.py), [.html](http://mathlab.github.io/PINA/_rst/tutorials/tutorial11/tutorial.html)]|
|
||||||
Building custom geometries with PINA `Location` class|[[.ipynb](tutorial6/tutorial.ipynb), [.py](tutorial6/tutorial.py), [.html](http://mathlab.github.io/PINA/_rst/tutorials/tutorial6/tutorial.html)]|
|
Building custom geometries with PINA `Location` class|[[.ipynb](tutorial6/tutorial.ipynb), [.py](tutorial6/tutorial.py), [.html](http://mathlab.github.io/PINA/_rst/tutorials/tutorial6/tutorial.html)]|
|
||||||
|
|
||||||
|
|||||||
235
tutorials/tutorial12/tutorial.ipynb
vendored
Normal file
235
tutorials/tutorial12/tutorial.ipynb
vendored
Normal file
@@ -0,0 +1,235 @@
|
|||||||
|
{
|
||||||
|
"cells": [
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"# Tutorial: The `Equation` Class"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"In this tutorial, we will show how to use the `Equation` Class in PINA. Specifically, we will see how use the Class and its inherited classes to enforce residuals minimization in PINNs."
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"# Example: The Burgers 1D equation"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"We will start implementing the viscous Burgers 1D problem Class, described as follows:\n",
|
||||||
|
"\n",
|
||||||
|
"\n",
|
||||||
|
"$$\n",
|
||||||
|
"\\begin{equation}\n",
|
||||||
|
"\\begin{cases}\n",
|
||||||
|
"\\frac{\\partial u}{\\partial t} + u \\frac{\\partial u}{\\partial x} &= \\nu \\frac{\\partial^2 u}{ \\partial x^2}, \\quad x\\in(0,1), \\quad t>0\\\\\n",
|
||||||
|
"u(x,0) &= -\\sin (\\pi x)\\\\\n",
|
||||||
|
"u(x,t) &= 0 \\quad x = \\pm 1\\\\\n",
|
||||||
|
"\\end{cases}\n",
|
||||||
|
"\\end{equation}\n",
|
||||||
|
"$$\n",
|
||||||
|
"\n",
|
||||||
|
"where we set $ \\nu = \\frac{0.01}{\\pi}$.\n",
|
||||||
|
"\n",
|
||||||
|
"In the class that models this problem we will see in action the `Equation` class and one of its inherited classes, the `FixedValue` class. "
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 7,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"#useful imports\n",
|
||||||
|
"from pina.problem import SpatialProblem, TimeDependentProblem\n",
|
||||||
|
"from pina.equation import Equation, FixedValue, FixedGradient, FixedFlux\n",
|
||||||
|
"from pina.geometry import CartesianDomain\n",
|
||||||
|
"import torch\n",
|
||||||
|
"from pina.operators import grad, laplacian\n",
|
||||||
|
"from pina import Condition\n",
|
||||||
|
"\n"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 6,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"class Burgers1D(TimeDependentProblem, SpatialProblem):\n",
|
||||||
|
"\n",
|
||||||
|
" # define the burger equation\n",
|
||||||
|
" def burger_equation(input_, output_):\n",
|
||||||
|
" du = grad(output_, input_)\n",
|
||||||
|
" ddu = grad(du, input_, components=['dudx'])\n",
|
||||||
|
" return (\n",
|
||||||
|
" du.extract(['dudt']) +\n",
|
||||||
|
" output_.extract(['u'])*du.extract(['dudx']) -\n",
|
||||||
|
" (0.01/torch.pi)*ddu.extract(['ddudxdx'])\n",
|
||||||
|
" )\n",
|
||||||
|
"\n",
|
||||||
|
" # define initial condition\n",
|
||||||
|
" def initial_condition(input_, output_):\n",
|
||||||
|
" u_expected = -torch.sin(torch.pi*input_.extract(['x']))\n",
|
||||||
|
" return output_.extract(['u']) - u_expected\n",
|
||||||
|
"\n",
|
||||||
|
" # assign output/ spatial and temporal variables\n",
|
||||||
|
" output_variables = ['u']\n",
|
||||||
|
" spatial_domain = CartesianDomain({'x': [-1, 1]})\n",
|
||||||
|
" temporal_domain = CartesianDomain({'t': [0, 1]})\n",
|
||||||
|
"\n",
|
||||||
|
" # problem condition statement\n",
|
||||||
|
" conditions = {\n",
|
||||||
|
" 'gamma1': Condition(location=CartesianDomain({'x': -1, 't': [0, 1]}), equation=FixedValue(0.)),\n",
|
||||||
|
" 'gamma2': Condition(location=CartesianDomain({'x': 1, 't': [0, 1]}), equation=FixedValue(0.)),\n",
|
||||||
|
" 't0': Condition(location=CartesianDomain({'x': [-1, 1], 't': 0}), equation=Equation(initial_condition)),\n",
|
||||||
|
" 'D': Condition(location=CartesianDomain({'x': [-1, 1], 't': [0, 1]}), equation=Equation(burger_equation)),\n",
|
||||||
|
" }"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"\n",
|
||||||
|
"The `Equation` class takes as input a function (in this case it happens twice, with `initial_condition` and `burger_equation`) which computes a residual of an equation, such as a PDE. In a problem class such as the one above, the `Equation` class with such a given input is passed as a parameter in the specified `Condition`. \n",
|
||||||
|
"\n",
|
||||||
|
"The `FixedValue` class takes as input a value of same dimensions of the output functions; this class can be used to enforced a fixed value for a specific condition, e.g. Dirichlet boundary conditions, as it happens for instance in our example.\n",
|
||||||
|
"\n",
|
||||||
|
"Once the equations are set as above in the problem conditions, the PINN solver will aim to minimize the residuals described in each equation in the training phase. "
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"Available classes of equations include also:\n",
|
||||||
|
"- `FixedGradient` and `FixedFlux`: they work analogously to `FixedValue` class, where we can require a constant value to be enforced, respectively, on the gradient of the solution or the divergence of the solution;\n",
|
||||||
|
"- `Laplace`: it can be used to enforce the laplacian of the solution to be zero;\n",
|
||||||
|
"- `SystemEquation`: we can enforce multiple conditions on the same subdomain through this class, passing a list of residual equations defined in the problem.\n"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"# Defining a new Equation class"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"`Equation` classes can be also inherited to define a new class. As example, we can see how to rewrite the above problem introducing a new class `Burgers1D`; during the class call, we can pass the viscosity parameter $\\nu$:"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 13,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"class Burgers1DEquation(Equation):\n",
|
||||||
|
" \n",
|
||||||
|
" def __init__(self, nu = 0.):\n",
|
||||||
|
" \"\"\"\n",
|
||||||
|
" Burgers1D class. This class can be\n",
|
||||||
|
" used to enforce the solution u to solve the viscous Burgers 1D Equation.\n",
|
||||||
|
" \n",
|
||||||
|
" :param torch.float32 nu: the viscosity coefficient. Default value is set to 0.\n",
|
||||||
|
" \"\"\"\n",
|
||||||
|
" self.nu = nu \n",
|
||||||
|
" \n",
|
||||||
|
" def equation(input_, output_):\n",
|
||||||
|
" return grad(output_, input_, d='x') +\\\n",
|
||||||
|
" output_*grad(output_, input_, d='t') -\\\n",
|
||||||
|
" self.nu*laplacian(output_, input_, d='x')\n",
|
||||||
|
"\n",
|
||||||
|
" \n",
|
||||||
|
" super().__init__(equation)"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"Now we can just pass the above class as input for the last condition, setting $\\nu= \\frac{0.01}{\\pi}$:"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 14,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"class Burgers1D(TimeDependentProblem, SpatialProblem):\n",
|
||||||
|
"\n",
|
||||||
|
" # define initial condition\n",
|
||||||
|
" def initial_condition(input_, output_):\n",
|
||||||
|
" u_expected = -torch.sin(torch.pi*input_.extract(['x']))\n",
|
||||||
|
" return output_.extract(['u']) - u_expected\n",
|
||||||
|
"\n",
|
||||||
|
" # assign output/ spatial and temporal variables\n",
|
||||||
|
" output_variables = ['u']\n",
|
||||||
|
" spatial_domain = CartesianDomain({'x': [-1, 1]})\n",
|
||||||
|
" temporal_domain = CartesianDomain({'t': [0, 1]})\n",
|
||||||
|
"\n",
|
||||||
|
" # problem condition statement\n",
|
||||||
|
" conditions = {\n",
|
||||||
|
" 'gamma1': Condition(location=CartesianDomain({'x': -1, 't': [0, 1]}), equation=FixedValue(0.)),\n",
|
||||||
|
" 'gamma2': Condition(location=CartesianDomain({'x': 1, 't': [0, 1]}), equation=FixedValue(0.)),\n",
|
||||||
|
" 't0': Condition(location=CartesianDomain({'x': [-1, 1], 't': 0}), equation=Equation(initial_condition)),\n",
|
||||||
|
" 'D': Condition(location=CartesianDomain({'x': [-1, 1], 't': [0, 1]}), equation=Burgers1DEquation(0.01/torch.pi)),\n",
|
||||||
|
" }"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"# What's next?"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"Congratulations on completing the `Equation` class tutorial of **PINA**! As we have seen, you can build new classes that inherits `Equation` to store more complex equations, as the Burgers 1D equation, only requiring to pass the characteristic coefficients of the problem. \n",
|
||||||
|
"From now on, you can:\n",
|
||||||
|
"- define additional complex equation classes (e.g. `SchrodingerEquation`, `NavierStokeEquation`..)\n",
|
||||||
|
"- define more `FixedOperator` (e.g. `FixedCurl`)"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"metadata": {
|
||||||
|
"kernelspec": {
|
||||||
|
"display_name": "pina",
|
||||||
|
"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.1.0"
|
||||||
|
},
|
||||||
|
"orig_nbformat": 4
|
||||||
|
},
|
||||||
|
"nbformat": 4,
|
||||||
|
"nbformat_minor": 2
|
||||||
|
}
|
||||||
142
tutorials/tutorial12/tutorial.py
vendored
Normal file
142
tutorials/tutorial12/tutorial.py
vendored
Normal file
@@ -0,0 +1,142 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
# coding: utf-8
|
||||||
|
|
||||||
|
# # Tutorial: The `Equation` Class
|
||||||
|
|
||||||
|
# In this tutorial, we will show how to use the `Equation` Class in PINA. Specifically, we will see how use the Class and its inherited classes to enforce residuals minimization in PINNs.
|
||||||
|
|
||||||
|
# # Example: The Burgers 1D equation
|
||||||
|
|
||||||
|
# We will start implementing the viscous Burgers 1D problem Class, described as follows:
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# $$
|
||||||
|
# \begin{equation}
|
||||||
|
# \begin{cases}
|
||||||
|
# \frac{\partial u}{\partial t} + u \frac{\partial u}{\partial x} &= \nu \frac{\partial^2 u}{ \partial x^2}, \quad x\in(0,1), \quad t>0\\
|
||||||
|
# u(x,0) &= -\sin (\pi x)\\
|
||||||
|
# u(x,t) &= 0 \quad x = \pm 1\\
|
||||||
|
# \end{cases}
|
||||||
|
# \end{equation}
|
||||||
|
# $$
|
||||||
|
#
|
||||||
|
# where we set $ \nu = \frac{0.01}{\pi}$.
|
||||||
|
#
|
||||||
|
# In the class that models this problem we will see in action the `Equation` class and one of its inherited classes, the `FixedValue` class.
|
||||||
|
|
||||||
|
# In[7]:
|
||||||
|
|
||||||
|
|
||||||
|
#useful imports
|
||||||
|
from pina.problem import SpatialProblem, TimeDependentProblem
|
||||||
|
from pina.equation import Equation, FixedValue, FixedGradient, FixedFlux
|
||||||
|
from pina.geometry import CartesianDomain
|
||||||
|
import torch
|
||||||
|
from pina.operators import grad, laplacian
|
||||||
|
from pina import Condition
|
||||||
|
|
||||||
|
|
||||||
|
# In[6]:
|
||||||
|
|
||||||
|
|
||||||
|
class Burgers1D(TimeDependentProblem, SpatialProblem):
|
||||||
|
|
||||||
|
# define the burger equation
|
||||||
|
def burger_equation(input_, output_):
|
||||||
|
du = grad(output_, input_)
|
||||||
|
ddu = grad(du, input_, components=['dudx'])
|
||||||
|
return (
|
||||||
|
du.extract(['dudt']) +
|
||||||
|
output_.extract(['u'])*du.extract(['dudx']) -
|
||||||
|
(0.01/torch.pi)*ddu.extract(['ddudxdx'])
|
||||||
|
)
|
||||||
|
|
||||||
|
# define initial condition
|
||||||
|
def initial_condition(input_, output_):
|
||||||
|
u_expected = -torch.sin(torch.pi*input_.extract(['x']))
|
||||||
|
return output_.extract(['u']) - u_expected
|
||||||
|
|
||||||
|
# assign output/ spatial and temporal variables
|
||||||
|
output_variables = ['u']
|
||||||
|
spatial_domain = CartesianDomain({'x': [-1, 1]})
|
||||||
|
temporal_domain = CartesianDomain({'t': [0, 1]})
|
||||||
|
|
||||||
|
# problem condition statement
|
||||||
|
conditions = {
|
||||||
|
'gamma1': Condition(location=CartesianDomain({'x': -1, 't': [0, 1]}), equation=FixedValue(0.)),
|
||||||
|
'gamma2': Condition(location=CartesianDomain({'x': 1, 't': [0, 1]}), equation=FixedValue(0.)),
|
||||||
|
't0': Condition(location=CartesianDomain({'x': [-1, 1], 't': 0}), equation=Equation(initial_condition)),
|
||||||
|
'D': Condition(location=CartesianDomain({'x': [-1, 1], 't': [0, 1]}), equation=Equation(burger_equation)),
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# The `Equation` class takes as input a function (in this case it happens twice, with `initial_condition` and `burger_equation`) which computes a residual of an equation, such as a PDE. In a problem class such as the one above, the `Equation` class with such a given input is passed as a parameter in the specified `Condition`.
|
||||||
|
#
|
||||||
|
# The `FixedValue` class takes as input a value of same dimensions of the output functions; this class can be used to enforced a fixed value for a specific condition, e.g. Dirichlet boundary conditions, as it happens for instance in our example.
|
||||||
|
#
|
||||||
|
# Once the equations are set as above in the problem conditions, the PINN solver will aim to minimize the residuals described in each equation in the training phase.
|
||||||
|
|
||||||
|
# Available classes of equations include also:
|
||||||
|
# - `FixedGradient` and `FixedFlux`: they work analogously to `FixedValue` class, where we can require a constant value to be enforced, respectively, on the gradient of the solution or the divergence of the solution;
|
||||||
|
# - `Laplace`: it can be used to enforce the laplacian of the solution to be zero;
|
||||||
|
# - `SystemEquation`: we can enforce multiple conditions on the same subdomain through this class, passing a list of residual equations defined in the problem.
|
||||||
|
#
|
||||||
|
|
||||||
|
# # Defining a new Equation class
|
||||||
|
|
||||||
|
# `Equation` classes can be also inherited to define a new class. As example, we can see how to rewrite the above problem introducing a new class `Burgers1D`; during the class call, we can pass the viscosity parameter $\nu$:
|
||||||
|
|
||||||
|
# In[13]:
|
||||||
|
|
||||||
|
|
||||||
|
class Burgers1DEquation(Equation):
|
||||||
|
|
||||||
|
def __init__(self, nu = 0.):
|
||||||
|
"""
|
||||||
|
Burgers1D class. This class can be
|
||||||
|
used to enforce the solution u to solve the viscous Burgers 1D Equation.
|
||||||
|
|
||||||
|
:param torch.float32 nu: the viscosity coefficient. Default value is set to 0.
|
||||||
|
"""
|
||||||
|
self.nu = nu
|
||||||
|
|
||||||
|
def equation(input_, output_):
|
||||||
|
return grad(output_, input_, d='x') + output_*grad(output_, input_, d='t') - self.nu*laplacian(output_, input_, d='x')
|
||||||
|
|
||||||
|
|
||||||
|
super().__init__(equation)
|
||||||
|
|
||||||
|
|
||||||
|
# Now we can just pass the above class as input for the last condition, setting $\nu= \frac{0.01}{\pi}$:
|
||||||
|
|
||||||
|
# In[14]:
|
||||||
|
|
||||||
|
|
||||||
|
class Burgers1D(TimeDependentProblem, SpatialProblem):
|
||||||
|
|
||||||
|
# define initial condition
|
||||||
|
def initial_condition(input_, output_):
|
||||||
|
u_expected = -torch.sin(torch.pi*input_.extract(['x']))
|
||||||
|
return output_.extract(['u']) - u_expected
|
||||||
|
|
||||||
|
# assign output/ spatial and temporal variables
|
||||||
|
output_variables = ['u']
|
||||||
|
spatial_domain = CartesianDomain({'x': [-1, 1]})
|
||||||
|
temporal_domain = CartesianDomain({'t': [0, 1]})
|
||||||
|
|
||||||
|
# problem condition statement
|
||||||
|
conditions = {
|
||||||
|
'gamma1': Condition(location=CartesianDomain({'x': -1, 't': [0, 1]}), equation=FixedValue(0.)),
|
||||||
|
'gamma2': Condition(location=CartesianDomain({'x': 1, 't': [0, 1]}), equation=FixedValue(0.)),
|
||||||
|
't0': Condition(location=CartesianDomain({'x': [-1, 1], 't': 0}), equation=Equation(initial_condition)),
|
||||||
|
'D': Condition(location=CartesianDomain({'x': [-1, 1], 't': [0, 1]}), equation=Burgers1DEquation(0.01/torch.pi)),
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# # What's next?
|
||||||
|
|
||||||
|
# Congratulations on completing the `Equation` class tutorial of **PINA**! As we have seen, you can build new classes that inherits `Equation` to store more complex equations, as the Burgers 1D equation, only requiring to pass the characteristic coefficients of the problem.
|
||||||
|
# From now on, you can:
|
||||||
|
# - define additional complex equation classes (e.g. `SchrodingerEquation`, `NavierStokeEquation`..)
|
||||||
|
# - define more `FixedOperator` (e.g. `FixedCurl`)
|
||||||
Reference in New Issue
Block a user