You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: README.md
+32-5Lines changed: 32 additions & 5 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -12,9 +12,9 @@
12
12
13
13
A Package that provides Layers for the learning of (nonlinear) operators in order to solve parametric PDEs.
14
14
15
-
For now, this package contains the Fourier Neural Operator originally proposed by Li et al.
15
+
For now, this package contains the Fourier Neural Operator originally proposed by Li et al[1] as well as the DeepONet conceived by Lu et al [2].
16
16
17
-
I decided to implement this method in Julia because coding up a layer using PyTorch in Python is rather cumbersome in comparison and Julia as a whole simply runs at comparable or faster speed than Python. Please do check out the [original work](https://github.com/zongyi-li/fourier_neural_operator) at GitHub as well.
17
+
I decided to implement this method in Julia because coding up a layer using PyTorch in Python is rather cumbersome in comparison and Julia as a whole simply runs at comparable or faster speed than Python.
18
18
19
19
The implementation of the layers is influenced heavily by the basic layers provided in the [Flux.jl](https://github.com/FluxML/Flux.jl) package.
20
20
@@ -28,6 +28,8 @@ pkg> add OperatorLearning
28
28
29
29
## Usage/Examples
30
30
31
+
### Fourier Layer
32
+
31
33
The basic workflow is more or less in line with the layer architectures that `Flux` provides, i.e. you construct individual layers, chain them if desired and pass the inputs as arguments to the layers.
32
34
33
35
The Fourier Layer performs a linear transform as well as convolution (linear transform in fourier space), adds them and passes it through the activation.
model =FourierLayer(101, 101, 100, 16, σ; bias_fourier=false)
48
50
```
49
51
50
-
To see a full implementation, check the Burgers equation example at `examples/burgers.jl`.
52
+
To see a full implementation, check the Burgers equation example at `examples/burgers_FNO.jl`.
51
53
Compared to the original implementation by [Li et al.](https://github.com/zongyi-li/fourier_neural_operator/blob/master/fourier_1d.py) using PyTorch, this version written in Julia clocks in about 20 - 25% faster when running on a NVIDIA RTX A5000 GPU.
52
54
53
55
If you'd like to replicate the example, you need to get the dataset for learning the Burgers equation. You can get it [here](https://drive.google.com/drive/folders/1UnbQh2WWc6knEHbLn-ZaXrKUZhp7pjt-) or alternatively use the provided [scripts](https://github.com/zongyi-li/fourier_neural_operator/tree/master/data_generation/burgers).
54
56
57
+
### DeepONet
58
+
59
+
The `DeepONet` function basically sets up two separate Flux `Chain` structs and transforms the two input arrays into one via einsum/dot product.
60
+
61
+
You can either set up a "vanilla" DeepONet via the constructor function which sets up `Dense` layers for you or, if you feel fancy, pass two Chains directly to the function so you can use other architectures such as CNN or RNN as well.
62
+
The former takes two tuples that describe each architecture. E.g. `(32,64,72)` sets up a DNN with 32 neurons in the first, 64 in the second and 72 in the last layer.
63
+
64
+
```julia
65
+
using OperatorLearning
66
+
using Flux
67
+
68
+
# Create a DeepONet with branch 32 -> 64 -> 72 and sigmoid activation
69
+
# and trunk 24 -> 64 -> 72 and tanh activation without biases
70
+
model =DeepONet((32,64,72), (24,64,72), σ, tanh; init_branch=Flux.glorot_normal, bias_trunk=false)
71
+
72
+
# Alternatively, set up your own nets altogether and pass them to DeepONet
For usage, check the Burgers equation example at `examples/burgers_DeepONet.jl`.
79
+
55
80
## License
56
81
57
82
[MIT](https://choosealicense.com/licenses/mit/)
@@ -60,7 +85,7 @@ If you'd like to replicate the example, you need to get the dataset for learning
60
85
61
86
-[x] 1D Fourier Layer
62
87
-[ ] 2D / 3D Fourier Layer
63
-
-[] DeepONet
88
+
-[x] DeepONet
64
89
-[ ] Physics informed Loss
65
90
66
91
## Contributing
@@ -69,4 +94,6 @@ Contributions are always welcome! Please submit a PR if you'd like to participat
69
94
70
95
## References
71
96
72
-
- Li et al., 2020 [arXiv:2010.08895](https://arxiv.org/abs/2010.08895)
97
+
[1] Z. Li et al., „Fourier Neural Operator for Parametric Partial Differential Equations“, [arXiv:2010.08895](https://arxiv.org/abs/2010.08895)[cs, math], May 2021
98
+
99
+
[2] L. Lu, P. Jin, and G. E. Karniadakis, „DeepONet: Learning nonlinear operators for identifying differential equations based on the universal approximation theorem of operators“, [arXiv:1910.03193](http://arxiv.org/abs/1910.03193)[cs, stat], Apr. 2020
Create an (unstacked) DeepONet architecture as proposed by Lu et al.
10
+
arXiv:1910.03193
11
+
12
+
The model works as follows:
13
+
14
+
x --- branch --
15
+
|
16
+
-⊠--u-
17
+
|
18
+
y --- trunk ---
19
+
20
+
Where `x` represents the input function, discretely evaluated at its respective sensors. So the ipnut is of shape [m] for one instance or [m x b] for a training set.
21
+
`y` are the probing locations for the operator to be trained. It has shape [N x n] for N different variables in the PDE (i.e. spatial and temporal coordinates) with each n distinct evaluation points.
22
+
`u` is the solution of the queried instance of the PDE, given by the specific choice of parameters.
23
+
24
+
Both inputs `x` and `y` are multiplied together via dot product Σᵢ bᵢⱼ tᵢₖ.
25
+
26
+
You can set up this architecture in two ways:
27
+
28
+
1. By Specifying the architecture and all its parameters as given above. This always creates `Dense` layers for the branch and trunk net and corresponds to the DeepONet proposed by Lu et al.
29
+
30
+
2. By passing two architectures in the form of two Chain structs directly. Do this if you want more flexibility and e.g. use an RNN or CNN instead of simple `Dense` layers.
31
+
32
+
Strictly speaking, DeepONet does not imply either of the branch or trunk net to be a simple DNN. Usually though, this is the case which is why it's treated as the default case here.
33
+
34
+
# Example
35
+
36
+
Consider a transient 1D advection problem ∂ₜu + u ⋅ ∇u = 0, with an IC u(x,0) = g(x).
37
+
We are given several (b = 200) instances of the IC, discretized at 50 points each and want to query the solution for 100 different locations and times [0;1].
38
+
39
+
That makes the branch input of shape [50 x 200] and the trunk input of shape [2 x 100]. So the input for the branch net is 50 and 100 for the trunk net.
40
+
41
+
# Usage
42
+
43
+
```julia
44
+
julia> model = DeepONet((32,64,72), (24,64,72))
45
+
DeepONet with
46
+
branch net: (Chain(Dense(32, 64), Dense(64, 72)))
47
+
Trunk net: (Chain(Dense(24, 64), Dense(64, 72)))
48
+
49
+
julia> model = DeepONet((32,64,72), (24,64,72), σ, tanh; init_branch=Flux.glorot_normal, bias_trunk=false)
@assert architecture_branch[end] == architecture_trunk[end] "Branch and Trunk net must share the same amount of nodes in the last layer. Otherwise Σᵢ bᵢⱼ tᵢₖ won't work."
86
+
87
+
# To construct the subnets we use the helper function in subnets.jl
0 commit comments