-
Notifications
You must be signed in to change notification settings - Fork 103
Expand file tree
/
Copy pathtutorial.py
More file actions
209 lines (151 loc) · 5.66 KB
/
tutorial.py
File metadata and controls
209 lines (151 loc) · 5.66 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
#!/usr/bin/env python
# coding: utf-8
# # Tutorial: Two dimensional Darcy flow using the Fourier Neural Operator
#
# [](https://colab.research.google.com/github/mathLab/PINA/blob/master/tutorials/tutorial5/tutorial.ipynb)
#
# In this tutorial we are going to solve the Darcy flow problem in two dimensions, presented in [*Fourier Neural Operator for
# Parametric Partial Differential Equation*](https://openreview.net/pdf?id=c8P9NQVtmnO). First of all we import the modules needed for the tutorial. Importing `scipy` is needed for input-output operations.
# In[ ]:
## routine needed to run the notebook on Google Colab
try:
import google.colab
IN_COLAB = True
except:
IN_COLAB = False
if IN_COLAB:
get_ipython().system('pip install "pina-mathlab"')
get_ipython().system('pip install scipy')
# get the data
get_ipython().system('wget https://github.com/mathLab/PINA/raw/refs/heads/master/tutorials/tutorial5/Data_Darcy.mat')
import torch
import matplotlib.pyplot as plt
import warnings
# !pip install scipy # install scipy
from scipy import io
from pina.model import FNO, FeedForward # let's import some models
from pina import Condition, Trainer
from pina.solver import SupervisedSolver
from pina.problem.zoo import SupervisedProblem
warnings.filterwarnings("ignore")
# ## Data Generation
#
# We will focus on solving a specific PDE, the **Darcy Flow** equation. The Darcy PDE is a second-order elliptic PDE with the following form:
#
# $$
# -\nabla\cdot(k(x, y)\nabla u(x, y)) = f(x) \quad (x, y) \in D.
# $$
#
# Specifically, $u$ is the flow pressure, $k$ is the permeability field and $f$ is the forcing function. The Darcy flow can parameterize a variety of systems including flow through porous media, elastic materials and heat conduction. Here you will define the domain as a 2D unit square Dirichlet boundary conditions. The dataset is taken from the authors original reference.
#
# In[2]:
# download the dataset
data = io.loadmat("Data_Darcy.mat")
# extract data (we use only 100 data for train)
k_train = torch.tensor(data["k_train"], dtype=torch.float)
u_train = torch.tensor(data["u_train"], dtype=torch.float)
k_test = torch.tensor(data["k_test"], dtype=torch.float)
u_test = torch.tensor(data["u_test"], dtype=torch.float)
x = torch.tensor(data["x"], dtype=torch.float)[0]
y = torch.tensor(data["y"], dtype=torch.float)[0]
# Let's visualize some data
# In[3]:
plt.subplot(1, 2, 1)
plt.title("permeability")
plt.imshow(k_train[0])
plt.subplot(1, 2, 2)
plt.title("field solution")
plt.imshow(u_train[0])
plt.show()
# We now create the Neural Operators problem class. Learning Neural Operators is similar as learning in a supervised manner, therefore we will use `SupervisedProblem`.
# In[4]:
# make problem
problem = SupervisedProblem(
input_=k_train.unsqueeze(-1), output_=u_train.unsqueeze(-1)
)
# ## Solving the problem with a FeedForward Neural Network
#
# We will first solve the problem using a Feedforward neural network. We will use the `SupervisedSolver` for solving the problem, since we are training using supervised learning.
# In[5]:
# make model
model = FeedForward(input_dimensions=1, output_dimensions=1)
# make solver
solver = SupervisedSolver(problem=problem, model=model, use_lt=False)
# make the trainer and train
trainer = Trainer(
solver=solver,
max_epochs=10,
accelerator="cpu",
enable_model_summary=False,
batch_size=10,
train_size=1.0,
val_size=0.0,
test_size=0.0,
)
trainer.train()
# The final loss is pretty high... We can calculate the error by importing `LpLoss`.
# In[6]:
from pina.loss import LpLoss
# make the metric
metric_err = LpLoss(relative=False)
model = solver.model
err = (
float(
metric_err(u_train.unsqueeze(-1), model(k_train.unsqueeze(-1))).mean()
)
* 100
)
print(f"Final error training {err:.2f}%")
err = (
float(metric_err(u_test.unsqueeze(-1), model(k_test.unsqueeze(-1))).mean())
* 100
)
print(f"Final error testing {err:.2f}%")
# ## Solving the problem with a Fourier Neural Operator (FNO)
#
# We will now move to solve the problem using a FNO. Since we are learning operator this approach is better suited, as we shall see.
# In[7]:
# make model
lifting_net = torch.nn.Linear(1, 24)
projecting_net = torch.nn.Linear(24, 1)
model = FNO(
lifting_net=lifting_net,
projecting_net=projecting_net,
n_modes=8,
dimensions=2,
inner_size=24,
padding=8,
)
# make solver
solver = SupervisedSolver(problem=problem, model=model, use_lt=False)
# make the trainer and train
trainer = Trainer(
solver=solver,
max_epochs=10,
accelerator="cpu",
enable_model_summary=False,
batch_size=10,
train_size=1.0,
val_size=0.0,
test_size=0.0,
)
trainer.train()
# We can clearly see that the final loss is lower. Let's see in testing.. Notice that the number of parameters is way higher than a `FeedForward` network. We suggest to use GPU or TPU for a speed up in training, when many data samples are used.
# In[8]:
model = solver.model
err = (
float(
metric_err(u_train.unsqueeze(-1), model(k_train.unsqueeze(-1))).mean()
)
* 100
)
print(f"Final error training {err:.2f}%")
err = (
float(metric_err(u_test.unsqueeze(-1), model(k_test.unsqueeze(-1))).mean())
* 100
)
print(f"Final error testing {err:.2f}%")
# As we can see the loss is way lower!
# ## What's next?
#
# We have made a very simple example on how to use the `FNO` for learning neural operator. Currently in **PINA** we implement 1D/2D/3D cases. We suggest to extend the tutorial using more complex problems and train for longer, to see the full potential of neural operators.