SoL training updated for phiflow3.1 and new data loader

This commit is contained in:
N_T committed 2024-10-08 13:30:33 +08:00
1 parent 4afc1c816e
commit 2db1f59d24
1 file changed
+184 -92
+184 -92
View File
@@ -128,26 +128,40 @@
"base_uri": "https://localhost:8080/" "base_uri": "https://localhost:8080/"
}, },
"id": "JwZudtWauiGa", "id": "JwZudtWauiGa",
"outputId": "f284b19b-0a77-44de-befe-06e3218fe49d" "outputId": "3e61b6dd-e1ea-47e7-f9af-6cde0c64162a"
}, },
"outputs": [ "outputs": [
{ {
"name": "stdout",
"output_type": "stream", "output_type": "stream",
"name": "stdout",
"text": [ "text": [
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m182.2/182.2 kB\u001b[0m \u001b[31m9.5 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
"\u001b[?25h Preparing metadata (setup.py) ... \u001b[?25l\u001b[?25hdone\n",
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m306.1/306.1 kB\u001b[0m \u001b[31m11.4 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
"\u001b[?25h Preparing metadata (setup.py) ... \u001b[?25l\u001b[?25hdone\n",
" Building wheel for phiflow (setup.py) ... \u001b[?25l\u001b[?25hdone\n",
" Building wheel for phiml (setup.py) ... \u001b[?25l\u001b[?25hdone\n",
" Installing build dependencies ... \u001b[?25l\u001b[?25hdone\n",
" Getting requirements to build wheel ... \u001b[?25l\u001b[?25hdone\n",
" Preparing metadata (pyproject.toml) ... \u001b[?25l\u001b[?25hdone\n",
" Building wheel for pbdl (pyproject.toml) ... \u001b[?25l\u001b[?25hdone\n",
"Using device: cuda:0\n" "Using device: cuda:0\n"
] ]
} }
], ],
"source": [ "source": [
"!pip install --upgrade --quiet phiflow==3.1\n",
"!pip install --upgrade --quiet git+https://github.com/tum-pbs/pbdl-dataset@develop\n",
"\n",
"import os, sys, logging, argparse, pickle, glob, random, pylab, time\n", "import os, sys, logging, argparse, pickle, glob, random, pylab, time\n",
"from tqdm import tqdm\n", "from tqdm import tqdm\n",
"from phi.torch.flow import *\n", "from phi.torch.flow import *\n",
"\n", "\n",
"random.seed(42)\n", "random.seed(42)\n",
"np.random.seed(42)\n", "np.random.seed(42)\n",
"#math.seed(42) # phiflow seed\n", "\n",
"math.set_global_precision(32)\n", "math.seed(42) # phiflow seed\n",
"math.set_global_precision(32) # single precision\n",
"\n", "\n",
"USE_CPU = 0\n", "USE_CPU = 0\n",
"TORCH.set_default_device(\"GPU\")\n", "TORCH.set_default_device(\"GPU\")\n",
@@ -233,13 +247,14 @@
" self.solve_info = { 'pressure': pressure, 'advected_velocity': advected_velocity }\n", " self.solve_info = { 'pressure': pressure, 'advected_velocity': advected_velocity }\n",
"\n", "\n",
" return [marker, velocity]\n", " return [marker, velocity]\n",
"\n", "\n"
" "
] ]
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"metadata": {}, "metadata": {
"id": "mP-5ZNNy1FoE"
},
"source": [ "source": [
"Note that the `marker` density here denotes a passively advected marker field, and not the density of the fluid. Below we'll only be focusing on the velocity for the correction task. The marker density is tracked purely for visualization purposes.\n" "Note that the `marker` density here denotes a passively advected marker field, and not the density of the fluid. Below we'll only be focusing on the velocity for the correction task. The marker density is tracked purely for visualization purposes.\n"
] ]
@@ -270,12 +285,16 @@
"cell_type": "code", "cell_type": "code",
"execution_count": 3, "execution_count": 3,
"metadata": { "metadata": {
"id": "qIrWYTy6xscA" "id": "qIrWYTy6xscA",
"colab": {
"base_uri": "https://localhost:8080/"
},
"outputId": "90e91528-0f57-467a-a407-6f895bd8333b"
}, },
"outputs": [ "outputs": [
{ {
"name": "stdout",
"output_type": "stream", "output_type": "stream",
"name": "stdout",
"text": [ "text": [
"ResNet(\n", "ResNet(\n",
" (Res_in): ResNetBlock(\n", " (Res_in): ResNetBlock(\n",
@@ -439,26 +458,27 @@
"base_uri": "https://localhost:8080/" "base_uri": "https://localhost:8080/"
}, },
"id": "59EBdEdj0QR2", "id": "59EBdEdj0QR2",
"outputId": "c6f13916-2764-45dc-89f1-22890cb2662b" "outputId": "16176f06-542c-4a65-8562-b0efd0da621d"
}, },
"outputs": [ "outputs": [
{ {
"name": "stdout",
"output_type": "stream", "output_type": "stream",
"name": "stdout",
"text": [ "text": [
"\u001b[96m\u001b[1mSuccess:\u001b[22m Loaded solver-in-the-loop-wake-flow with 10 simulations (6 selected) and 496 samples each.\u001b[0m\n" "\u001b[Kdownload completed\t ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[38;5;240m\u001b[94m 100%\u001b[0m\n",
"\u001b[96m\u001b[1mSuccess:\u001b[22m Loaded solver-in-the-loop-wake-flow with 6 simulations (6 selected) and 496 samples each.\u001b[0m\n",
"\u001b[1mInfo:\u001b[22m No precomputed normalization data found (or not complete). Calculating data...\u001b[0m\n"
] ]
} }
], ],
"source": [ "source": [
"import pbdl\n", "import pbdl\n",
"import pbdl.torch.loader\n", "import pbdl.torch.loader\n",
"from pbdl.normalization import StdNorm\n",
"\n", "\n",
"dataloader = pbdl.torch.loader.Dataloader(\"solver-in-the-loop-wake-flow\", MSTEPS, shuffle=True, sel_sims=[0,1,2,3,4,5],\n", "dataloader = pbdl.torch.loader.Dataloader(\"solver-in-the-loop-wake-flow\", MSTEPS, shuffle=True, sel_sims=[0,1,2,3,4,5],\n",
" batch_size=BATCH_SIZE, normalize=StdNorm(), intermediate_time_steps=True)\n", " batch_size=BATCH_SIZE, normalize=\"std\", intermediate_time_steps=True)\n",
"\n", "\n",
"# remember for normalization of the Reynolds number conditioning\n", "# remember for normalization of the Reynolds number conditioning , then turn off (None), we'll only normalize Re manually below\n",
"DATA_RE_MEAN = dataloader.dataset.normalize.const_mean[0][0]\n", "DATA_RE_MEAN = dataloader.dataset.normalize.const_mean[0][0]\n",
"DATA_RE_STD = dataloader.dataset.normalize.const_std[0][0]\n", "DATA_RE_STD = dataloader.dataset.normalize.const_std[0][0]\n",
"dataloader.dataset.normalize = None" "dataloader.dataset.normalize = None"
@@ -483,24 +503,24 @@
"base_uri": "https://localhost:8080/" "base_uri": "https://localhost:8080/"
}, },
"id": "EjgkdCzKP2Ip", "id": "EjgkdCzKP2Ip",
"outputId": "9e95aa79-6124-4e30-baf1-28bc37801b0f", "outputId": "36d2d677-6293-4b7d-e7f2-c6f1a7343aa9",
"scrolled": true "scrolled": true
}, },
"outputs": [ "outputs": [
{ {
"name": "stderr",
"output_type": "stream", "output_type": "stream",
"name": "stderr",
"text": [ "text": [
"/tmp/ipykernel_953067/1761501079.py:8: FutureWarning: Domain (phi.physics._boundaries) is deprecated and will be removed in a future release.\n", "<ipython-input-7-b9dac715c45b>:8: FutureWarning: Domain (phi.physics._boundaries) is deprecated and will be removed in a future release.\n",
"Please create grids directly, replacing the domain with a dict, e.g.\n", "Please create grids directly, replacing the domain with a dict, e.g.\n",
" domain = dict(x=64, y=128, bounds=Box(x=1, y=1))\n", " domain = dict(x=64, y=128, bounds=Box(x=1, y=1))\n",
" grid = CenteredGrid(0, **domain)\n", " grid = CenteredGrid(0, **domain)\n",
" from phi.physics._boundaries import Domain, OPEN, STICKY as CLOSED\n", " from phi.physics._boundaries import Domain, OPEN, STICKY as CLOSED\n",
"/tmp/ipykernel_953067/1761501079.py:15: DeprecationWarning: Domain is deprecated and will be removed in a future release. Use a dict instead, e.g. CenteredGrid(values, extrapolation, **domain_dict)\n", "<ipython-input-7-b9dac715c45b>:15: DeprecationWarning: Domain is deprecated and will be removed in a future release. Use a dict instead, e.g. CenteredGrid(values, extrapolation, **domain_dict)\n",
" domain = phi.physics._boundaries.Domain(y=SOURCE_RES[0], x=SOURCE_RES[1], boundaries=BNDS, bounds=Box(y=2*LENGTH, x=LENGTH))\n", " domain = phi.physics._boundaries.Domain(y=SOURCE_RES[0], x=SOURCE_RES[1], boundaries=BNDS, bounds=Box(y=2*LENGTH, x=LENGTH))\n",
"/tmp/ipykernel_953067/1761501079.py:15: FutureWarning: Domain is deprecated and will be removed in a future release. Use a dict instead, e.g. CenteredGrid(values, extrapolation, **domain_dict)\n", "<ipython-input-7-b9dac715c45b>:15: FutureWarning: Domain is deprecated and will be removed in a future release. Use a dict instead, e.g. CenteredGrid(values, extrapolation, **domain_dict)\n",
" domain = phi.physics._boundaries.Domain(y=SOURCE_RES[0], x=SOURCE_RES[1], boundaries=BNDS, bounds=Box(y=2*LENGTH, x=LENGTH))\n", " domain = phi.physics._boundaries.Domain(y=SOURCE_RES[0], x=SOURCE_RES[1], boundaries=BNDS, bounds=Box(y=2*LENGTH, x=LENGTH))\n",
"/tmp/ipykernel_953067/4224160660.py:7: DeprecationWarning: HardGeometryMask and SoftGeometryMask are deprecated. Use field.mask or field.resample instead.\n", "<ipython-input-2-590832b2dd2f>:7: DeprecationWarning: HardGeometryMask and SoftGeometryMask are deprecated. Use field.mask or field.resample instead.\n",
" self.vel_BcMask = self.domain.staggered_grid(HardGeometryMask( Box(y=(None, 5), x=None) ) )\n" " self.vel_BcMask = self.domain.staggered_grid(HardGeometryMask( Box(y=(None, 5), x=None) ) )\n"
] ]
} }
@@ -538,7 +558,9 @@
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 8, "execution_count": 8,
"metadata": {}, "metadata": {
"id": "5VCAzofU1FoH"
},
"outputs": [], "outputs": [],
"source": [ "source": [
"@jit_compile\n", "@jit_compile\n",
@@ -553,7 +575,9 @@
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"metadata": {}, "metadata": {
"id": "HWpyoUKE1FoH"
},
"source": [ "source": [
"Next comes the **most crucial** step in the whole setup: we define a function that encapsulates the chain of simulation steps and network evaluations in each training step. With the helper functions we've set up so far, it's actually pretty simple: we loop `MSTEPS` times, calling the simulator via `simulator_step` for an input state, and afterwards evaluate the correction operator via `network(to_pytorch(...))`. The NN correction is then added to the last simulation state in the `prediction` list of states. This list keeps around the marker density and velocity for each time step.\n", "Next comes the **most crucial** step in the whole setup: we define a function that encapsulates the chain of simulation steps and network evaluations in each training step. With the helper functions we've set up so far, it's actually pretty simple: we loop `MSTEPS` times, calling the simulator via `simulator_step` for an input state, and afterwards evaluate the correction operator via `network(to_pytorch(...))`. The NN correction is then added to the last simulation state in the `prediction` list of states. This list keeps around the marker density and velocity for each time step.\n",
"\n", "\n",
@@ -563,7 +587,9 @@
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 9, "execution_count": 9,
"metadata": {}, "metadata": {
"id": "KFp4eUta1FoH"
},
"outputs": [], "outputs": [],
"source": [ "source": [
"def training_step(inputs_targets):\n", "def training_step(inputs_targets):\n",
@@ -601,7 +627,9 @@
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"metadata": {}, "metadata": {
"id": "Sk82sacv1FoH"
},
"source": [ "source": [
"The `training_step` function above also directly evaluates and returns the loss. Here, we simply use an $L^2$ loss over the grids (in phiflow `fields`) for the whole sequence, i.e. over the unrolled `msteps`. In `vdiff` we're simply computing the difference between the targets and the current prediction, and then compute its `l2_loss`.\n", "The `training_step` function above also directly evaluates and returns the loss. Here, we simply use an $L^2$ loss over the grids (in phiflow `fields`) for the whole sequence, i.e. over the unrolled `msteps`. In `vdiff` we're simply computing the difference between the targets and the current prediction, and then compute its `l2_loss`.\n",
"\n", "\n",
@@ -612,33 +640,38 @@
"cell_type": "code", "cell_type": "code",
"execution_count": 10, "execution_count": 10,
"metadata": { "metadata": {
"scrolled": true "scrolled": true,
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "AJn5a5k31FoH",
"outputId": "91c710f7-1475-4dbb-8c33-45d33063859b"
}, },
"outputs": [ "outputs": [
{ {
"name": "stderr",
"output_type": "stream", "output_type": "stream",
"name": "stderr",
"text": [ "text": [
" 0%| | 0/4960 [00:00<?, ?it/s]/tmp/ipykernel_953067/1256326133.py:7: UserWarning: To copy construct from a tensor, it is recommended to use sourceTensor.clone().detach() or sourceTensor.clone().detach().requires_grad_(True), rather than torch.tensor(sourceTensor).\n", "\r 0%| | 0/992 [00:00<?, ?it/s]<ipython-input-10-64f00155003c>:8: UserWarning: To copy construct from a tensor, it is recommended to use sourceTensor.clone().detach() or sourceTensor.clone().detach().requires_grad_(True), rather than torch.tensor(sourceTensor).\n",
" input = torch.tensor(input_cpu, dtype=torch.float32).to(device);\n", " input = torch.tensor(input_cpu, dtype=torch.float32).to(device);\n",
"/tmp/ipykernel_953067/1256326133.py:8: UserWarning: To copy construct from a tensor, it is recommended to use sourceTensor.clone().detach() or sourceTensor.clone().detach().requires_grad_(True), rather than torch.tensor(sourceTensor).\n", "<ipython-input-10-64f00155003c>:9: UserWarning: To copy construct from a tensor, it is recommended to use sourceTensor.clone().detach() or sourceTensor.clone().detach().requires_grad_(True), rather than torch.tensor(sourceTensor).\n",
" targets = torch.tensor(targets_cpu, dtype=torch.float32).to(device)\n", " targets = torch.tensor(targets_cpu, dtype=torch.float32).to(device)\n",
"/home/thuerey/anaconda3/envs/torch24/lib/python3.12/site-packages/phiml/math/_optimize.py:631: UserWarning: Possible rank deficiency detected. Matrix might be singular which can lead to convergence problems. Please specify using Solve(rank_deficiency=...).\n", "/usr/local/lib/python3.10/dist-packages/phiml/math/_optimize.py:631: UserWarning: Possible rank deficiency detected. Matrix might be singular which can lead to convergence problems. Please specify using Solve(rank_deficiency=...).\n",
" warnings.warn(\"Possible rank deficiency detected. Matrix might be singular which can lead to convergence problems. Please specify using Solve(rank_deficiency=...).\")\n", " warnings.warn(\"Possible rank deficiency detected. Matrix might be singular which can lead to convergence problems. Please specify using Solve(rank_deficiency=...).\")\n",
"/home/thuerey/anaconda3/envs/torch24/lib/python3.12/site-packages/phiml/backend/torch/_torch_backend.py:800: UserWarning: Sparse CSR tensor support is in beta state. If you miss a functionality in the sparse tensor support, please submit a feature request to https://github.com/pytorch/pytorch/issues. (Triggered internally at ../aten/src/ATen/SparseCsrTensorImpl.cpp:53.)\n", "/usr/local/lib/python3.10/dist-packages/phiml/backend/torch/_torch_backend.py:800: UserWarning: Sparse CSR tensor support is in beta state. If you miss a functionality in the sparse tensor support, please submit a feature request to https://github.com/pytorch/pytorch/issues. (Triggered internally at ../aten/src/ATen/SparseCsrTensorImpl.cpp:53.)\n",
" return torch.sparse_csr_tensor(row_pointers, column_indices, values, shape, device=values.device)\n", " return torch.sparse_csr_tensor(row_pointers, column_indices, values, shape, device=values.device)\n",
"/home/thuerey/anaconda3/envs/torch24/lib/python3.12/site-packages/phiml/math/_optimize.py:631: UserWarning: Possible rank deficiency detected. Matrix might be singular which can lead to convergence problems. Please specify using Solve(rank_deficiency=...).\n", "/usr/local/lib/python3.10/dist-packages/phiml/math/_optimize.py:631: UserWarning: Possible rank deficiency detected. Matrix might be singular which can lead to convergence problems. Please specify using Solve(rank_deficiency=...).\n",
" warnings.warn(\"Possible rank deficiency detected. Matrix might be singular which can lead to convergence problems. Please specify using Solve(rank_deficiency=...).\")\n", " warnings.warn(\"Possible rank deficiency detected. Matrix might be singular which can lead to convergence problems. Please specify using Solve(rank_deficiency=...).\")\n",
"loss 11.792998: 0%| | 1/4960 [00:17<23:34:51, 17.12s/it]/tmp/ipykernel_953067/1256326133.py:7: UserWarning: To copy construct from a tensor, it is recommended to use sourceTensor.clone().detach() or sourceTensor.clone().detach().requires_grad_(True), rather than torch.tensor(sourceTensor).\n", "loss 15.871401: 0%| | 1/992 [00:31<8:39:45, 31.47s/it]<ipython-input-10-64f00155003c>:8: UserWarning: To copy construct from a tensor, it is recommended to use sourceTensor.clone().detach() or sourceTensor.clone().detach().requires_grad_(True), rather than torch.tensor(sourceTensor).\n",
" input = torch.tensor(input_cpu, dtype=torch.float32).to(device);\n", " input = torch.tensor(input_cpu, dtype=torch.float32).to(device);\n",
"/tmp/ipykernel_953067/1256326133.py:8: UserWarning: To copy construct from a tensor, it is recommended to use sourceTensor.clone().detach() or sourceTensor.clone().detach().requires_grad_(True), rather than torch.tensor(sourceTensor).\n", "<ipython-input-10-64f00155003c>:9: UserWarning: To copy construct from a tensor, it is recommended to use sourceTensor.clone().detach() or sourceTensor.clone().detach().requires_grad_(True), rather than torch.tensor(sourceTensor).\n",
" targets = torch.tensor(targets_cpu, dtype=torch.float32).to(device)\n", " targets = torch.tensor(targets_cpu, dtype=torch.float32).to(device)\n",
"loss 0.21036954: 100%|████████████████████████████████████| 4960/4960 [2:21:38<00:00, 1.71s/it]\n" "loss 0.9743874: 100%|███████████████████████████████████████| 992/992 [1:18:15<00:00, 4.73s/it]\n"
] ]
} }
], ],
"source": [ "source": [
"EPOCHS = 5\n", "EPOCHS = 1\n",
"\n", "\n",
"pbar = tqdm(initial=0, total=EPOCHS*len(dataloader), ncols=96)\n", "pbar = tqdm(initial=0, total=EPOCHS*len(dataloader), ncols=96)\n",
"\n", "\n",
@@ -658,17 +691,21 @@
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"metadata": {}, "metadata": {
"id": "Wk1Z9PB71FoH"
},
"source": [ "source": [
"\n", "\n",
"Note that each call to `update_weights` internally performs all 4 interleaved simulation steps and neural network calls, and back-propagates gradients for the whole chain. Due to the order, solver first, then network, the first step does not go back through the solver. However, for the next 3 steps, the first network call will receive feedback whether it's inferred correction influenced the 3 subsequent states towards the right direction or not.\n", "Note that each call to `update_weights` internally performs all 4 interleaved simulation steps and neural network calls, and back-propagates gradients for the whole chain. Due to the order, solver first, then network, the first step does not go back through the solver. However, for the next 3 steps, the first network call will receive feedback whether it's inferred correction influenced the 3 subsequent states towards the right direction or not.\n",
"\n", "\n",
"With the default parameters, the loss should go down from above 10 initially to around 0.2 (more epochs and larger/deeper networks will bring it down further). The decreasing loss is a good sign, but of course it's even more important to see how the resulting NN-solver combination fares on new inputs. With this training approach we've realized a hybrid solver, consisting of a regular _source_ simulator, and a network operator that was trained to specifically interact with this simulator for a chosen domain of simulation cases.\n" "With the default parameters, the loss should go down from above 10 initially to around 1.0 (more epochs and larger/deeper networks will bring it down further). The decreasing loss is a good sign, but of course it's even more important to see how the resulting NN-solver combination fares on new inputs. With this training approach we've realized a hybrid solver, consisting of a regular _source_ simulator, and a network operator that was trained to specifically interact with this simulator for a chosen domain of simulation cases.\n"
] ]
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"metadata": {}, "metadata": {
"id": "UlCHHTW_1FoH"
},
"source": [ "source": [
"## Test evaluation\n", "## Test evaluation\n",
"\n", "\n",
@@ -680,17 +717,25 @@
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 11, "execution_count": 11,
"metadata": {}, "metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "RPhPR9-51FoI",
"outputId": "6adee7c0-2117-4ec6-e731-b71532d4e819"
},
"outputs": [ "outputs": [
{ {
"name": "stdout",
"output_type": "stream", "output_type": "stream",
"name": "stdout",
"text": [ "text": [
"\u001b[Kdownload completed\t ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[38;5;240m\u001b[94m 100%\u001b[0m\n",
"\u001b[96m\u001b[1mSuccess:\u001b[22m Loaded solver-in-the-loop-wake-flow with 10 simulations (4 selected) and 300 samples each.\u001b[0m\n" "\u001b[96m\u001b[1mSuccess:\u001b[22m Loaded solver-in-the-loop-wake-flow with 10 simulations (4 selected) and 300 samples each.\u001b[0m\n"
] ]
} }
], ],
"source": [ "source": [
"#del dataloader # close hdf5 file handle\n",
"del dataloader # close hdf5 file handle\n", "del dataloader # close hdf5 file handle\n",
"\n", "\n",
"# get new & unseen test data\n", "# get new & unseen test data\n",
@@ -700,7 +745,9 @@
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"metadata": {}, "metadata": {
"id": "yFu75G9n1FoI"
},
"source": [ "source": [
"In case you have a pre-trained network, this is a good point to load a model. By default, we assume the training above was completed, so it's not necessary to load anything." "In case you have a pre-trained network, this is a good point to load a model. By default, we assume the training above was completed, so it's not necessary to load anything."
] ]
@@ -708,7 +755,9 @@
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 12, "execution_count": 12,
"metadata": {}, "metadata": {
"id": "NRJwUnRz1FoI"
},
"outputs": [], "outputs": [],
"source": [ "source": [
"# optionally load\n", "# optionally load\n",
@@ -720,7 +769,9 @@
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"metadata": {}, "metadata": {
"id": "NEu96LeY1FoI"
},
"source": [ "source": [
"We can reuse a lot of the solver code from above, but in the following, we will consider two simulated versions: for comparison, we'll run one reference simulation in the _source_ manifold (i.e. based on $\\mathcal P_s$, without any corrections applied). The second version is the actual result, we'll repeatedly compute the source solver plus the learned correction.\n", "We can reuse a lot of the solver code from above, but in the following, we will consider two simulated versions: for comparison, we'll run one reference simulation in the _source_ manifold (i.e. based on $\\mathcal P_s$, without any corrections applied). The second version is the actual result, we'll repeatedly compute the source solver plus the learned correction.\n",
"\n", "\n",
@@ -730,7 +781,9 @@
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 13, "execution_count": 13,
"metadata": {}, "metadata": {
"id": "RWC0mKNJ1FoI"
},
"outputs": [], "outputs": [],
"source": [ "source": [
"def run_sim(inputs, targets, steps, network=None):\n", "def run_sim(inputs, targets, steps, network=None):\n",
@@ -783,7 +836,9 @@
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"metadata": {}, "metadata": {
"id": "ysBPP8r21FoI"
},
"source": [ "source": [
"With `next(iter(dataloader_test))` we'll get a new state from the dataloader with a previously unseen Reynolds number. Then we'll run source and hybrid solver for `ROLLOUT_STEPS` iterations starting from the same initial state. Similar to training, we'll first get an initial state and reference states from the dataloader in `input` and `targets`. (Due to the random sampling, you might need to run this multiple times to e.g. get one of the higher Re cases.)\n", "With `next(iter(dataloader_test))` we'll get a new state from the dataloader with a previously unseen Reynolds number. Then we'll run source and hybrid solver for `ROLLOUT_STEPS` iterations starting from the same initial state. Similar to training, we'll first get an initial state and reference states from the dataloader in `input` and `targets`. (Due to the random sampling, you might need to run this multiple times to e.g. get one of the higher Re cases.)\n",
"\n" "\n"
@@ -792,22 +847,28 @@
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 14, "execution_count": 14,
"metadata": {}, "metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "aA7BRsSZ1FoJ",
"outputId": "fa436860-e5c9-4719-a605-50b9668fbe2d"
},
"outputs": [ "outputs": [
{ {
"name": "stdout",
"output_type": "stream", "output_type": "stream",
"name": "stdout",
"text": [ "text": [
"Re \u001b[94m1171.875\u001b[0m\n" "Re \u001b[94m1171.875\u001b[0m\n"
] ]
}, },
{ {
"name": "stderr",
"output_type": "stream", "output_type": "stream",
"name": "stderr",
"text": [ "text": [
"/tmp/ipykernel_953067/345484244.py:3: UserWarning: To copy construct from a tensor, it is recommended to use sourceTensor.clone().detach() or sourceTensor.clone().detach().requires_grad_(True), rather than torch.tensor(sourceTensor).\n", "<ipython-input-14-525360075f27>:3: UserWarning: To copy construct from a tensor, it is recommended to use sourceTensor.clone().detach() or sourceTensor.clone().detach().requires_grad_(True), rather than torch.tensor(sourceTensor).\n",
" input = torch.tensor(input_cpu, dtype=torch.float32).to(device)\n", " input = torch.tensor(input_cpu, dtype=torch.float32).to(device)\n",
"/tmp/ipykernel_953067/345484244.py:4: UserWarning: To copy construct from a tensor, it is recommended to use sourceTensor.clone().detach() or sourceTensor.clone().detach().requires_grad_(True), rather than torch.tensor(sourceTensor).\n", "<ipython-input-14-525360075f27>:4: UserWarning: To copy construct from a tensor, it is recommended to use sourceTensor.clone().detach() or sourceTensor.clone().detach().requires_grad_(True), rather than torch.tensor(sourceTensor).\n",
" targets = torch.tensor(targets_cpu, dtype=torch.float32).to(device)\n" " targets = torch.tensor(targets_cpu, dtype=torch.float32).to(device)\n"
] ]
} }
@@ -822,7 +883,9 @@
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"metadata": {}, "metadata": {
"id": "7kS6jU8j1FoJ"
},
"source": [ "source": [
"The interesting question of course is: how much does the NN operator actually improve the accuracy of the low-fidelity _source_ solver? This is captured by the relative $L_2$ errors computed each time by the `run_sim` function. It measures the squared distance in comparison to the squared magnitudes of the reference velocities. The cell above directly plots the aggregated errors.\n", "The interesting question of course is: how much does the NN operator actually improve the accuracy of the low-fidelity _source_ solver? This is captured by the relative $L_2$ errors computed each time by the `run_sim` function. It measures the squared distance in comparison to the squared magnitudes of the reference velocities. The cell above directly plots the aggregated errors.\n",
"\n", "\n",
@@ -836,50 +899,56 @@
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 15, "execution_count": 15,
"metadata": {}, "metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "QlsK9rG71FoJ",
"outputId": "2005389a-32e1-49b9-cb46-3a7c6d2d425d"
},
"outputs": [ "outputs": [
{ {
"name": "stdout",
"output_type": "stream", "output_type": "stream",
"name": "stdout",
"text": [ "text": [
"Running test with Re=\u001b[94m1171.875\u001b[0m, Sim. only\n" "Running test with Re=\u001b[94m1171.875\u001b[0m, Sim. only\n"
] ]
}, },
{ {
"name": "stderr",
"output_type": "stream", "output_type": "stream",
"name": "stderr",
"text": [ "text": [
"Sim. only: 0%| | 0/100 [00:00<?, ?it/s]/home/thuerey/anaconda3/envs/torch24/lib/python3.12/site-packages/phiml/math/_optimize.py:631: UserWarning: Possible rank deficiency detected. Matrix might be singular which can lead to convergence problems. Please specify using Solve(rank_deficiency=...).\n", "\rSim. only: 0%| | 0/100 [00:00<?, ?it/s]/usr/local/lib/python3.10/dist-packages/phiml/math/_optimize.py:631: UserWarning: Possible rank deficiency detected. Matrix might be singular which can lead to convergence problems. Please specify using Solve(rank_deficiency=...).\n",
" warnings.warn(\"Possible rank deficiency detected. Matrix might be singular which can lead to convergence problems. Please specify using Solve(rank_deficiency=...).\")\n", " warnings.warn(\"Possible rank deficiency detected. Matrix might be singular which can lead to convergence problems. Please specify using Solve(rank_deficiency=...).\")\n",
"/home/thuerey/anaconda3/envs/torch24/lib/python3.12/site-packages/phiml/math/_optimize.py:631: UserWarning: Possible rank deficiency detected. Matrix might be singular which can lead to convergence problems. Please specify using Solve(rank_deficiency=...).\n", "/usr/local/lib/python3.10/dist-packages/phiml/math/_optimize.py:631: UserWarning: Possible rank deficiency detected. Matrix might be singular which can lead to convergence problems. Please specify using Solve(rank_deficiency=...).\n",
" warnings.warn(\"Possible rank deficiency detected. Matrix might be singular which can lead to convergence problems. Please specify using Solve(rank_deficiency=...).\")\n", " warnings.warn(\"Possible rank deficiency detected. Matrix might be singular which can lead to convergence problems. Please specify using Solve(rank_deficiency=...).\")\n",
"Sim. only: 100%|██████████████| 100/100 [00:23<00:00, 4.22it/s]\n" "Sim. only: 100%|██████████████| 100/100 [00:50<00:00, 1.99it/s]\n"
] ]
}, },
{ {
"name": "stdout",
"output_type": "stream", "output_type": "stream",
"name": "stdout",
"text": [ "text": [
"Running test with Re=\u001b[94m1171.875\u001b[0m, With corr.\n" "Running test with Re=\u001b[94m1171.875\u001b[0m, With corr.\n"
] ]
}, },
{ {
"name": "stderr",
"output_type": "stream", "output_type": "stream",
"name": "stderr",
"text": [ "text": [
"With corr.: 100%|█████████████| 100/100 [00:40<00:00, 2.49it/s]" "With corr.: 100%|█████████████| 100/100 [01:53<00:00, 1.14s/it]"
] ]
}, },
{ {
"output_type": "stream",
"name": "stdout", "name": "stdout",
"output_type": "stream",
"text": [ "text": [
"Rel. L2 errors: low-fidelity: 0.13536353854462504 corrected: 0.03418217146769166\n" "Rel. L2 errors: low-fidelity: 0.13708033837378025 corrected: 0.03381159909069538\n"
] ]
}, },
{ {
"name": "stderr",
"output_type": "stream", "output_type": "stream",
"name": "stderr",
"text": [ "text": [
"\n" "\n"
] ]
@@ -890,12 +959,14 @@
"\n", "\n",
"err_lowfid_only, prediction_lowfid_only, refs, _ = run_sim(input, targets, ROLLOUT_STEPS)\n", "err_lowfid_only, prediction_lowfid_only, refs, _ = run_sim(input, targets, ROLLOUT_STEPS)\n",
"err_corrected, prediction_corrected , _ , corrs = run_sim(input, targets, ROLLOUT_STEPS, network)\n", "err_corrected, prediction_corrected , _ , corrs = run_sim(input, targets, ROLLOUT_STEPS, network)\n",
"print(\"Rel. L2 errors: low-fidelity:\", float(np.mean(err_lowfid_only)),\" corrected:\", float(np.mean(err_corrected)) )" "print(\"\\n Rel. L2 errors: low-fidelity:\", float(np.mean(err_lowfid_only)),\" corrected:\", float(np.mean(err_corrected)) )"
] ]
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"metadata": {}, "metadata": {
"id": "syC2KPDS1FoJ"
},
"source": [ "source": [
"Now we'll plot and compare the two versions in more detail. The next graph shows how the errors evolve over time. The relative errors of the low-fidelity solver rise linearly over time, while the hybrid solver yields a much slower increase. For larger networks and successful training runs, it can pretty much suppress any increase, and keep the errors at a very low level. This indicates, that it can successfully nudge the low-fidelity solver to preserve the accuracy of the targets. Note that this job would be much more difficult without the base solver: then the NN would need to do _all_ the work. Here, it can rely on the prediction of the coupled solver, and a small correction typically suffices." "Now we'll plot and compare the two versions in more detail. The next graph shows how the errors evolve over time. The relative errors of the low-fidelity solver rise linearly over time, while the hybrid solver yields a much slower increase. For larger networks and successful training runs, it can pretty much suppress any increase, and keep the errors at a very low level. This indicates, that it can successfully nudge the low-fidelity solver to preserve the accuracy of the targets. Note that this job would be much more difficult without the base solver: then the NN would need to do _all_ the work. Here, it can rely on the prediction of the coupled solver, and a small correction typically suffices."
] ]
@@ -903,24 +974,31 @@
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 16, "execution_count": 16,
"metadata": {}, "metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 466
},
"id": "ys_qAMGu1FoK",
"outputId": "02dc5fa1-62e9-4f24-cce6-051bd644c30e"
},
"outputs": [ "outputs": [
{ {
"name": "stdout",
"output_type": "stream", "output_type": "stream",
"name": "stdout",
"text": [ "text": [
"MAE for low-fidelity: 0.13536353854462504 , and hybrid: 0.03418217146769166\n" "MAE for low-fidelity: 0.13708033837378025 , and hybrid: 0.03381159909069538\n"
] ]
}, },
{ {
"output_type": "display_data",
"data": { "data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAkAAAAGwCAYAAABB4NqyAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjkuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8hTgPZAAAACXBIWXMAAA9hAAAPYQGoP6dpAABg2ElEQVR4nO3dd3hT1f8H8He6ku69Zwpl7xZqAcFRrYoiigjIKIgoCAhUQFBZ6teCyhQEAWUJUlBBAUGxDEU2CAgdrO690z2S+/sjP26NDJuSNm3zfj1PnrYnyc0nF2jenHPuORJBEAQQERERGRAjfRdARERE1NgYgIiIiMjgMAARERGRwWEAIiIiIoPDAEREREQGhwGIiIiIDA4DEBERERkcE30X0BSpVCqkp6fD2toaEolE3+UQERFRHQiCgOLiYnh4eMDI6P59PAxAd5Geng5vb299l0FERET1kJKSAi8vr/s+hgHoLqytrQGoT6CNjY2eqyEiIqK6UCgU8Pb2Fj/H74cB6C5uD3vZ2NgwABERETUzdZm+wknQREREZHAYgIiIiMjgMAARERGRweEcoAegVCpRXV2t7zIMjqmpKYyNjfVdBhERNWMMQPUgCAIyMzNRWFio71IMlp2dHdzc3LhOExER1QsDUD3cDj8uLi6wsLDgh3AjEgQBZWVlyM7OBgC4u7vruSIiImqOGIC0pFQqxfDj6Oio73IMkrm5OQAgOzsbLi4uHA4jIiKtcRK0lm7P+bGwsNBzJYbt9vnnHCwiIqoPBqB64rCXfvH8ExHRg2AAIiIiIoPDAEREREQGhwGIiIiIDA4DkAHJycnBxIkT4ePjA6lUCjc3N4SFheHPP//Ud2lERGQgYmLKMXZsIqKi8vVaBy+DNyCDBw9GVVUVNm/eDH9/f2RlZSE6Ohp5eXkN9ppVVVUwMzNrsOMTEVHz8OefJVi8OAt79xYBAC5cKMfLL9vr7aIW9gAZiMLCQvzxxx9YvHgxHn30Ufj6+qJXr16YM2cOBg4cCABITk7G888/DysrK9jY2ODll19GVlaWeIwxY8Zg0KBBGsedNm0aHnnkEfHnRx55BJMnT8a0adPg5OSEsLAwAMDVq1fx7LPPwsbGBtbW1nj44Ydx8+ZN8XkbNmxA+/btIZPJ0K5dO3zxxRcNdzKIiKhRqFQC9u4tRN++8ejb95oYfgAgObkKN29W6q029gDpSFBQHDIzG3dNGjc3U5w7165Oj7WysoKVlRX27NmDhx56CFKpVON+lUolhp9jx46hpqYGkyZNwtChQ3H06FGt6tq8eTMmTpwoDq2lpaWhX79+eOSRR3D48GHY2Njgzz//RE1NDQBg27ZtmDdvHlatWoXu3bvjr7/+wvjx42FpaYnw8HCtXpuIiPSvqkqFbdsK8OmnWYiNrdC4z8vLFBERLnjtNSdYW+tvIVsGIB3JzKxGWlrTXZTPxMQEmzZtwvjx47F27Vr06NED/fv3x7Bhw9ClSxdER0fj77//RkJCAry9vQEAW7ZsQceOHXH27Fn07Nmzzq8VEBCATz75RPz53Xffha2tLXbs2AFTU1MAQJs2bcT758+fjyVLluDFF18EAMjlcsTExODLL79kACIiakYUCiXWrcvFsmXZSE/X/Ezs0EGGWbNcMXy4PczM9D8AxQCkI25upk3+NQcPHowBAwbgjz/+wKlTp3DgwAF88skn2LBhAxQKBby9vcXwAwAdOnSAnZ0dYmNjtQpAgYGBGj9fvHgRDz/8sBh+/qm0tBQ3b97EuHHjMH78eLG9pqYGtra2Wr0/IiLSj4KCGqxcmYPly7NRWKjUuO/hh60wa5YrnnnGBkZGTWcRWwYgHanrUJS+yWQyPPHEE3jiiScwd+5cvPbaa5g/fz7efvvt/3yukZERBEHQaLvbVhSWlpYaP9/eu+tuSkpKAADr169HcHCwxn3c44uIqGnLza3BsmVZWLUqBwqFSmyXSIBBg2wxc6YrQkKs9FjhvTEAGbgOHTpgz549aN++PVJSUpCSkiL2AsXExKCwsBAdOnQAADg7O+PKlSsaz7948eJde3b+qUuXLti8eTOqq6vveKyrqys8PDxw69YtjBgxQofvjIiIGkppqRKffZaNTz/NQmlpbfAxNgZGjXLA7NluaNtWpscK/5v+B+GoUeTl5eGxxx7DN998g8uXLyMhIQG7du3CJ598gueffx6hoaHo3LkzRowYgQsXLuDMmTMYPXo0+vfvj6CgIADAY489hnPnzmHLli24fv065s+ff0cgupvJkydDoVBg2LBhOHfuHK5fv46tW7ciPj4eALBw4UJERkZi5cqVuHbtGv7++29s3LgRS5cubdBzQkRE2lEqBWzYkIuAgBgsWJAhhh9TUwlef90J1693xMaNfk0+/AAMQAbDysoKwcHBWLZsGfr164dOnTph7ty5GD9+PFatWgWJRIIff/wR9vb26NevH0JDQ+Hv74+oqCjxGGFhYZg7dy5mzZqFnj17ori4GKNHj/7P13Z0dMThw4dRUlKC/v37IzAwEOvXrxd7g1577TVs2LABGzduROfOndG/f39s2rQJcrm8wc4HERHVnSAIOHCgCN26xWL8+GRkZKinP5iYABMnOuHmzY748ksfyOXS/zhS0yER/j2pg6BQKGBra4uioiLY2Nho3FdRUYGEhATI5XLIZE0/4bZU/HMgImocZ8+W4p130nDkSIlG+wsv2GLRIk+0adN0fgff7/P73zgHiIiIiO5w/XoF3nsvHbt2FWq09+plgc8+88LDDzfNyc11xQBEREREosLCGixYkIHVq3Pw/+vVAgBatZLif/9z1+v2FbrEAERERERQKgV89VUe3nsvHbm5tcnHxcUE8+e7Y/x4J5iaNv/gcxsDEBERkYH7/fdiTJ2aiosXy8U2c3MJZs1yxYwZrrCyannrsjEAERERGagrV8rx7rvpGpuUAsCwYfb45BNPeHub6amyhscAREREZGCSk6swf346tmzJh6p2HUN0726OFSu8m/0E57pgACIiIjIQubk1iIzMxOrVOaisrF0Fx8vLFAsXuiM83BHGxi1nns/9MAARERG1cMXFSixdmo0lS7JQXFzb5WNnZ4x333XD5MnOMDc3rLWRDevd0gNLTEyERCLBxYsXtX7uggUL0K1bt/s+ZsyYMRg0aFC9aiMiIk2VlSosX54Nf/+rWLAgQww/MpkEM2e64Natjpg509Xgwg/AAGRQ7hUujh49ColEgsLCwgZ9/RkzZiA6OrpBX4OIiNRbV/zwQwE6dozF9Omp4mXtJibAG2844caNjvjkEy/Y2xvuQJDhvnNqNIIgQKlUwsrKClZWLX9iHRGRPp07V4qIiDT88Uft1hUSCTB8uD0WLnRH69ZNZ+sKfWIPEIlKS0thY2OD7777TqN9z549sLS0RHFxsdgWFxeH3r17QyaToVOnTjh27Jh43+0epQMHDiAwMBBSqRTHjx+/YwhMqVQiIiICdnZ2cHR0xKxZs8Ct6YiI6icjoxpjxiSiZ894jfDzyCNWOH++HbZtkzP8/AMDEIksLS0xbNgwbNy4UaN948aNeOmll2BtbS22zZw5E2+//Tb++usvhISE4LnnnkNeXp7G82bPno1FixYhNjYWXbp0ueP1lixZgk2bNuHrr7/G8ePHkZ+fj927dzfMmyMiaqEqK1VYvDgTbdpcxebN+WJ7QIAUe/b44/DhAHTvbqHHCpsmDoHpSNC6IGSWZDbqa7pZueHc6+e0es6+ffvuGIZSKpXi96+99hp69+6NjIwMuLu7Izs7Gz///DN+++03jedMnjwZgwcPBgCsWbMGBw8exFdffYVZs2aJj/nggw/wxBNP3LOW5cuXY86cOXjxxRcBAGvXrsUvv/yi1fshIjJUgiBg374iRESk4caNSrHdzs4Y8+e74803nWBmxn6Oe2EA0pHMkkykFafpu4z/9Oijj2LNmjUabadPn8bIkSMBAL169ULHjh2xefNmzJ49G9988w18fX3Rr18/jeeEhISI35uYmCAoKAixsbEajwkKCrpnHUVFRcjIyEBwcPAdx+EwGBHR/cXFVWDatFT88otCbDMyAl5/3QkffOAOZ2dTPVbXPDAA6YiblVuzeE1LS0u0bt1aoy01NVXj59deew2rV6/G7NmzsXHjRowdO7ZeO/9aWlpq/RwiIrq3wsIafPBBJj7/PFtjp/b+/a2wYoUXunblUFddMQDpiLZDUU3ZyJEjMWvWLKxcuRIxMTEIDw+/4zGnTp0Se4Vqampw/vx5TJ48uc6vYWtrC3d3d5w+ffqO4/To0UM3b4SIqIUQBAGbNuXjnXfSkJNTm3x8fMzw2WeeeOklu3r9R9WQMQDRHezt7fHiiy9i5syZePLJJ+Hl5XXHY1avXo2AgAC0b98ey5YtQ0FBAV599VWtXmfq1KlYtGgRAgIC0K5dOyxdurTB1yIiImpu4uIq8MYbyfj999oru2QyCWbPdsPMma6wsOA8n/rgWaO7GjduHKqqqu4ZahYtWoRFixaha9euOH78OH766Sc4OTlp9Rpvv/02Ro0ahfDwcISEhMDa2hovvPCCLsonImr2KitVWLAgHV27xmqEn5deskNcXAfMn+/O8PMAJAJnnN5BoVDA1tYWRUVFsLGx0bivoqICCQkJkMvlkMla7noKW7duxfTp05Geng4zMzN9l3MHQ/lzICLDdPhwMd58Mxnx8bVXd8nlZlizxgdhYTb3eaZhu9/n979xCIw0lJWVISMjA4sWLcIbb7zRJMMPEVFLlZ5ehbffTsOOHQVim7ExMGOGK+bNY4+PLvFMkoZPPvkE7dq1g5ubG+bMmaPvcoiIDEJNjYBly7LQrl2MRvh56CFLXLjQDosWeTL86BjPJmlYsGABqqurER0dzX27iIgawYkTJQgMjENERJq4W7ujozHWr/fBn3+2QZcuvLS9IXAIjIiISA/y82swe3Ya1q+v3UZIIgFee80RkZGecHTLine truncated
"text/plain": [ "text/plain": [
"<Figure size 640x480 with 1 Axes>" "<Figure size 640x480 with 1 Axes>"
] ],
"image/png": "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 truncated
}, },
"metadata": {}, "metadata": {}
"output_type": "display_data"
} }
], ],
"source": [ "source": [
@@ -928,14 +1006,14 @@
"pltx = np.linspace(0,ROLLOUT_STEPS-1,ROLLOUT_STEPS)\n", "pltx = np.linspace(0,ROLLOUT_STEPS-1,ROLLOUT_STEPS)\n",
"fig.plot(pltx, err_lowfid_only, lw=2, color='mediumblue', label='Source')\n", "fig.plot(pltx, err_lowfid_only, lw=2, color='mediumblue', label='Source')\n",
"fig.plot(pltx, err_corrected, lw=2, color='green', label='Hybrid')\n", "fig.plot(pltx, err_corrected, lw=2, color='green', label='Hybrid')\n",
"pylab.xlabel('Time step'); pylab.ylabel('Relative L2 error'); fig.legend()\n", "pylab.xlabel('Time step'); pylab.ylabel('Relative L2 error'); fig.legend()\n"
"\n",
"print(\"MAE for low-fidelity: \",np.mean(err_lowfid_only),\" , and hybrid: \",np.mean(err_corrected) )"
] ]
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"metadata": {}, "metadata": {
"id": "eDK3M93b1FoK"
},
"source": [ "source": [
"While the quantified results give an important summary of the performance of our Neural operator, it's important to sanity check these results to make sure the NN works as intended. In the next cell, we'll plot the states of the reference, the low-fidelity solver and the hybrid solver side-by-side. Additionally, we'll plot the errors made by both solvers on the right side." "While the quantified results give an important summary of the performance of our Neural operator, it's important to sanity check these results to make sure the NN works as intended. In the next cell, we'll plot the states of the reference, the low-fidelity solver and the hybrid solver side-by-side. Additionally, we'll plot the errors made by both solvers on the right side."
] ]
@@ -943,17 +1021,24 @@
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 17, "execution_count": 17,
"metadata": {}, "metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 471
},
"id": "MZnqSzq21FoK",
"outputId": "14037f18-44e4-4d3a-c0bd-0caeb384513b"
},
"outputs": [ "outputs": [
{ {
"output_type": "display_data",
"data": { "data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAABhQAAAHqCAYAAADs06STAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjkuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8hTgPZAAAACXBIWXMAAA9hAAAPYQGoP6dpAAEAAElEQVR4nOzde3wU1d0/8M/M7C0JJAgCAeXmDbwBCgVR8AGbGvFSKdQLj1ZExdaKVVJF8bFc1IpaK2hLRRQFbRWl9VJ/VLygKFqQitKqLRQsFUQSAYWQQPY28/sDszJn53uW3UxIwn7evOb1YmfmzJyZnT3fOTkz5xiO4zggIiIiIiIiIiIiIiLSMJs6A0RERERERERERERE1PyxQYGIiIiIiIiIiIiIiDJigwIREREREREREREREWXEBgUiIiIiIiIiIiIiIsqIDQpERERERERERERERJQRGxSIiIiIiIiIiIiIiCgjNigQEREREREREREREVFGbFAgIiIiIiIiIiIiIqKM2KBAREREREREREREREQZsUGBDoh169bhzDPPRElJCQzDwAsvvNDUWSIiohbgV7/6FY444ghYloW+ffsCALp3747LL788Y9p58+bBMAz897//bdQ8EhEREREREeULNihQmvo/wNRPgUAAhx12GC6//HJs3rw5p22OGTMGH330EX75y1/iySefRP/+/X3ONRER5aq+3H///febOisur776KiZOnIjTTjsNjz/+OO66666mzhIREfns008/xY9//GMcccQRiEQiKC4uxmmnnYYHHngAe/bsaersEREREZEi0NQZoObr9ttvR48ePVBXV4cVK1Zg3rx5eOedd/Dxxx8jEons93b27NmD5cuX4//+7/8wfvz4RswxEREdTN544w2Ypom5c+ciFAql5q9duxamyWciiIhaukWLFuGCCy5AOBzGZZddhhNOOAGxWAzvvPMObrrpJnzyySeYM2dOU2eTiIiIiPbBBgUSDR8+PPUmwVVXXYVDDz0U99xzD/785z/jwgsv3O/tbN26FQDQpk2bxsgmEREdpL788ksUFBS4GhMAIBwON1GOiIjILxs2bMDFF1+Mbt264Y033kCnTp1Sy6699lqsX78eixYtatA+HMdBXV0dCgoK0pbV1dUhFAqxgZqIiIgoS7x7ov02ZMgQAHtfS663Zs0a/PCHP0Tbtm0RiUTQv39//PnPf04tnzp1Krp16wYAuOmmm2AYBrp3735A801ERA334YcfYvjw4SguLkarVq3w3e9+FytWrEgt37FjByzLwoMPPpiat23bNpimiXbt2sFxnNT8a665BqWlpdr9GYaBxx9/HLW1taku+ObNmwfAewyFTz75BGeccQYKCgpw+OGH484774Rt2w0/cCIiahT33nsvampqMHfuXFdjQr2jjjoK119/PQAgkUjgjjvuwJFHHolwOIzu3bvj1ltvRTQadaXp3r07zj33XLzyyivo378/CgoK8PDDD2Pp0qUwDAMLFizAbbfdhsMOOwyFhYWorq4+IMdKREREdDDhGwq03+oHtTzkkEMA7P3jzWmnnYbDDjsMt9xyC4qKivDss89ixIgR+NOf/oQf/OAHGDlyJNq0aYMJEyZg9OjROPvss9GqVasmPAoiIsrWJ598giFDhqC4uBgTJ05EMBjEww8/jKFDh+Ktt97CwIED0aZNG5xwwgl4++238bOf/QwA8M4778AwDHz11Vf45z//ieOPPx4AsGzZslQjteTJJ5/EnDlzsHLlSjz66KMAgFNPPdVz3crKSgwbNgyJRCIVj+bMmeP5RCoRETUPL730Eo444gixbN/XVVddhfnz5+OHP/whfv7zn+O9997D9OnT8a9//QvPP/+8a921a9di9OjR+PGPf4xx48ahZ8+eqWV33HEHQqEQbrzxRkSj0bQ34IiIiIgoMzYokGjnzp3Ytm0b6urq8N5772HatGkIh8M499xzAQDXX389unbtir/97W+p7id++tOfYvDgwbj55pvxgx/8AL1790ZxcTEmTJiAk08+GZdeemlTHhIREeXgtttuQzwexzvvvIMjjjgCAHDZZZehZ8+emDhxIt566y0Ae99k++Mf/5hKt2zZMgwePBhr1qzBsmXLcPzxx6caF66++mrtPi+99FK8/vrr+OCDDzLGjnvuuQdbt27Fe++9hwEDBgAAxowZg6OPProhh01ERI2kuroamzdvxvnnn59x3b///e+YP38+rrrqKjzyyCMA9tY5OnTogPvuuw9vvvkmhg0bllp//fr1WLx4McrLy1Pzli5dCmBvN0fvv/8+G5yJiIiIGoBdHpGorKwM7du3R5cuXfDDH/4QRUVF+POf/4zDDz8cX331Fd544w1ceOGF2LVrF7Zt24Zt27Zh+/btKC8vx7p167B58+amPgQiImqgZDKJV199FSNGjEg1JgBAp06d8L//+7945513Ul1GDBkyBFVVVVi7di2AvQ0Kp59+OoYMGYJly5YB2PvWguM4Gd9QyMZf/vIXnHLKKanGBABo3749LrnkEt/2QURE/qmPG61bt8647l/+8hcAQEVFhWv+z3/+cwBIG2ehR48ersaEfY0ZM4aNCUREREQNxAYFEs2aNQuvvfYa/vjHP+Lss8/Gtm3bUm8irF+/Ho7j4Be/+AXat2/vmqZMmQJg72CaRETUsm3duhW7d+92dRlR79hjj4Vt29i0aROAb8faWbZsGWpra/Hhhx9iyJAhOP3001MNCsuWLUNxcTH69OkDAKipqUFlZWVq2rp1a9Z5/OyzzzzfRvDKMxERNb3i4mIAwK5duzKu+9lnn8E0TRx11FGu+aWlpWjTpg0+++wz1/wePXqI29ItIyIiIqL9wy6PSDRgwAD0798fADBixAgMHjwY//u//4u1a9emBrq88cYbxSeA1Jt+IiI6uHXu3Bk9evTA22+/je7du8NxHAwaNAjt27fH9ddfj88++wzLli3DqaeeCtPc+0zDfffdh2nTpqW20a1bt9SYPUREdHAqLi5G586d8fHHH+93GsMw9ms93RsIfDuBiIiIqOHYoED7xbIsTJ8+HcOGDcNvf/tbXHHFFQCAYDCIsrKyJs4dERE1lvbt26OwsDDVjdG+1qxZA9M00aVLl9S8IUOG4O2330aPHj3Qt29ftG7dGn369EFJSQkWL16MDz74wNWAcNlll2Hw4MGpz7n8sadbt25Yt25d2nyvPBMRUfNw7rnnYs6cOVi+fDkGDRokrtetWzfYto1169bh2GOPTc2vqqrCjh070K1btwORXSIiIiL6Brs8ov02dOhQDBgwADNnzkRxcTGGDh2Khx9+GFu2bElbN5cuK4iIqPmxLAtnnnkmXnzxRdebA1VVVXjqqacwePDgVNcVwN4Ghf/+97945plnUl0gmaaJU089Fffffz/i8bhr/IQjjjgCZWVlqem0007LOo9nn302VqxYgZUrV6bmbd26FX/4wx/S1t2yZQvWrFmDeDye9X6IiMg/EydORFFREa666ipUVVWlLf/000/xwAMP4OyzzwYAzJw507X8/vvvBwCcc845OeeBMYGIiIgoe3xDgbJy00034YILLsC8efMwa9YsDB48GCeeeCLGjRuHI444AlVVVVi+fDk+//xz/P3vf2/q7BIRURYee+wxLF68OG3+1KlT8dprr2Hw4MH46U9/ikAggIcffhjRaBT33nuva936xoK1a9firrvuSs0//fTT8fLLLyMcDuM73/mOr/meOHEinnzySZx11lm4/vrrUVRUhDlz5qBbt274xz/+4Vp30qRJmD9/PjZs2IDu3bv7mg8iItp/Rx55JJ566ilcdNFFOPbYY3HZZZfhhBNOQCwWw1//+lcsXLgQl19+Oa6//nqMGTMGc+bMwY4dO/A///M/WLlyJebPn48RI0Zg2LBhOeeBMYGIiIgoe2xQoKyMHDkSRx55JO677z6MGzcO77//PqZNm4Z58+Zh+/bt6NChA0466SRMnjy5qbNKRERZeuihhzznX3755Vi2bBkmTZqE6dOnw7ZtDBw4EL///e8xcOBA17o9e/ZEhw4d8OWXX7q6MqpvaBgwYADC4bCv+e7UqRPefPNNXHfddbj77rvRrl07/OQnP0Hnzp1x5ZVX+rovIiLyz/e//3384x//wK9+9Su8+OKLeOihhxAOh9G7d2/8+te/xrhx4wAAjz76KI444gjMmzcPzz//PEpLSzFp0iRMmTKliY+AiIiIKP8YjuM4TZ0JIiIiIiIiIiIiIiJq3jiGAhERERERERERERERZcQGBSIiIiIiIiIiIiIiyogNCkRERERERERERERElBEbFIiIiIiIiIiIiIiIKCM2KBARERERERERERERUUZsUCAiIiIiIiIiIiIioowCTZ0BlW3b+OKLL9C6dWsYhtHU2SE6qDiOg127dqFz584wzdzaE+vq6hCLxXzNVygUQiQS8XWblL8YR4gaB2MI5QPGEKLG4UcMARhHiIgod4wh/ml2DQpffPEFunTp0tTZIDqobdq0CYcffnjW6erq6tCjx2GorPzK1/yUlpZiw4YNeVkIk/8YR4gaF2MIHcwYQ4gaV64xBGAcISKi3NXV1aFHt2JUfhn3dbv5GkOaXYNC69atAQD/+P4P0ToYTFte1CXpndCWt+kkhCTCfF2a+G75SaXYHu/TWVsbFtNU13kv+0qYDwBfx9PPS72dccs7D5pjTTrexxQ0HTFNK+HKKY3ILX3di3d5zu90+E4xTcHRIc/51uFtxDRo00peFpbPncgWLq6kcC0CgMe1q92WZntO5ddikk/+4P3d3fJ37y8o4cSwYtec1O8sW7FYDJWVX+G/nz2L4uLCnLahqq7eje7dLkQsFsu7ApgaR/31veS0sSgKpJchXY6Qf1MSMY4k5ZiQjHk/fZeIy0/lxaLev914wrtsB4BYwjtNLCnvJ65Z5iD7J3Itw7tsC1lymRcJeZ/UwkhUTtPLine truncated
"text/plain": [ "text/plain": [
"<Figure size 1600x500 with 8 Axes>" "<Figure size 1600x500 with 8 Axes>"
] ],
"image/png": "iVBORw0KGgoAAAANSUhEUgAABhIAAAHqCAYAAADhzdTUAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/bCgiHAAAACXBIWXMAAA9hAAAPYQGoP6dpAAEAAElEQVR4nOzde3wU1fk/8M/MXpNAiNwS0HBRK3gFhBJRaKFGIyoVoV6oVkShrYpVoqJY5aJ+oVZFbItGFAVtFbVeqj8UL1EKKEgBabUVBERBJBFQCAlkr/P7A7MyZ+c5m72EhOTz9rUv2TlzzpyZ3T3PTM7MOYZlWRaIiIiIiIiIiIiIiIgcmI1dASIiIiIiIiIiIiIiarrYkUBERERERERERERERCJ2JBARERERERERERERkYgdCUREREREREREREREJGJHAhERERERERERERERidiRQEREREREREREREREInYkEBERERERERERERGRiB0JREREREREREREREQkYkcCERERERERERERERGJ2JFAh8SGDRtw9tlno02bNjAMA6+88kpjV4mIiA4z9913H44++mi4XC707t0bANCtWzdceeWVCfPOmzcPhmHgiy++aNA6EhERERERETVH7EigOHV/bKl7ud1uHHnkkbjyyiuxbdu2lMocPXo0Pv74Y/zf//0fnn76afTr1y/DtSYiokyoiwGrVq1q7KrYvPXWW5g4cSLOOOMMPPnkk5g+fXpjV4mIiBrApk2b8Jvf/AZHH300/H4/cnNzccYZZ+Chhx7C/v37G7t6RERERC2Wu7ErQE3XXXfdhe7du6O2thYrVqzAvHnzsGzZMnzyySfw+/31Lmf//v1Yvnw5fv/732P8+PENWGMiImqu3n33XZimiblz58Lr9caWr1+/HqbJ+yKIiJqDhQsX4qKLLoLP58MVV1yBk046CcFgEMuWLcMtt9yC//73v5gzZ05jV5OIiIioRWJHAomGDh0ae3Jg7NixaN++Pe699168+uqruPjii+tdzo4dOwAAeXl5DVFNIiJqAb755htkZWXZOhEAwOfzNVKNiIgokzZv3oxLL70UXbt2xbvvvotOnTrF0q677jps3LgRCxcuTGsblmWhtrYWWVlZcWm1tbXwer3snCYiIiIS8CyJ6m3QoEEADjxuXGfdunX4xS9+gbZt28Lv96Nfv3549dVXY+lTp05F165dAQC33HILDMNAt27dDmm9iYgosz766CMMHToUubm5aNWqFc4880ysWLEilr579264XC786U9/ii3buXMnTNNEu3btYFlWbPk111yDgoIC7fYMw8CTTz6Jmpqa2LB78+bNA+A8R8J///tf/OxnP0NWVhaOOuoo3HPPPYhGo+nvOBERNZg//vGPqK6uxty5c22dCHWOPfZY3HDDDQCAcDiMu+++G8cccwx8Ph+6deuG22+/HYFAwJanW7duOP/88/Hmm2+iX79+yMrKwqOPPorFixfDMAwsWLAAd9xxB4488khkZ2ejqqrqkOwrERER0eGITyRQvdVNUHnEEUcAOPCHmjPOOANHHnkkbrvtNuTk5OD555/H8OHD8eKLL+LCCy/EiBEjkJeXhwkTJmDUqFE499xz0apVq0bcCyIiSsd///tfDBo0CLm5uZg4cSI8Hg8effRRDB48GP/85z9RVFSEvLw8nHTSSViyZAl+97vfAQCWLVsGwzDw7bff4n//+x9OPPFEAMDSpUtjHdWSp59+GnPmzMHKlSvx+OOPAwBOP/10x3UrKiowZMgQhMPhWGyaM2eO492nRETUdLz22ms4+uijxfb9YGPHjsX8+fPxi1/8AjfddBM+/PBDzJgxA59++ilefvll27rr16/HqFGj8Jvf/Abjxo1Djx49Yml33303vF4vbr75ZgQCgbin3oiIiIjoB+xIINGePXuwc+dO1NbW4sMPP8S0adPg8/lw/vnnAwBuuOEGdOnSBf/6179iQ0tce+21GDhwIG699VZceOGFOOWUU5Cbm4sJEybg1FNPxeWXX96Yu0RERGm64447EAqFsGzZMhx99NEAgCuuuAI9evTAxIkT8c9//hPAgafY/v73v8fyLV26FAMHDsS6deuwdOlSnHjiibFOhV//+tfabV5++eV45513sGbNmoRx5N5778WOHTvw4Ycfon///gCA0aNH40c/+lE6u01ERA2oqqoK27ZtwwUXXJBw3X//+9+YP38+xo4di8ceewzAgWuQjh074v7778d7772HIUOGxNbfuHEjFi1ahJKSktiyxYsXAzgwnNGqVavY2UxERERUDxzaiETFxcXo0KEDCgsL8Ytf/AI5OTl49dVXcdRRR+Hbb7/Fu+++i4svvhh79+7Fzp07sXPnTuzatQslJSXYsGEDtm3b1ti7QEREGRSJRPDWW29h+PDhsU4EAOjUqRN++ctfYtmyZbFhIQYNGoTKykqsX78ewIGOhJ/85CcYNGgQli5dCuDAUwqWZSV8IiEZr7/+Ok477bRYJwIAdOjQAZdddlnGtkFERJlVFztat26dcN3XX38dAFBaWmpbftNNNwFA3DwK3bt3t3UiHGz06NHsRCAiIiKqJ3YkkGj27Nl4++238fe//x3nnnsudu7cGXvyYOPGjbAsC3feeSc6dOhge02ZMgXAgYkxiYio+dixYwf27dtnGxaizvHHH49oNIqtW7cC+GFenaVLl6KmpgYfffQRBg0ahJ/85CexjoSlS5ciNzcXvXr1AgBUV1ejoqIi9tqxY0fSdfzyyy8dnz5wqjMRETUNubm5AIC9e/cmXPfLL7+EaZo49thjbcsLCgqQl5eHL7/80ra8e/fuYlm6NCIiIiKy49BGJOrfvz/69esHABg+fDgGDhyIX/7yl1i/fn1s0sqbb75ZvMNHPbknIqKWo3PnzujevTuWLFmCbt26wbIsDBgwAB06dMANN9yAL7/8EkuXLsXpp58O0zxwX8P999+PadOmxcro2rVrbH4eIiJqvnJzc9G5c2d88skn9c5jGEa91tM9ccCnEYiIiIjqjx0JVC8ulwszZszAkCFD8Je//AVXXXUVAMDj8aC4uLiRa0dERIdChw4dkJ2dHRuu6GDr1q2DaZooLCyMLRs0aBCWLFmC7t27o3fv3mjdujV69eqFNm3aYNGiRVizZo2t4+CKK67AwIEDY+9T+QNP165dsWHDhrjlTnUmIqKm4/zzz8ecOXOwfPlyDBgwQFyva9euiEaj2LBhA44//vjY8srKSuzevRtdu3Y9FNUlIiIianE4tBHV2+DBg9G/f3/MmjULubm5GDx4MB599FFs3749bt1UhqMgIqKmzeVy4eyzz8Y//vEP25MClZWVeOaZZzBw4MDY8BTAgY6EL774As8991xsqCPTNHH66adj5syZCIVCtvkRjj76aBQXF8deZ5xxRtJ1PPfcc7FixQqsXLkytmzHjh3429/+Frfu9u3bsW7dOoRCoaS3Q0REmTVx4kTk5ORg7NixqKysjEvftGkTHnroIZx77rkAgFmzZtnSZ86cCQA477zzUq4D4wIRERGRjE8kUFJuueUWXHTRRZg3bx5mz56NgQMH4uSTT8a4ceNw9NFHo7KyEsuXL8dXX32Ff//7341dXSIiStETTzyBRYsWxS2fOnUq3n77bQwcOBDXXnst3G43Hn30UQQCAfzxj3+0rVvXSbB+/XpMnz49tvwnP/kJ3njjDfh8Pvz4xz/OaL0nTpyIp59+Gueccw5uuOEG5OTkYM6cOejatSv+85//2NadNGkS5s+fj82bN6Nbt24ZrQcRESXnmGOOwTPPPINLLrkExx9/PK644gqcdNJJCAaD+OCDD/DCCy/gyiuvxA033IDRo0djzpw52L17N376059i5cqVmD9/PoYPH44hQ4akXAfGBSIiIiIZOxIoKSNGjMAxxxyD+++/H+PGjcOqVaswbdo0zJs3D7t27ULHjh3Rp08fTJ48ubGrSkREaXjkkUccl1955ZVYunQpJk2ahBkzZiAajaKoqAh//etfUVRUZFu3R48e6NixI7755hvbkEV1HQz9+/eHz+fLaL07deqE9957D9dffz3+8Ic/oF27dvjtb3+Lzp074+qrr87otoiIKLN+/vOf4z//+Q/uu+8+/OMf/8AjjzwCn8+HU045BQ888ADGjRsHAHj88cdx9NFHY968eXj55ZdRUFCASZMmYcqUKY28B0RERETNl2FZltXYlSAiIiIiIiIiIiIioqaJcyQQEREREREREREREZGIHQlERERERERERERERCRiRwIREREREREREREREYnYkUBERERERERERERERCJ2JBARERERERERERERkYgdCUREREREREREREREJHI3dgVU0WgUX3/9NVq3bg3DMBq7OkTNimVZ2Lt3Lzp37gzTTK0fsba2FsFgMKP18nq98Pv9GS2TiPGEqGFkIpYAjCd0eGAsIWoYjCVERNRUNEQsAZpnPGlyHQlff/01CgsLG7saRM3a1q1bcdRRRyWdr7a2Ft27H4mKim8zWp+CggJs3ry52TWw1LgYT4gaVqqxBGA8ocMHYwlRw2IsISKixlRbW4vuXXNR8U0o42U3x3jS5DoSWrduDQBYceYv0crtjUs/avyRzhmzNB+KIdzhYMp3FVm++G0DAPw+eTtuj5wmCQYcFxu7vhOzWJ9uFdP2LK92XL52Uycxz7/3ZDkur6wVsyBqOS9vIxw2AMjzOGc6QlgOAEd4w8JyuafwiCy54q2zndP8reTyPH7n+pmar4IpHAdD84sz3Mnf5bZ3k8tx+RXlbR2Xh60gVuydE/udJSsYDKKi4lt88eXzyM3NTqkMVVXVPnTrejGCwWCzalyp8dV9z1/p92vkOMSTfpfud8xnHOn8+wEAuJx/c9qBAqPScikBQERIC8htlbXPOZ5Ye+Q2Mfqdcx4ACH/nXIfa3XJbVVvt3PjtD8jBoTbo3DCGovJBteSwILine truncated
}, },
"metadata": {}, "metadata": {}
"output_type": "display_data"
} }
], ],
"source": [ "source": [
@@ -997,7 +1082,9 @@
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"metadata": {}, "metadata": {
"id": "VCs1K3uo1FoK"
},
"source": [ "source": [
"This shows very clearly how the pure source simulation in the middle deviates from the reference on the left. The learned version stays much closer to the reference solution.\n", "This shows very clearly how the pure source simulation in the middle deviates from the reference on the left. The learned version stays much closer to the reference solution.\n",
"\n", "\n",
@@ -1009,7 +1096,9 @@
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"metadata": {}, "metadata": {
"id": "VuzDHrc21FoL"
},
"source": [ "source": [
"\n", "\n",
"## Next steps\n", "## Next steps\n",
@@ -1024,20 +1113,22 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": 17,
"metadata": {}, "metadata": {
"id": "WyM-UoqA1FoL"
},
"outputs": [], "outputs": [],
"source": [] "source": []
} }
], ],
"metadata": { "metadata": {
"colab": { "colab": {
"collapsed_sections": [], "provenance": [],
"provenance": [] "machine_shape": "hm",
"gpuType": "A100"
}, },
"kernelspec": { "kernelspec": {
"display_name": "Python 3 (ipykernel)", "display_name": "Python 3",
"language": "python",
"name": "python3" "name": "python3"
}, },
"language_info": { "language_info": {
@@ -1051,8 +1142,9 @@
"nbconvert_exporter": "python", "nbconvert_exporter": "python",
"pygments_lexer": "ipython3", "pygments_lexer": "ipython3",
"version": "3.12.4" "version": "3.12.4"
} },
"accelerator": "GPU"
}, },
"nbformat": 4, "nbformat": 4,
"nbformat_minor": 4 "nbformat_minor": 0
} }