├── Tutorial 01 - Function Approximation with Pytorch.ipynb ├── Tutorial 02 - Cross Validation and Intro to CNNs.ipynb ├── Tutorial 03 - PINN Training.ipynb ├── Tutorial 04 - PINNs for Inverse Problems .ipynb ├── Tutorial 05 - Operator Learing - Fourier Neural Operator.ipynb ├── Tutorial 06 - Operator Learing - Convolutional Neural Operator.ipynb ├── Tutorial 07 - Introduction to Graph Neural Networks.ipynb ├── Tutorial 08 - Vision Transformers for solving PDEs.ipynb ├── Tutorial 10 - Coding Autodiff.ipynb ├── Tutorial 11 - Introduction to JAX, NDEs and diffusion models.ipynb ├── Tutorial New - Time Dependent CNO.ipynb ├── Tutorial New - Transfer Learning for PDEs.ipynb ├── X_obs.npy ├── _pics ├── 123 ├── cam1.jpeg └── cam2.jpg ├── datasets ├── AC_data_input.npy ├── AC_data_output.npy ├── pde_data.npy └── readme.md ├── engine.py └── readme.md /Tutorial 10 - Coding Autodiff.ipynb: -------------------------------------------------------------------------------- 1 | {"cells":[{"cell_type":"markdown","id":"0e209abf","metadata":{"id":"0e209abf"},"source":["# Autodifferentiation tutorial\n","\n","In this tutorial, we will be implementing autodifferentiation from scratch, without using external python libraries.\n","\n","## Problem overview\n","\n","In particular, we will be defining a custom `Value` object in python.\n","\n","This object defines a scalar value (analogous to a python `float`) which can have primitive operations (e.g. add/multiply/pow) applied to it. Each primitive operation returns a new `Value` object.\n","\n","Importantly, each `Value` object keeps track of the child `Value` objects which created it, and defines a `._backward` method which computes the vector-Jacobian product of the primative operation which created it.\n","\n","This extra bookmarking allows us to define a `Value.backward()` method (similar to `PyTorch`) which recursively backpropagates gradients through the entire computational graph, accumulating gradients in the leaf `Values` of the graph.\n","\n","\n","## Part A: implement the `Value` class\n","\n","The `Value` class is defined in `engine.py`.\n","\n","There are a number of lines of code missing from this class that you must fill in:\n","\n","> **Task A.1**: Implement the primitive operations which currently raise a `NotImplementedError`\n","\n","> **Task A.2**: Implement the `Value.backward` method.\n","\n","> **Task A.3**: Test that the class is correctly implemented by running the tests defined in `engine.py`\n","\n","More hints are contained in `engine.py`.\n","\n","## Part B: use the `Value` class to solve a differentiable physics problem\n","\n","Once we have a working `Value` object, we can use it to solve any problem requiring gradients.\n","\n","In this part, we will use the `Value` object to learn how to **throw a ball** to hit a target.\n","\n","### Problem overview\n","\n","Imagine you are located at $P1 = (0,0)$ and you throw a ball with an initial velocity $v$ at an angle $\\alpha$ from the x-axis. Your goal is to hit a target at $P2 = (x_2, y_2)$. What are values of $\\alpha$ and $v$ you should use?\n","\n","We can treat this as a inverse problem, where the goal is to minimise the following loss function\n","\n","$$\n","L(v,\\alpha) = (F(v, \\alpha, x_2) - y_2)^2 ~~~~~~~(1)\n","$$\n","\n","Here $F(v, \\alpha, x_2)$ is our forward physics model, which tells us the height of the ball at $x_2$ given the initial velocity and angle of the ball.\n","\n","In this case, $F$ is given by\n","\n","$$\n","F(v, \\alpha, x_2) = - \\frac{g}{2} \\left( \\frac{x_2}{v \\cos \\alpha} \\right)^2 + x_2 \\tan \\alpha ~~~~~~~(2)\n","$$\n","\n","where $g$ is the acceleration due to gravity.\n","\n","> **Optional task B.1**: Derive (2) using Netwon's laws.\n","\n","> **Task B.2**: Write a python function that computes $F(v, \\alpha, x_2)$, where $v$ and $\\alpha$ are `Value` objects.\n","\n","> **Task B.3**: Use `Value.backward` to write a gradient descent algorithm which minimises the loss function (1), given the starting guess of $v$ and $\\alpha$ below.\n","\n","> **Task B.4**: Verify that the learned values of $\\alpha$ and $v$ hits the target by plotting the optimised trajectory.\n","\n","> **Task B.5**: What happens to the trajectory when you change the starting guess of $v$ and $\\alpha$? Why is this the case?"]},{"cell_type":"code","execution_count":null,"id":"5c638652","metadata":{"scrolled":false,"id":"5c638652","outputId":"b546f8a7-b49e-4a31-d1ea-2a9b9431e606"},"outputs":[{"data":{"image/png":"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","text/plain":["
"]},"metadata":{},"output_type":"display_data"},{"data":{"image/png":"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","text/plain":["
"]},"metadata":{},"output_type":"display_data"}],"source":["import math\n","import matplotlib.pyplot as plt\n","from engine import Value\n","\n","g = 9.81\n","x2, y2 = 1, 0.7\n","\n","v = Value(1)# starting guess\n","alpha = Value(45*math.pi/180)# starting guess\n","\n","def plot_trajectory(v, alpha):\n"," xs = [x2*(i/100) for i in range(100)]\n"," ys = [F(v, alpha, x).data for x in xs]\n"," plt.figure()\n"," plt.title(f\"$v={v.data:.1f}$, $\\\\alpha={180*alpha.data/math.pi:.1f}$\")\n"," plt.plot(xs, ys, label=\"Trajectory\")\n"," plt.scatter(x2, y2, label=\"Target\", s=100, color=\"tab:red\")\n"," plt.gca().set_aspect(\"equal\")\n"," plt.legend()\n"," plt.show()\n","\n","def F(v, alpha, x2):\n"," \"Forward physics model\"\n"," return -(g/2)*((x2 / v * alpha.cos())**2) + (x2*(alpha.sin()/alpha.cos()))\n","\n","lr = 1e-2\n","plot_trajectory(v, alpha)\n","for i in range(1000):\n"," y = F(v, alpha, x2)\n"," loss = (y-y2)**2\n"," loss.backward()\n"," v = Value(v.data - lr*v.grad)\n"," alpha = Value(alpha.data - lr*alpha.grad)\n","plot_trajectory(v, alpha)"]}],"metadata":{"kernelspec":{"display_name":"Python 3 (ipykernel)","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.10.10"},"colab":{"provenance":[]}},"nbformat":4,"nbformat_minor":5} -------------------------------------------------------------------------------- /X_obs.npy: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/camlab-ethz/AI_Science_Engineering/fd02ac932bb448d8dc5c0165ee108c9be6af79db/X_obs.npy -------------------------------------------------------------------------------- /_pics/123: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /_pics/cam1.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/camlab-ethz/AI_Science_Engineering/fd02ac932bb448d8dc5c0165ee108c9be6af79db/_pics/cam1.jpeg -------------------------------------------------------------------------------- /_pics/cam2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/camlab-ethz/AI_Science_Engineering/fd02ac932bb448d8dc5c0165ee108c9be6af79db/_pics/cam2.jpg -------------------------------------------------------------------------------- /datasets/AC_data_input.npy: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/camlab-ethz/AI_Science_Engineering/fd02ac932bb448d8dc5c0165ee108c9be6af79db/datasets/AC_data_input.npy -------------------------------------------------------------------------------- /datasets/AC_data_output.npy: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/camlab-ethz/AI_Science_Engineering/fd02ac932bb448d8dc5c0165ee108c9be6af79db/datasets/AC_data_output.npy -------------------------------------------------------------------------------- /datasets/pde_data.npy: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/camlab-ethz/AI_Science_Engineering/fd02ac932bb448d8dc5c0165ee108c9be6af79db/datasets/pde_data.npy -------------------------------------------------------------------------------- /datasets/readme.md: -------------------------------------------------------------------------------- 1 | This is the folder with the dasatest needed to run the notebooks. 2 | 3 | The Allen-cahn dataset may be found here: 4 | 5 | [Zenodo: Allen-Cahn](https://zenodo.org/records/15388674?token=eyJhbGciOiJIUzUxMiJ9.eyJpZCI6IjU4N2I3ZWJmLWE0YjItNDFkZi04MDYwLWZiMzE1MjhmNTZkNiIsImRhdGEiOnt9LCJyYW5kb20iOiJiYWRkNTE5ZWZjNjRmNWMxMmI4YTY4NmVkNzRiNTk3OSJ9.TbblJrkXOAMTBPIKIlkvTd18-rzS67wm0xlDXEtBxYItyMZatyWTJvRtYUvOYZfudNAj6KO2dUWOO5n7ZGgWzQ) 6 | -------------------------------------------------------------------------------- /engine.py: -------------------------------------------------------------------------------- 1 | import math 2 | 3 | class Value: 4 | """Defines a Value object, which stores a single scalar value and its gradient. 5 | 6 | When a primitive operation is called on this Value object (e.g. add/multiply/pow), 7 | a new Value object is returned which: 8 | 1) keeps track of its child value objects 9 | 2) has a "._backward" method defined which computes the vector-Jacobian 10 | product of the primative operation which created it 11 | 12 | After computing a series of operations with Value objects, one can call the 13 | ".backward" method. This recursively backpropagates (applies the chain rule) 14 | through the entire computational graph, accumulating gradients in the leaf 15 | Values of the graph. 16 | 17 | Your tasks: 18 | 19 | 1) Implement the primitive operations which currently raise a NotImplementedError 20 | HINT: for each primitive operation, make sure to define its vector-Jacobian 21 | product i.e. return a new value object which has a "._backward" defined 22 | Because we are only dealing with scalar primitive operations, the 23 | vector-Jacobian product just reduces to two scalar values multiplied 24 | together (no matrix operations are needed) 25 | 26 | 2) Implement the ".backward" method. 27 | HINT: In order to apply the chain rule properly, we need to call the 28 | ._backward method of each Value in the graph in topological order. 29 | So you must first sort the Values in the graph into this order and 30 | then apply the chain rule to this sorted list. 31 | """ 32 | 33 | def __init__(self, data, _children=(), _op=''): 34 | self.data = data 35 | self.grad = 0 36 | 37 | # internal variables used for autograd graph construction 38 | self._backward = lambda: None 39 | self._prev = set(_children) 40 | self._op = _op # the op that produced this node, for graphviz / debugging / etc 41 | 42 | def __add__(self, other): 43 | other = other if isinstance(other, Value) else Value(other) 44 | out = Value(self.data + other.data, (self, other), '+') 45 | 46 | def _backward(): 47 | self.grad += out.grad 48 | other.grad += out.grad 49 | out._backward = _backward 50 | 51 | return out 52 | 53 | def __mul__(self, other): 54 | other = other if isinstance(other, Value) else Value(other) 55 | out = Value(self.data * other.data, (self, other), '*') 56 | 57 | def _backward(): 58 | self.grad += other.data * out.grad 59 | other.grad += self.data * out.grad 60 | out._backward = _backward 61 | 62 | return out 63 | 64 | def __pow__(self, other): 65 | assert isinstance(other, (int, float)), "only supporting int/float powers for now" 66 | out = Value(self.data**other, (self,), f'**{other}') 67 | 68 | def _backward(): 69 | self.grad += (other * self.data**(other-1)) * out.grad 70 | out._backward = _backward 71 | 72 | return out 73 | 74 | def cos(self): 75 | out = Value(math.cos(self.data), (self,), "cos") 76 | 77 | def _backward(): 78 | self.grad += -math.sin(self.data) * out.grad 79 | out._backward = _backward 80 | 81 | return out 82 | 83 | def sin(self): 84 | out = Value(math.sin(self.data), (self,), "sin") 85 | 86 | def _backward(): 87 | self.grad += math.cos(self.data) * out.grad 88 | out._backward = _backward 89 | 90 | return out 91 | 92 | def backward(self): 93 | 94 | # topological order all of the children in the graph 95 | topo = [] 96 | visited = set() 97 | def build_topo(v): 98 | if v not in visited: 99 | visited.add(v) 100 | for child in v._prev: 101 | build_topo(child) 102 | topo.append(v) 103 | build_topo(self) 104 | 105 | # go one variable at a time and apply the chain rule to get its gradient 106 | self.grad = 1 107 | for v in reversed(topo): 108 | v._backward() 109 | 110 | def __neg__(self): # -self 111 | return self * -1 112 | 113 | def __radd__(self, other): # other + self 114 | return self + other 115 | 116 | def __sub__(self, other): # self - other 117 | return self + (-other) 118 | 119 | def __rsub__(self, other): # other - self 120 | return (-self) + other 121 | 122 | def __rmul__(self, other): # other * self 123 | return self * other 124 | 125 | def __truediv__(self, other): # self / other 126 | return self * other**-1 127 | 128 | def __rtruediv__(self, other): # other / self 129 | return (self**-1) * other 130 | 131 | def __repr__(self): 132 | return f"Value(data={self.data}, grad={self.grad})" 133 | 134 | 135 | 136 | if __name__ == "__main__": 137 | 138 | # Run some tests on the value class 139 | 140 | x = Value(1) 141 | y = x + 2 - 3 142 | y.backward() 143 | assert x.grad == 1 144 | 145 | x = Value(1) 146 | y = 4*x/2 147 | y.backward() 148 | assert x.grad == 2 149 | 150 | x = Value(2) 151 | y = x**2 152 | y.backward() 153 | assert x.grad == 2*2 154 | 155 | x = Value(0) 156 | y = x.cos() 157 | y.backward() 158 | assert x.grad == 0 159 | 160 | x = Value(0) 161 | y = x.sin() 162 | y.backward() 163 | assert x.grad == 1 164 | 165 | x = Value(0) 166 | y = x*x.cos() + x**2 + 3 167 | y.backward() 168 | assert x.grad == 1 169 | 170 | 171 | 172 | 173 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # AI in the Sciences and Engineering, ETH Zurich 2 | 3 | This repository is the official project page of the course AI in the Sciences and Engineering, ETH Zurich. 4 | 5 | **Lecturers**: Prof. Dr. Siddhartha Mishra, Dr. Ben Moseley\ 6 | **Assistants**: Bogdan Raonic, Victor Armegioiu 7 | 8 | ### Course page can be found at [this link](https://camlab.ethz.ch/teaching/ai-in-the-sciences-and-engineering-2024.html) 9 | ### Recordings of the lectures can be found at this YouTube [link](https://www.youtube.com/watch?v=LkKvhvsf6jY&list=PLJkYEExhe7rYFkBIB2U5pf_RWzYnFLj7r). 10 | 11 | ## Topics 12 | 13 | **A selection of the following topics is presented in the lectures**: 14 | 15 | - Key scientific tasks common to many scientific domains, such as simulation, inverse problems, equation discovery, design, and control problems, and issues with traditional methods for solving them 16 | - Physics-informed neural networks for solving forward, inverse and equation discovery problems related to PDEs 17 | - Neural operators, including Fourier neural operators, Convolutional neural operators and DeepONets, for learning efficient surrogate models, and their theoretical foundations 18 | - Differentiable scientific algorithms, neural differential equations, and the benefits of hybrid workflows 19 | - AI for symbolic regression and equation discovery 20 | - Applications of graph neural networks in science 21 | - Large language models and other Foundation models for scientific discovery 22 | 23 | Applications using these techniques will be illustrated across fluid dynamics, wave physics, medical physics, molecular design, and computational biology. Several examples where AI algorithms outperform traditional scientific workflows will be shown. 24 | 25 | ## Tutorials 26 | - **Tutorial 01** - Function Approximation with Pytorch 27 | - **Tutorial 02** - Cross Validation and Intro to CNNs 28 | - **Tutorial 03** - PINN Training 29 | - **Tutorial 04** - PINNs for Inverse Problems 30 | - **Tutorial 05** - Operator Learning - Fourier Neural Operator 31 | - **Tutorial 06** - Operator Learning - Convolutional Neural Operator 32 | - **Tutorial 07** - Introduction to Graph Neural Networks 33 | - **Tutorial 08** - Vision Transformers for solving PDEs 34 | - **Tutorial 09** - Denoising Diffusion Probabilistic Models - Please visit [this link](https://github.com/dataflowr/notebooks/blob/master/Module18/ddpm_nano_sol.ipynb) to access the notebook 35 | - **Tutorial 10** - Coding Autodiff 36 | - **Tutorial 11** - Introduction to JAX, NDEs and diffusion models 37 | 38 | ### New Tutorials from Fall 2024 39 | - Time Dependent CNO 40 | - Transfer Learning for PDEs 41 | 42 | #### Note 43 | 44 | The Allen-cahn dataset may be found here: [Zenodo: Allen-Cahn](https://zenodo.org/records/15388674?token=eyJhbGciOiJIUzUxMiJ9.eyJpZCI6IjU4N2I3ZWJmLWE0YjItNDFkZi04MDYwLWZiMzE1MjhmNTZkNiIsImRhdGEiOnt9LCJyYW5kb20iOiJiYWRkNTE5ZWZjNjRmNWMxMmI4YTY4NmVkNzRiNTk3OSJ9.TbblJrkXOAMTBPIKIlkvTd18-rzS67wm0xlDXEtBxYItyMZatyWTJvRtYUvOYZfudNAj6KO2dUWOO5n7ZGgWzQ) 45 | 46 | ## Archive 47 | 48 | - Recordings of the 2023 lectures can be found at [this link](https://www.youtube.com/watch?v=y6wHpRzhhkA&list=PLJkYEExhe7rYY5HjpIJbgo-tDZ3bIAqAm) 49 | --------------------------------------------------------------------------------