Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 72 additions & 0 deletions .github/workflows/export_tutorials.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
name: "Export Tutorials"

on:
push:
branches:
- "**" # Run on push on all branches
paths:
- 'tutorials/**/*.ipynb'

jobs:
export_tutorials:
permissions: write-all
runs-on: ubuntu-latest
env:
TUTORIAL_TIMEOUT: 1200s
steps:
- uses: actions/checkout@v4

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: 3.8

- name: Install dependencies
run: |
# Dependencies for tutorials
python3 -m pip install --upgrade pip .[tutorial] black[jupyter]
- name: Setup FFmpeg
uses: FedericoCarboni/setup-ffmpeg@v2

- id: files
uses: jitterbit/get-changed-files@v1
with:
token: ${{ secrets.GITHUB_TOKEN }}
format: space-delimited

- name: Configure git
run: |
git config user.name "github-actions[bot]"
git config user.email 41898282+github-actions[bot]@users.noreply.github.com
- name: Export tutorials to .py and .html
run: |
set -x
for file in ${{ steps.files.outputs.all }}; do
if [[ $file == *.ipynb ]]; then
filename=$(basename $file)
pyfilename=$(echo ${filename%?????})py
timeout --signal=SIGKILL $TUTORIAL_TIMEOUT python -Xfrozen_modules=off -m jupyter nbconvert --execute $file --to python --output $pyfilename --output-dir=$(dirname $file)
htmlfilename=$(echo ${filename%?????} | sed -e 's/-//g')html
htmldir="docs/source"/$(echo ${file%?????} | sed -e 's/-//g')html
timeout --signal=SIGKILL $TUTORIAL_TIMEOUT python -Xfrozen_modules=off -m jupyter nbconvert --execute $file --to html --output $htmlfilename --output-dir=$htmldir
fi
done
set +x

- name: Run formatter
run: black tutorials/

- uses: benjlevesque/[email protected]
id: short-sha

- name: Remove unwanted files
run: |
rm -rf build/
- name: Create Pull Request
uses: peter-evans/[email protected]
with:
labels: maintenance
title: Export tutorial changed in ${{ steps.short-sha.outputs.sha }}
branch: export-tutorial-${{ steps.short-sha.outputs.sha }}
commit-message: export tutorials changed in ${{ steps.short-sha.outputs.sha }}
delete-branch: true
22 changes: 13 additions & 9 deletions tutorials/tutorial1/tutorial.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -87,25 +87,27 @@
"source": [
"## routine needed to run the notebook on Google Colab\n",
"try:\n",
" import google.colab\n",
" IN_COLAB = True\n",
" import google.colab\n",
"\n",
" IN_COLAB = True\n",
"except:\n",
" IN_COLAB = False\n",
" IN_COLAB = False\n",
"if IN_COLAB:\n",
" !pip install \"pina-mathlab\"\n",
" !pip install \"pina-mathlab\"\n",
"\n",
"import warnings\n",
"\n",
"from pina.problem import SpatialProblem, TimeDependentProblem\n",
"from pina.domain import CartesianDomain\n",
"\n",
"warnings.filterwarnings('ignore')\n",
"warnings.filterwarnings(\"ignore\")\n",
"\n",
"\n",
"class TimeSpaceODE(SpatialProblem, TimeDependentProblem):\n",
" \n",
" output_variables = ['u']\n",
" spatial_domain = CartesianDomain({'x': [0, 1]})\n",
" temporal_domain = CartesianDomain({'t': [0, 1]})\n",
"\n",
" output_variables = [\"u\"]\n",
" spatial_domain = CartesianDomain({\"x\": [0, 1]})\n",
" temporal_domain = CartesianDomain({\"t\": [0, 1]})\n",
"\n",
" # other stuff ..."
]
Expand Down Expand Up @@ -152,6 +154,7 @@
"from pina.domain import CartesianDomain\n",
"from pina.equation import Equation, FixedValue\n",
"\n",
"\n",
"# defining the ode equation\n",
"def ode_equation(input_, output_):\n",
"\n",
Expand All @@ -164,6 +167,7 @@
" # calculate the residual and return it\n",
" return u_x - u\n",
"\n",
"\n",
"class SimpleODE(SpatialProblem):\n",
"\n",
" output_variables = [\"u\"]\n",
Expand Down
128 changes: 85 additions & 43 deletions tutorials/tutorial10/tutorial.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -25,16 +25,17 @@
"source": [
"## routine needed to run the notebook on Google Colab\n",
"try:\n",
" import google.colab\n",
" IN_COLAB = True\n",
" import google.colab\n",
"\n",
" IN_COLAB = True\n",
"except:\n",
" IN_COLAB = False\n",
" IN_COLAB = False\n",
"if IN_COLAB:\n",
" !pip install \"pina-mathlab\"\n",
" # get the data\n",
" !mkdir \"data\"\n",
" !wget \"https://github.com/mathLab/PINA/raw/refs/heads/master/tutorials/tutorial10/data/Data_KS.mat\" -O \"data/Data_KS.mat\"\n",
" !wget \"https://github.com/mathLab/PINA/raw/refs/heads/master/tutorials/tutorial10/data/Data_KS2.mat\" -O \"data/Data_KS2.mat\"\n",
" !pip install \"pina-mathlab\"\n",
" # get the data\n",
" !mkdir \"data\"\n",
" !wget \"https://github.com/mathLab/PINA/raw/refs/heads/master/tutorials/tutorial10/data/Data_KS.mat\" -O \"data/Data_KS.mat\"\n",
" !wget \"https://github.com/mathLab/PINA/raw/refs/heads/master/tutorials/tutorial10/data/Data_KS2.mat\" -O \"data/Data_KS2.mat\"\n",
"\n",
"import torch\n",
"import matplotlib.pyplot as plt\n",
Expand All @@ -46,7 +47,7 @@
"from pina.solver import SupervisedSolver\n",
"from pina.problem.zoo import SupervisedProblem\n",
"\n",
"warnings.filterwarnings('ignore')"
"warnings.filterwarnings(\"ignore\")"
]
},
{
Expand Down Expand Up @@ -106,17 +107,24 @@
],
"source": [
"# load data\n",
"data=io.loadmat(\"data/Data_KS.mat\")\n",
"data = io.loadmat(\"data/Data_KS.mat\")\n",
"\n",
"# converting to label tensor\n",
"initial_cond_train = LabelTensor(torch.tensor(data['initial_cond_train'], dtype=torch.float), ['t','x','u0'])\n",
"initial_cond_test = LabelTensor(torch.tensor(data['initial_cond_test'], dtype=torch.float), ['t','x','u0'])\n",
"sol_train = LabelTensor(torch.tensor(data['sol_train'], dtype=torch.float), ['u'])\n",
"sol_test = LabelTensor(torch.tensor(data['sol_test'], dtype=torch.float), ['u'])\n",
"\n",
"print('Data Loaded')\n",
"print(f' shape initial condition: {initial_cond_train.shape}')\n",
"print(f' shape solution: {sol_train.shape}')"
"initial_cond_train = LabelTensor(\n",
" torch.tensor(data[\"initial_cond_train\"], dtype=torch.float),\n",
" [\"t\", \"x\", \"u0\"],\n",
")\n",
"initial_cond_test = LabelTensor(\n",
" torch.tensor(data[\"initial_cond_test\"], dtype=torch.float), [\"t\", \"x\", \"u0\"]\n",
")\n",
"sol_train = LabelTensor(\n",
" torch.tensor(data[\"sol_train\"], dtype=torch.float), [\"u\"]\n",
")\n",
"sol_test = LabelTensor(torch.tensor(data[\"sol_test\"], dtype=torch.float), [\"u\"])\n",
"\n",
"print(\"Data Loaded\")\n",
"print(f\" shape initial condition: {initial_cond_train.shape}\")\n",
"print(f\" shape solution: {sol_train.shape}\")"
]
},
{
Expand Down Expand Up @@ -151,35 +159,58 @@
"# helper function\n",
"def plot_trajectory(coords, real, no_sol=None):\n",
" # find the x-t shapes\n",
" dim_x = len(torch.unique(coords.extract('x')))\n",
" dim_t = len(torch.unique(coords.extract('t')))\n",
" dim_x = len(torch.unique(coords.extract(\"x\")))\n",
" dim_t = len(torch.unique(coords.extract(\"t\")))\n",
" # if we don't have the Neural Operator solution we simply plot the real one\n",
" if no_sol is None:\n",
" fig, axs = plt.subplots(1, 1, figsize=(15, 5), sharex=True, sharey=True)\n",
" c = axs.imshow(real.reshape(dim_t, dim_x).T.detach(),extent=[0, 50, 0, 64], cmap='PuOr_r', aspect='auto')\n",
" axs.set_title('Real solution')\n",
" c = axs.imshow(\n",
" real.reshape(dim_t, dim_x).T.detach(),\n",
" extent=[0, 50, 0, 64],\n",
" cmap=\"PuOr_r\",\n",
" aspect=\"auto\",\n",
" )\n",
" axs.set_title(\"Real solution\")\n",
" fig.colorbar(c, ax=axs)\n",
" axs.set_xlabel('t')\n",
" axs.set_ylabel('x')\n",
" axs.set_xlabel(\"t\")\n",
" axs.set_ylabel(\"x\")\n",
" # otherwise we plot the real one, the Neural Operator one, and their difference\n",
" else:\n",
" fig, axs = plt.subplots(1, 3, figsize=(15, 5), sharex=True, sharey=True)\n",
" axs[0].imshow(real.reshape(dim_t, dim_x).T.detach(),extent=[0, 50, 0, 64], cmap='PuOr_r', aspect='auto')\n",
" axs[0].set_title('Real solution')\n",
" axs[1].imshow(no_sol.reshape(dim_t, dim_x).T.detach(),extent=[0, 50, 0, 64], cmap='PuOr_r', aspect='auto')\n",
" axs[1].set_title('NO solution')\n",
" c = axs[2].imshow((real - no_sol).abs().reshape(dim_t, dim_x).T.detach(),extent=[0, 50, 0, 64], cmap='PuOr_r', aspect='auto')\n",
" axs[2].set_title('Absolute difference')\n",
" axs[0].imshow(\n",
" real.reshape(dim_t, dim_x).T.detach(),\n",
" extent=[0, 50, 0, 64],\n",
" cmap=\"PuOr_r\",\n",
" aspect=\"auto\",\n",
" )\n",
" axs[0].set_title(\"Real solution\")\n",
" axs[1].imshow(\n",
" no_sol.reshape(dim_t, dim_x).T.detach(),\n",
" extent=[0, 50, 0, 64],\n",
" cmap=\"PuOr_r\",\n",
" aspect=\"auto\",\n",
" )\n",
" axs[1].set_title(\"NO solution\")\n",
" c = axs[2].imshow(\n",
" (real - no_sol).abs().reshape(dim_t, dim_x).T.detach(),\n",
" extent=[0, 50, 0, 64],\n",
" cmap=\"PuOr_r\",\n",
" aspect=\"auto\",\n",
" )\n",
" axs[2].set_title(\"Absolute difference\")\n",
" fig.colorbar(c, ax=axs.ravel().tolist())\n",
" for ax in axs:\n",
" ax.set_xlabel('t')\n",
" ax.set_ylabel('x')\n",
" ax.set_xlabel(\"t\")\n",
" ax.set_ylabel(\"x\")\n",
" plt.show()\n",
"\n",
"\n",
"# a sample trajectory (we use the sample 5, feel free to change)\n",
"sample_number = 20\n",
"plot_trajectory(coords=initial_cond_train[sample_number].extract(['x', 't']),\n",
" real=sol_train[sample_number].extract('u'))\n"
"plot_trajectory(\n",
" coords=initial_cond_train[sample_number].extract([\"x\", \"t\"]),\n",
" real=sol_train[sample_number].extract(\"u\"),\n",
")"
]
},
{
Expand Down Expand Up @@ -300,7 +331,12 @@
],
"source": [
"# initialize problem\n",
"problem = SupervisedProblem(initial_cond_train, sol_train, input_variables=initial_cond_train.labels, output_variables=sol_train.labels)\n",
"problem = SupervisedProblem(\n",
" initial_cond_train,\n",
" sol_train,\n",
" input_variables=initial_cond_train.labels,\n",
" output_variables=sol_train.labels,\n",
")\n",
"# initialize solver\n",
"solver = SupervisedSolver(problem=problem, model=model)\n",
"# train, only CPU and avoid model summary at beginning of training (optional)\n",
Expand Down Expand Up @@ -343,9 +379,11 @@
"source": [
"sample_number = 2\n",
"no_sol = solver(initial_cond_test)\n",
"plot_trajectory(coords=initial_cond_test[sample_number].extract(['x', 't']),\n",
" real=sol_test[sample_number].extract('u'),\n",
" no_sol=no_sol[5])"
"plot_trajectory(\n",
" coords=initial_cond_test[sample_number].extract([\"x\", \"t\"]),\n",
" real=sol_test[sample_number].extract(\"u\"),\n",
" no_sol=no_sol[5],\n",
")"
]
},
{
Expand Down Expand Up @@ -373,15 +411,19 @@
"source": [
"from pina.loss import PowerLoss\n",
"\n",
"error_metric = PowerLoss(p=2) # we use the MSE loss\n",
"error_metric = PowerLoss(p=2) # we use the MSE loss\n",
"\n",
"with torch.no_grad():\n",
" no_sol_train = solver(initial_cond_train)\n",
" err_train = error_metric(sol_train.extract('u'), no_sol_train).mean() # we average the error over trajectories\n",
" err_train = error_metric(\n",
" sol_train.extract(\"u\"), no_sol_train\n",
" ).mean() # we average the error over trajectories\n",
" no_sol_test = solver(initial_cond_test)\n",
" err_test = error_metric(sol_test.extract('u'),no_sol_test).mean() # we average the error over trajectories\n",
" print(f'Training error: {float(err_train):.3f}')\n",
" print(f'Testing error: {float(err_test):.3f}')"
" err_test = error_metric(\n",
" sol_test.extract(\"u\"), no_sol_test\n",
" ).mean() # we average the error over trajectories\n",
" print(f\"Training error: {float(err_train):.3f}\")\n",
" print(f\"Testing error: {float(err_test):.3f}\")"
]
},
{
Expand Down
Loading
Loading