Skip to content

Commit 379c427

Browse files
committed
tutorial11 - Equation Class
1 parent 481bf76 commit 379c427

File tree

4 files changed

+541
-1
lines changed

4 files changed

+541
-1
lines changed

docs/source/_rst/_tutorial.rst

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@ Physics Informed Neural Networks
2121
Two dimensional Poisson problem using Extra Features Learning<tutorials/tutorial2/tutorial.rst>
2222
Two dimensional Wave problem with hard constraint<tutorials/tutorial3/tutorial.rst>
2323
Resolution of a 2D Poisson inverse problem<tutorials/tutorial7/tutorial.rst>
24-
Periodic Boundary Conditions for Helmotz Equation<tutorials/tutorial9/tutorial.rst>
24+
Periodic Boundary Conditions for Helmholtz Equation<tutorials/tutorial9/tutorial.rst>
25+
Building custom equations with PINA Equation class<tutorials/tutorial11/tutorial.rst>
2526

2627
Neural Operator Learning
2728
------------------------
Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
Tutorial: The ``Equation`` Class
2+
================================
3+
4+
In this tutorial, we will show how to use the ``Equation`` Class in
5+
PINA. Specifically, we will see how use the Class and its inherited
6+
classes to enforce residuals minimization in PINNs.
7+
8+
Example: The Burgers 1D equation
9+
================================
10+
11+
We will start implementing the viscous Burgers 1D problem Class,
12+
described as follows:
13+
14+
.. math::
15+
16+
17+
\begin{equation}
18+
\begin{cases}
19+
\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\\
20+
u(x,0) &= -\sin (\pi x)\\
21+
u(x,t) &= 0 \quad x = \pm 1\\
22+
\end{cases}
23+
\end{equation}
24+
25+
where we set $ :raw-latex:`\nu `= :raw-latex:`\frac{0.01}{\pi}`$.
26+
27+
In the class that models this problem we will see in action the
28+
``Equation`` class and one of its inherited classes, the ``FixedValue``
29+
class.
30+
31+
.. code:: ipython3
32+
33+
#useful imports
34+
from pina.problem import SpatialProblem, TimeDependentProblem
35+
from pina.equation import Equation, FixedValue, FixedGradient, FixedFlux
36+
from pina.geometry import CartesianDomain
37+
import torch
38+
from pina.operators import grad, laplacian
39+
from pina import Condition
40+
41+
42+
43+
.. code:: ipython3
44+
45+
class Burgers1D(TimeDependentProblem, SpatialProblem):
46+
47+
# define the burger equation
48+
def burger_equation(input_, output_):
49+
du = grad(output_, input_)
50+
ddu = grad(du, input_, components=['dudx'])
51+
return (
52+
du.extract(['dudt']) +
53+
output_.extract(['u'])*du.extract(['dudx']) -
54+
(0.01/torch.pi)*ddu.extract(['ddudxdx'])
55+
)
56+
57+
# define initial condition
58+
def initial_condition(input_, output_):
59+
u_expected = -torch.sin(torch.pi*input_.extract(['x']))
60+
return output_.extract(['u']) - u_expected
61+
62+
# assign output/ spatial and temporal variables
63+
output_variables = ['u']
64+
spatial_domain = CartesianDomain({'x': [-1, 1]})
65+
temporal_domain = CartesianDomain({'t': [0, 1]})
66+
67+
# problem condition statement
68+
conditions = {
69+
'gamma1': Condition(location=CartesianDomain({'x': -1, 't': [0, 1]}), equation=FixedValue(0.)),
70+
'gamma2': Condition(location=CartesianDomain({'x': 1, 't': [0, 1]}), equation=FixedValue(0.)),
71+
't0': Condition(location=CartesianDomain({'x': [-1, 1], 't': 0}), equation=Equation(initial_condition)),
72+
'D': Condition(location=CartesianDomain({'x': [-1, 1], 't': [0, 1]}), equation=Equation(burger_equation)),
73+
}
74+
75+
The ``Equation`` class takes as input a function (in this case it
76+
happens twice, with ``initial_condition`` and ``burger_equation``) which
77+
computes a residual of an equation, such as a PDE. In a problem class
78+
such as the one above, the ``Equation`` class with such a given input is
79+
passed as a parameter in the specified ``Condition``.
80+
81+
The ``FixedValue`` class takes as input a value of same dimensions of
82+
the output functions; this class can be used to enforced a fixed value
83+
for a specific condition, e.g. Dirichlet boundary conditions, as it
84+
happens for instance in our example.
85+
86+
Once the equations are set as above in the problem conditions, the PINN
87+
solver will aim to minimize the residuals described in each equation in
88+
the training phase.
89+
90+
Available classes of equations include also: - ``FixedGradient`` and
91+
``FixedFlux``: they work analogously to ``FixedValue`` class, where we
92+
can require a constant value to be enforced, respectively, on the
93+
gradient of the solution or the divergence of the solution; -
94+
``Laplace``: it can be used to enforce the laplacian of the solution to
95+
be zero; - ``SystemEquation``: we can enforce multiple conditions on the
96+
same subdomain through this class, passing a list of residual equations
97+
defined in the problem.
98+
99+
Defining a new Equation class
100+
=============================
101+
102+
``Equation`` classes can be also inherited to define a new class. As
103+
example, we can see how to rewrite the above problem introducing a new
104+
class ``Burgers1D``; during the class call, we can pass the viscosity
105+
parameter :math:`\nu`:
106+
107+
.. code:: ipython3
108+
109+
class Burgers1DEquation(Equation):
110+
111+
def __init__(self, nu = 0.):
112+
"""
113+
Burgers1D class. This class can be
114+
used to enforce the solution u to solve the viscous Burgers 1D Equation.
115+
116+
:param torch.float32 nu: the viscosity coefficient. Default value is set to 0.
117+
"""
118+
self.nu = nu
119+
120+
def equation(input_, output_):
121+
return grad(output_, input_, d='x') +\
122+
output_*grad(output_, input_, d='t') -\
123+
self.nu*laplacian(output_, input_, d='x')
124+
125+
126+
super().__init__(equation)
127+
128+
Now we can just pass the above class as input for the last condition,
129+
setting :math:`\nu= \frac{0.01}{\pi}`:
130+
131+
.. code:: ipython3
132+
133+
class Burgers1D(TimeDependentProblem, SpatialProblem):
134+
135+
# define initial condition
136+
def initial_condition(input_, output_):
137+
u_expected = -torch.sin(torch.pi*input_.extract(['x']))
138+
return output_.extract(['u']) - u_expected
139+
140+
# assign output/ spatial and temporal variables
141+
output_variables = ['u']
142+
spatial_domain = CartesianDomain({'x': [-1, 1]})
143+
temporal_domain = CartesianDomain({'t': [0, 1]})
144+
145+
# problem condition statement
146+
conditions = {
147+
'gamma1': Condition(location=CartesianDomain({'x': -1, 't': [0, 1]}), equation=FixedValue(0.)),
148+
'gamma2': Condition(location=CartesianDomain({'x': 1, 't': [0, 1]}), equation=FixedValue(0.)),
149+
't0': Condition(location=CartesianDomain({'x': [-1, 1], 't': 0}), equation=Equation(initial_condition)),
150+
'D': Condition(location=CartesianDomain({'x': [-1, 1], 't': [0, 1]}), equation=Burgers1DEquation(0.01/torch.pi)),
151+
}
152+
153+
What’s next?
154+
============
155+
156+
Congratulations on completing the ``Equation`` class tutorial of
157+
**PINA**! As we have seen, you can build new classes that inherits
158+
``Equation`` to store more complex equations, as the Burgers 1D
159+
equation, only requiring to pass the characteristic coefficients of the
160+
problem. From now on, you can: - define additional complex equation
161+
classes (e.g. ``SchrodingerEquation``, ``NavierStokeEquation``..) -
162+
define more ``FixedOperator`` (e.g. ``FixedCurl``)

0 commit comments

Comments
 (0)