From ac62adb47f60cf4e3e61e3f5233afa96265d52ce Mon Sep 17 00:00:00 2001
From: Prakhar Sharma <1915438@swansea.ac.uk>
Date: Tue, 1 Aug 2023 14:54:42 +0100
Subject: [PATCH 1/5] development tutorials added
---
Tutorials/1. Geometry/Basic_domains.ipynb | 44 +++-----------
Tutorials/1. Geometry/UKAEA SUT.ipynb | 7 +++
.../1. Geometry/different sampling.ipynb | 7 +++
Tutorials/2. BC/1. dirichlet.ipynb | 57 +++----------------
Tutorials/2. BC/2. pde.ipynb | 7 +++
Tutorials/3. Gradients/1. Gradients.ipynb | 7 +++
.../3. Gradients/2. higher derivative.ipynb | 7 +++
Tutorials/4. Dataset/1. basic.ipynb | 2 +-
Tutorials/5. FCNN/2. test.ipynb | 7 +++
docs/_toc.yml | 29 ++++++++--
10 files changed, 81 insertions(+), 93 deletions(-)
diff --git a/Tutorials/1. Geometry/Basic_domains.ipynb b/Tutorials/1. Geometry/Basic_domains.ipynb
index 2c7d4c7..46bb1b9 100644
--- a/Tutorials/1. Geometry/Basic_domains.ipynb
+++ b/Tutorials/1. Geometry/Basic_domains.ipynb
@@ -1,49 +1,21 @@
{
"cells": [
{
- "cell_type": "code",
- "execution_count": 2,
+ "cell_type": "markdown",
"metadata": {},
- "outputs": [],
"source": [
- "# This is only valid when the package is not installed\n",
- "import sys\n",
- "sys.path.append('../../') # two folders up"
+ "# Basic domain "
]
},
{
"cell_type": "code",
- "execution_count": 8,
+ "execution_count": 2,
"metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "MPLBACKEND=module://matplotlib_inline.backend_inline\n",
- "HOSTNAME=925e79cc0c33\n",
- "LD_LIBRARY_PATH=/usr/local/nvidia/lib:/usr/local/nvidia/lib64\n",
- "HOME=/root\n",
- "PAGER=cat\n",
- "LC_CTYPE=C.UTF-8\n",
- "FORCE_COLOR=1\n",
- "NVIDIA_DRIVER_CAPABILITIES=compute,utility\n",
- "TERM=xterm-color\n",
- "PATH=/opt/conda/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\n",
- "PYTORCH_VERSION=2.0.1\n",
- "CLICOLOR_FORCE=1\n",
- "GIT_PAGER=cat\n",
- "CLICOLOR=1\n",
- "PWD=/workspace/tutorials/1. Geometry\n",
- "JPY_PARENT_PID=1\n",
- "PYDEVD_USE_FRAME_EVAL=NO\n",
- "NVIDIA_VISIBLE_DEVICES=all\n",
- "JPY_SESSION_NAME=/workspace/tutorials/1. Geometry/Basic_domains.ipynb\n"
- ]
- }
- ],
+ "outputs": [],
"source": [
- "!env"
+ "# This is only valid when the package is not installed\n",
+ "import sys\n",
+ "sys.path.append('../../') # two folders up"
]
},
{
@@ -91,7 +63,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
- "version": "3.10.11"
+ "version": "3.8.10"
}
},
"nbformat": 4,
diff --git a/Tutorials/1. Geometry/UKAEA SUT.ipynb b/Tutorials/1. Geometry/UKAEA SUT.ipynb
index c67e47f..aa995a2 100644
--- a/Tutorials/1. Geometry/UKAEA SUT.ipynb
+++ b/Tutorials/1. Geometry/UKAEA SUT.ipynb
@@ -1,5 +1,12 @@
{
"cells": [
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "# UKAEA SUT"
+ ]
+ },
{
"cell_type": "code",
"execution_count": 1,
diff --git a/Tutorials/1. Geometry/different sampling.ipynb b/Tutorials/1. Geometry/different sampling.ipynb
index c6aefcf..0a38ec9 100644
--- a/Tutorials/1. Geometry/different sampling.ipynb
+++ b/Tutorials/1. Geometry/different sampling.ipynb
@@ -1,5 +1,12 @@
{
"cells": [
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "# Basic sampling techniques"
+ ]
+ },
{
"cell_type": "code",
"execution_count": 1,
diff --git a/Tutorials/2. BC/1. dirichlet.ipynb b/Tutorials/2. BC/1. dirichlet.ipynb
index c6cab43..a8c223b 100644
--- a/Tutorials/2. BC/1. dirichlet.ipynb
+++ b/Tutorials/2. BC/1. dirichlet.ipynb
@@ -1,5 +1,12 @@
{
"cells": [
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "# Dirichlet BC"
+ ]
+ },
{
"cell_type": "code",
"execution_count": 1,
@@ -272,56 +279,6 @@
"plt.scatter(bc_points_right_sampled[:,0], bc_points_right_sampled[:,1], c = bc_points_sampled_right_labels, cmap=plt.get_cmap('plasma', 10))\n",
"plt.colorbar()"
]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": []
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": []
- },
- {
- "cell_type": "code",
- "execution_count": 14,
- "metadata": {},
- "outputs": [
- {
- "ename": "TypeError",
- "evalue": "__init__() missing 3 required positional arguments: 'layer_size', 'activation', and 'initialiser'",
- "output_type": "error",
- "traceback": [
- "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
- "\u001b[0;31mTypeError\u001b[0m Traceback (most recent call last)",
- "Cell \u001b[0;32mIn[14], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m base \u001b[39m=\u001b[39m dp\u001b[39m.\u001b[39;49mnn\u001b[39m.\u001b[39;49mFullyConnected()\n\u001b[1;32m 2\u001b[0m base\u001b[39m.\u001b[39mforward()\n",
- "\u001b[0;31mTypeError\u001b[0m: __init__() missing 3 required positional arguments: 'layer_size', 'activation', and 'initialiser'"
- ]
- }
- ],
- "source": [
- "base = dp.nn.FullyConnected()\n",
- "#base.forward()"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": []
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": []
}
],
"metadata": {
diff --git a/Tutorials/2. BC/2. pde.ipynb b/Tutorials/2. BC/2. pde.ipynb
index e0b2449..21750ed 100644
--- a/Tutorials/2. BC/2. pde.ipynb
+++ b/Tutorials/2. BC/2. pde.ipynb
@@ -1,5 +1,12 @@
{
"cells": [
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "# PDE constraint"
+ ]
+ },
{
"cell_type": "code",
"execution_count": 1,
diff --git a/Tutorials/3. Gradients/1. Gradients.ipynb b/Tutorials/3. Gradients/1. Gradients.ipynb
index 0cdb3fd..6302c71 100644
--- a/Tutorials/3. Gradients/1. Gradients.ipynb
+++ b/Tutorials/3. Gradients/1. Gradients.ipynb
@@ -1,5 +1,12 @@
{
"cells": [
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "# Gradient basics"
+ ]
+ },
{
"cell_type": "code",
"execution_count": 1,
diff --git a/Tutorials/3. Gradients/2. higher derivative.ipynb b/Tutorials/3. Gradients/2. higher derivative.ipynb
index 1170639..92dea33 100644
--- a/Tutorials/3. Gradients/2. higher derivative.ipynb
+++ b/Tutorials/3. Gradients/2. higher derivative.ipynb
@@ -1,5 +1,12 @@
{
"cells": [
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "# Gradients in DeepINN"
+ ]
+ },
{
"cell_type": "code",
"execution_count": 6,
diff --git a/Tutorials/4. Dataset/1. basic.ipynb b/Tutorials/4. Dataset/1. basic.ipynb
index 19bd12f..4b15013 100644
--- a/Tutorials/4. Dataset/1. basic.ipynb
+++ b/Tutorials/4. Dataset/1. basic.ipynb
@@ -4,7 +4,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
- "# How to create the training dataset?"
+ "# Training dataset"
]
},
{
diff --git a/Tutorials/5. FCNN/2. test.ipynb b/Tutorials/5. FCNN/2. test.ipynb
index 1793f73..7ef458d 100644
--- a/Tutorials/5. FCNN/2. test.ipynb
+++ b/Tutorials/5. FCNN/2. test.ipynb
@@ -1,5 +1,12 @@
{
"cells": [
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "# Forward pass"
+ ]
+ },
{
"cell_type": "code",
"execution_count": 1,
diff --git a/docs/_toc.yml b/docs/_toc.yml
index 6d7b616..8ba0a3f 100644
--- a/docs/_toc.yml
+++ b/docs/_toc.yml
@@ -9,9 +9,26 @@ parts:
- file: docs_tutorial/installation.md
- file: docs_tutorial/contribution.md
- file: docs_tutorial/docs_contribution.md
- # - caption: Contribution
- # chapters:
- # - file: docs_tutorial/contribution.md
- # - caption: Documentation compilation
- # chapters:
- # - file: docs_tutorial/docs_contribution.md
\ No newline at end of file
+ - caption: Geometry Tutorials
+ chapters:
+ - file: Tutorials/1. Geometry/Basic_domains.ipynb
+ - file: Tutorials/1. Geometry/different sampling.ipynb
+ - file: Tutorials/1. Geometry/domain_creation.ipynb
+ - file: Tutorials/1. Geometry/polygons_external_objects.ipynb
+ - file: Tutorials/1. Geometry/UKAEA SUT.ipynb
+ - caption: Constraint Tutorials
+ chapters:
+ - file: Tutorials/2. BC/1. dirichlet.ipynb
+ - file: Tutorials/2. BC/2. pde.ipynb
+ - caption: Gradient Tutorials
+ chapters:
+ - file: Tutorials/3. Gradients/1. Gradients.ipynb
+ - file: Tutorials/3. Gradients/2. higher derivative.ipynb
+ - caption: Domain Tutorials
+ chapters:
+ - file: Tutorials/4. Dataset/1. basic.ipynb
+ - caption: Fully connected neural network
+ chapters:
+ - file: Tutorials/5. FCNN/1. basic.ipynb
+ - file: Tutorials/5. FCNN/2. test.ipynb
+ - file: Tutorials/5. FCNN/3. model.ipynb
\ No newline at end of file
From 978b5ac3fc8e5dd859fae746c75bd11fe75c8aa9 Mon Sep 17 00:00:00 2001
From: Prakhar Sharma <1915438@swansea.ac.uk>
Date: Tue, 1 Aug 2023 15:26:09 +0100
Subject: [PATCH 2/5] todo update
---
Tutorials/4. Dataset/1. basic.ipynb | 6 +++---
Tutorials/5. FCNN/1. basic.ipynb | 13 +++----------
Tutorials/5. FCNN/3. model.ipynb | 6 +++---
docs/docs_tutorial/docs_contribution.md | 4 ++--
todo.md | 4 ++--
5 files changed, 13 insertions(+), 20 deletions(-)
diff --git a/Tutorials/4. Dataset/1. basic.ipynb b/Tutorials/4. Dataset/1. basic.ipynb
index 4b15013..a7e1899 100644
--- a/Tutorials/4. Dataset/1. basic.ipynb
+++ b/Tutorials/4. Dataset/1. basic.ipynb
@@ -33,7 +33,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
- "### Geometry"
+ "## Geometry"
]
},
{
@@ -198,7 +198,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
- "### 1D Laplace equation"
+ "## 1D Laplace equation"
]
},
{
@@ -223,7 +223,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
- "### Dataset"
+ "## Dataset"
]
},
{
diff --git a/Tutorials/5. FCNN/1. basic.ipynb b/Tutorials/5. FCNN/1. basic.ipynb
index d193a43..f8b681b 100644
--- a/Tutorials/5. FCNN/1. basic.ipynb
+++ b/Tutorials/5. FCNN/1. basic.ipynb
@@ -25,7 +25,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
- "### Geometry"
+ "## Geometry"
]
},
{
@@ -76,7 +76,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
- "### 1D Laplace equation"
+ "## 1D Laplace equation"
]
},
{
@@ -101,7 +101,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
- "### Dataset"
+ "## Dataset"
]
},
{
@@ -262,13 +262,6 @@
"source": [
"laplace(boundary_point_sample[0],y)"
]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": []
}
],
"metadata": {
diff --git a/Tutorials/5. FCNN/3. model.ipynb b/Tutorials/5. FCNN/3. model.ipynb
index 7001569..5ef4669 100644
--- a/Tutorials/5. FCNN/3. model.ipynb
+++ b/Tutorials/5. FCNN/3. model.ipynb
@@ -33,7 +33,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
- "### Geometry"
+ "## Geometry"
]
},
{
@@ -83,7 +83,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
- "### PDE"
+ "## PDE"
]
},
{
@@ -118,7 +118,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
- "### Network"
+ "## Network"
]
},
{
diff --git a/docs/docs_tutorial/docs_contribution.md b/docs/docs_tutorial/docs_contribution.md
index 9f70ad3..8102e8b 100644
--- a/docs/docs_tutorial/docs_contribution.md
+++ b/docs/docs_tutorial/docs_contribution.md
@@ -1,8 +1,8 @@
-## Documentation compilation
+# Documentation compilation
The doc is created using [Jupyter-book](https://jupyterbook.org/en/stable/intro.html).
-### Setting up Jupyter-books
+## Setting up Jupyter-books
These steps will allows you to create a basic setup. For more details visit [here](https://jupyterbook.org/en/stable/start/your-first-book.html).
1. Create a new Python virtual environment or use an existing one.
diff --git a/todo.md b/todo.md
index 6f270e6..7eba18e 100644
--- a/todo.md
+++ b/todo.md
@@ -28,5 +28,5 @@ Last work : `DeepINN/constraint/gradients.py`
- [ ] Add template PDE in constraint directory.
## Misc
-- [ ] Migrate to JupyterBooks.
-- [ ] Move everything after contribution in the [readme.md](readme.md) to the docs.
\ No newline at end of file
+- [x] Migrate to JupyterBooks.
+- [x] Move everything after contribution in the [readme.md](readme.md) to the docs.
\ No newline at end of file
From bd58719180903535b3229f61f31e00bb6152d8a9 Mon Sep 17 00:00:00 2001
From: Prakhar Sharma <1915438@swansea.ac.uk>
Date: Wed, 23 Aug 2023 18:31:53 +0100
Subject: [PATCH 3/5] multiple spaces dropped
---
DeepINN/geometry/__init__.py | 6 +-
DeepINN/geometry/points.py | 8 +
DeepINN/geometry/spaces/__init__.py | 18 +-
DeepINN/geometry/spaces/space.py | 273 +++++++-----------
DeepINN/geometry_legacy/__init__.py | 5 +
.../conditions/__init__.py | 0
.../conditions/condition.py | 0
.../conditions/deeponet_condition.py | 0
.../domains/__init__.py | 0
.../domains/domain.py | 0
.../domains/domain0D/__init__.py | 0
.../domains/domain0D/point.py | 0
.../domains/domain1D/__init__.py | 0
.../domains/domain1D/interval.py | 0
.../domains/domain2D/__init__.py | 0
.../domains/domain2D/circle.py | 0
.../domains/domain2D/parallelogram.py | 0
.../domains/domain2D/shapely_polygon.py | 0
.../domains/domain2D/triangle.py | 0
.../domains/domain3D/__init__.py | 0
.../domains/domain3D/sphere.py | 0
.../domains/domain3D/trimesh_polyhedron.py | 0
.../domains/domainoperations/cut.py | 0
.../domains/domainoperations/intersection.py | 0
.../domains/domainoperations/product.py | 0
.../domains/domainoperations/rotate.py | 0
.../domainoperations/sampler_helper.py | 0
.../domains/domainoperations/translate.py | 0
.../domains/domainoperations/union.py | 0
.../domains/functionsets/__init__.py | 0
.../domains/functionsets/functionset.py | 0
.../samplers/__init__.py | 0
.../samplers/data_samplers.py | 0
.../samplers/grid_samplers.py | 0
.../samplers/plot_samplers.py | 0
.../samplers/random_samplers.py | 0
.../samplers/sampler_base.py | 0
DeepINN/geometry_legacy/spaces/__init__.py | 17 ++
.../spaces/functionspace.py | 0
.../spaces/points.py | 0
DeepINN/geometry_legacy/spaces/space.py | 198 +++++++++++++
geometry_test.py | 17 ++
42 files changed, 358 insertions(+), 184 deletions(-)
create mode 100644 DeepINN/geometry/points.py
create mode 100644 DeepINN/geometry_legacy/__init__.py
rename DeepINN/{geometry => geometry_legacy}/conditions/__init__.py (100%)
rename DeepINN/{geometry => geometry_legacy}/conditions/condition.py (100%)
rename DeepINN/{geometry => geometry_legacy}/conditions/deeponet_condition.py (100%)
rename DeepINN/{geometry => geometry_legacy}/domains/__init__.py (100%)
rename DeepINN/{geometry => geometry_legacy}/domains/domain.py (100%)
rename DeepINN/{geometry => geometry_legacy}/domains/domain0D/__init__.py (100%)
rename DeepINN/{geometry => geometry_legacy}/domains/domain0D/point.py (100%)
rename DeepINN/{geometry => geometry_legacy}/domains/domain1D/__init__.py (100%)
rename DeepINN/{geometry => geometry_legacy}/domains/domain1D/interval.py (100%)
rename DeepINN/{geometry => geometry_legacy}/domains/domain2D/__init__.py (100%)
rename DeepINN/{geometry => geometry_legacy}/domains/domain2D/circle.py (100%)
rename DeepINN/{geometry => geometry_legacy}/domains/domain2D/parallelogram.py (100%)
rename DeepINN/{geometry => geometry_legacy}/domains/domain2D/shapely_polygon.py (100%)
rename DeepINN/{geometry => geometry_legacy}/domains/domain2D/triangle.py (100%)
rename DeepINN/{geometry => geometry_legacy}/domains/domain3D/__init__.py (100%)
rename DeepINN/{geometry => geometry_legacy}/domains/domain3D/sphere.py (100%)
rename DeepINN/{geometry => geometry_legacy}/domains/domain3D/trimesh_polyhedron.py (100%)
rename DeepINN/{geometry => geometry_legacy}/domains/domainoperations/cut.py (100%)
rename DeepINN/{geometry => geometry_legacy}/domains/domainoperations/intersection.py (100%)
rename DeepINN/{geometry => geometry_legacy}/domains/domainoperations/product.py (100%)
rename DeepINN/{geometry => geometry_legacy}/domains/domainoperations/rotate.py (100%)
rename DeepINN/{geometry => geometry_legacy}/domains/domainoperations/sampler_helper.py (100%)
rename DeepINN/{geometry => geometry_legacy}/domains/domainoperations/translate.py (100%)
rename DeepINN/{geometry => geometry_legacy}/domains/domainoperations/union.py (100%)
rename DeepINN/{geometry => geometry_legacy}/domains/functionsets/__init__.py (100%)
rename DeepINN/{geometry => geometry_legacy}/domains/functionsets/functionset.py (100%)
rename DeepINN/{geometry => geometry_legacy}/samplers/__init__.py (100%)
rename DeepINN/{geometry => geometry_legacy}/samplers/data_samplers.py (100%)
rename DeepINN/{geometry => geometry_legacy}/samplers/grid_samplers.py (100%)
rename DeepINN/{geometry => geometry_legacy}/samplers/plot_samplers.py (100%)
rename DeepINN/{geometry => geometry_legacy}/samplers/random_samplers.py (100%)
rename DeepINN/{geometry => geometry_legacy}/samplers/sampler_base.py (100%)
create mode 100644 DeepINN/geometry_legacy/spaces/__init__.py
rename DeepINN/{geometry => geometry_legacy}/spaces/functionspace.py (100%)
rename DeepINN/{geometry => geometry_legacy}/spaces/points.py (100%)
create mode 100644 DeepINN/geometry_legacy/spaces/space.py
create mode 100644 geometry_test.py
diff --git a/DeepINN/geometry/__init__.py b/DeepINN/geometry/__init__.py
index 3fc0761..fc80254 100644
--- a/DeepINN/geometry/__init__.py
+++ b/DeepINN/geometry/__init__.py
@@ -1,5 +1 @@
-# Make the subdirectory callable
-from . import domains
-#from . import conditions
-from . import samplers
-from . import spaces
\ No newline at end of file
+pass
\ No newline at end of file
diff --git a/DeepINN/geometry/points.py b/DeepINN/geometry/points.py
new file mode 100644
index 0000000..14f44db
--- /dev/null
+++ b/DeepINN/geometry/points.py
@@ -0,0 +1,8 @@
+"""
+Contains a class that handles the storage of all created data points.
+"""
+
+import torch
+import numpy as np
+from .space import Space
+
diff --git a/DeepINN/geometry/spaces/__init__.py b/DeepINN/geometry/spaces/__init__.py
index 3606008..1515c26 100644
--- a/DeepINN/geometry/spaces/__init__.py
+++ b/DeepINN/geometry/spaces/__init__.py
@@ -1,17 +1 @@
-"""Contains the Spaces and Points classes.
-
-Spaces
- It's purpose is to define variable names and dimensions that can
- be used in functions, domains, models and more.
-
-Points
- The ``Points`` object is a central part of TorchPhysics. They consit of a PyTorch-Tensor
- and a space. ``Points`` store data in a tensor with 2-axis, the first corresponding
- the batch-dimension in a batch of multiple points.
- The second axis collects the space dimensionalities.
-"""
-
-from .space import (Space,
- R1, R2, R3, Rn)
-from .points import Points
-from .functionspace import FunctionSpace
\ No newline at end of file
+from .space import Space, R1, R2, R3
\ No newline at end of file
diff --git a/DeepINN/geometry/spaces/space.py b/DeepINN/geometry/spaces/space.py
index c3f10ba..0512b90 100644
--- a/DeepINN/geometry/spaces/space.py
+++ b/DeepINN/geometry/spaces/space.py
@@ -1,198 +1,147 @@
from collections import Counter, OrderedDict
+"""
+* A Counter is a dict subclass for counting hashable objects. It is a collection where elements are stored as dictionary keys and their counts are stored as dictionary values.
+* An OrderedDict is a dictionary subclass that remembers the order in which items are inserted.
+"""
class Space(Counter, OrderedDict):
- """A Space defines (and assigns) the dimensions of the variables
- that appear in the differentialequation. This class sholud not be instanced
- directly, rather the corresponding child classes.
-
+ """
+ Base class to define the dimensions of the variables in the differential equation.
+
Parameters
----------
- variables_dims : dict
- A dictionary containing the name of the variables and the dimension
- of the respective variable.
+ variables_dims: dict
+ A dict containing name of variables and the dimension of each variable.
"""
def __init__(self, variables_dims):
# set counter of variable names and their dimensionalities
+ # Since the Counter is inherited first, if the super().__init__ is consumed by Counter then the second super class won't receive the call.
super().__init__(variables_dims)
- def __mul__(self, other):
- """Creates the product space of the two input spaces. Allows the
- construction of higher dimensional spaces with 'mixed' variable names.
- E.g R1('x')*R1('y') is a two dimensional space where one axis is 'x'
- and the other stands for 'y'.
- """
- assert isinstance(other, Space)
- return Space(self + other)
-
- def __contains__(self, space):
- """Checks if the variables of the other space are contained in this
- space.
-
- Parameters
- ----------
- space : torchphysics.spaces.Space
- The other Space that should be checked if this is included.
- """
- if isinstance(space, str):
- return super().__contains__(space)
- if isinstance(space, Space):
- return (self & space) == space
- else:
- return False
+ # # Adding a magic method to overload the multiply operator using __mul__
+ # def __mul__(self, additional_space):
+ # """
+ # Combine two spaces to create higher dimension spaces.
+ # E.g R1('x')*R1('y') is a two dimensional space where one axis is 'x'
+ # and the other stands for 'y'.
+ # """
+ # assert isinstance(additional_space, Space), "The additional dimension isn't an instance of Space"
+ # # Since we haven't defined __add__. Python will use Counter's __add__ method
+ # return Space(self + additional_space)
- def __getitem__(self, val):
- """Returns a part of the Space dicitionary, specified in the
- input. Mathematically, this constructs a subspace.
-
- Parameters
- ----------
- val : str, slice, list or tuple
- The keys that correspond to the variables that should be used in the
- subspace.
- """
- if isinstance(val, slice):
- keys = list(self.keys())
- new_slice = slice(keys.index(val.start) if val.start is not None else None,
- keys.index(val.stop) if val.stop is not None else None,
- val.step)
- new_keys = keys[new_slice]
- return Space({k: self[k] for k in new_keys})
- if isinstance(val, list) or isinstance(val, tuple):
- return Space({k: self[k] for k in val})
- else:
- return super().__getitem__(val)
-
- @property
- def dim(self):
- """Returns the dimension of the space (sum of factor spaces)
- """
- return sum(self.values())
+ # # __contains__ is a predefined method checks if the key (a string) is present in the counter.
+ # # whenever we use `in` keyword with if condition involving instances of Space object, this self.__contains__ will run be override python's default __contains__.
+ # # here we override this functionpython's default __contains__
+ # # So if we do addition __add__ we will end up executing self.__contains__
+ # def __contains__(self, space):
+ # """
+ # Check if the variables of other space are container in this space.
+ # There are two possibilities.
+ # * method executed for internal dictionary operations such as addition
+ # * method executed when checking if intersection of space and self is space.
+ # That is why we need to modify python default __contains__ for instances of Space.
+
+ # ChatGPT's description:
+ # Override the membership test (in) for the Space class.
+ # - If `space` is a string: Checks if the variable name (key) exists in this Space.
+ # This is useful for both direct membership tests and internal operations
+ # (e.g., during dictionary-style key checking in addition).
+
+ # - If `space` is another Space object: Determines if the provided Space is
+ # entirely contained within the current Space (i.e., if it's a subset).
+ # """
+ # if isinstance(space,str):
+ # #print("Flag: string")
+ # # check if the space already contains the variable names.
+ # return super().__contains__(space)
+ # if isinstance(space, Space):
+ # #print("Flag: Space")
+ # return (self & space) == space
+ # else:
+ # return False
+
+ # # This is a special method in Python which is invoked when we try to access items from containers like array or dictionary.
+ # # It's what gets called when you use square bracket notation to access elements, such as with lists, dictionaries, and strings.
+ # def __getitem__(self, val):
+ # """
+ # Since __getitem__ is used to retrieve items. There are three ways to retrieve items. str, slice, list or tuple.
+
+ # 1. In the case of a slice.
+ # space_obj = Space({'a': 1, 'b': 2, 'c': 3, 'd': 4})
+ # sub_space = space_obj['a':'c'] # returns a Space with {'a': 1, 'b': 2, 'c': 3}
+
+ # 2. In the case of a tuple or a list
+ # space_obj = Space({'a': 1, 'b': 2, 'c': 3, 'd': 4})
+ # sub_space = space_obj[['a', 'c']] # returns a Space with {'a': 1, 'c': 3}
+
+ # 3. In all other cases then use Counter's __getitem__.
+ # space_obj = Space({'a': 1, 'b': 2, 'c': 3, 'd': 4})
+ # value = space_obj['a'] # returns 1
+
+ # Parameters
+ # ----------
+ # val : str, slice, list or tuple
+ # The keys that correspond to the variables that should be used in the
+ # subspace.
+ # """
+ # if isinstance(val, slice): # if val is a slice
+ # keys = list(self.keys())
+ # new_slice = slice(keys.index(val.start) if val.start is not None else None,
+ # keys.index(val.stop) if val.stop is not None else None,
+ # val.step)
+ # new_keys = keys[new_slice]
+ # return Space({k: self[k] for k in new_keys})
+ # if isinstance(val, list) or isinstance(val, tuple):
+ # return Space({k: self[k] for k in val})
+ # else:
+ # return super().__getitem__(val)
+
+ # # To promote encapsulation, @property decorator allows you to print internal read-only attributes of choice.
+ # # @property also allows you to call a function without the parentheses. This is useful when these isn't any input attribute.
+ # @property
+ # def dim(self):
+ # """
+ # Return the dimension of the space.
+ # """
+ # # self is the class Space inheriting Counter, which inherits dict, so values() will return list of values for each key of variables_dims. then sum will sum them up.
+ # return sum(self.values())
- @property
- def variables(self):
- """
- A unordered (!) set of variables.
- """
- return set(self.keys())
-
- def __eq__(self, o: object) -> bool:
- # use OrderedDict equal methode to get order-sensitive comparision
- return OrderedDict.__eq__(self, o)
-
- def __ne__(self, o: object) -> bool:
- return OrderedDict.__ne__(self, o)
-
- """
- Python recipe (see official Python docs) to maintain the insertion order.
- This way, dimensions with identical variable names will be joined, all
- other dimensions will be kept in the order of their creation by products
- or __init__.
- """
- def __repr__(self):
- return '%s(%r)' % (self.__class__.__name__, dict(OrderedDict(self)))
-
- def __reduce__(self):
- return self.__class__, (OrderedDict(self),)
-
- def check_values_in_space(self, values):
- """Checks if a given tensor is valid to belong to this space.
-
- Parameters
- ----------
- values : torch.tensor
- A tensor of values that should be checked.
- Generally the last dimension of the tensor has to fit
- the dimension of this space.
-
- Returns
- -------
- torch.tensor
- In the case, that the values have not the corrected shape, but can
- be reshaped, thet reshaped values are returned.
- This is used in the matrix-space.
- """
- assert values.shape[-1] == self.dim
- return values
-
-
class R1(Space):
- """The space for one dimensional real numbers.
-
+ """
+ Space to define 1D domain.
+
Parameters
----------
variable_name: str
The name of the variable that belongs to this space.
+ It can be any string for coordinate axes.
"""
def __init__(self, variable_name):
- super().__init__({variable_name: 1})
-
+ super().__init__(variable_name, 1)
class R2(Space):
- """The space for two dimensional real numbers.
-
+ """
+ Space to define 2D domain.
+
Parameters
----------
variable_name: str
The name of the variable that belongs to this space.
+ It can be any string for coordinate axes.
"""
def __init__(self, variable_name):
- super().__init__({variable_name: 2})
-
+ super().__init__(variable_name, 2)
class R3(Space):
- """The space for three dimensional real numbers.
-
- Parameters
- ----------
- variable_name: str
- The name of the variable that belongs to this space.
"""
- def __init__(self, variable_name):
- super().__init__({variable_name: 3})
-
-
-class Rn(Space):
- """The space for n dimensional real numbers.
-
+ Space to define 3D domain.
+
Parameters
----------
variable_name: str
The name of the variable that belongs to this space.
- n : int
- The dimension of this space.
+ It can be any string for coordinate axes.
"""
- def __init__(self, variable_name, n : int):
- super().__init__({variable_name: n})
-
-
-# class M(Space):
-# """The space for n x m matricies. (currently only real numbers)
-
-# Parameters
-# ----------
-# variable_name: str
-# The name of the variable that belongs to this space.
-# n : int
-# The number of rows of the matricies.
-# m : int
-# The number of columns.
-# """
-# def __init__(self, variable_name, n : int, m : int):
-# self.rows = n
-# self.columns = m
-# super().__init__({variable_name: n*m})
-
-# def __mul__(self, other):
-# raise NotImplementedError("Matrix-spaces can not be multiplied!")
-
-# def check_values_in_space(self, values):
-# v_shape = values.shape
-# if len(v_shape) >= 3 and v_shape[-2] == self.rows and v_shape[-1] == self.columns:
-# # values aready in correct shape
-# return values
-# if values.shape[-1] == self.dim:
-# # maybe values are given as a vector with correct dimension
-# # -> reshape to matrix
-# return values.reshape(-1, self.rows, self.columns)
-# raise AssertionError("Values do not belong to a matrix-space")
\ No newline at end of file
+ def __init__(self, variable_name):
+ super().__init__(variable_name, 3)
\ No newline at end of file
diff --git a/DeepINN/geometry_legacy/__init__.py b/DeepINN/geometry_legacy/__init__.py
new file mode 100644
index 0000000..3fc0761
--- /dev/null
+++ b/DeepINN/geometry_legacy/__init__.py
@@ -0,0 +1,5 @@
+# Make the subdirectory callable
+from . import domains
+#from . import conditions
+from . import samplers
+from . import spaces
\ No newline at end of file
diff --git a/DeepINN/geometry/conditions/__init__.py b/DeepINN/geometry_legacy/conditions/__init__.py
similarity index 100%
rename from DeepINN/geometry/conditions/__init__.py
rename to DeepINN/geometry_legacy/conditions/__init__.py
diff --git a/DeepINN/geometry/conditions/condition.py b/DeepINN/geometry_legacy/conditions/condition.py
similarity index 100%
rename from DeepINN/geometry/conditions/condition.py
rename to DeepINN/geometry_legacy/conditions/condition.py
diff --git a/DeepINN/geometry/conditions/deeponet_condition.py b/DeepINN/geometry_legacy/conditions/deeponet_condition.py
similarity index 100%
rename from DeepINN/geometry/conditions/deeponet_condition.py
rename to DeepINN/geometry_legacy/conditions/deeponet_condition.py
diff --git a/DeepINN/geometry/domains/__init__.py b/DeepINN/geometry_legacy/domains/__init__.py
similarity index 100%
rename from DeepINN/geometry/domains/__init__.py
rename to DeepINN/geometry_legacy/domains/__init__.py
diff --git a/DeepINN/geometry/domains/domain.py b/DeepINN/geometry_legacy/domains/domain.py
similarity index 100%
rename from DeepINN/geometry/domains/domain.py
rename to DeepINN/geometry_legacy/domains/domain.py
diff --git a/DeepINN/geometry/domains/domain0D/__init__.py b/DeepINN/geometry_legacy/domains/domain0D/__init__.py
similarity index 100%
rename from DeepINN/geometry/domains/domain0D/__init__.py
rename to DeepINN/geometry_legacy/domains/domain0D/__init__.py
diff --git a/DeepINN/geometry/domains/domain0D/point.py b/DeepINN/geometry_legacy/domains/domain0D/point.py
similarity index 100%
rename from DeepINN/geometry/domains/domain0D/point.py
rename to DeepINN/geometry_legacy/domains/domain0D/point.py
diff --git a/DeepINN/geometry/domains/domain1D/__init__.py b/DeepINN/geometry_legacy/domains/domain1D/__init__.py
similarity index 100%
rename from DeepINN/geometry/domains/domain1D/__init__.py
rename to DeepINN/geometry_legacy/domains/domain1D/__init__.py
diff --git a/DeepINN/geometry/domains/domain1D/interval.py b/DeepINN/geometry_legacy/domains/domain1D/interval.py
similarity index 100%
rename from DeepINN/geometry/domains/domain1D/interval.py
rename to DeepINN/geometry_legacy/domains/domain1D/interval.py
diff --git a/DeepINN/geometry/domains/domain2D/__init__.py b/DeepINN/geometry_legacy/domains/domain2D/__init__.py
similarity index 100%
rename from DeepINN/geometry/domains/domain2D/__init__.py
rename to DeepINN/geometry_legacy/domains/domain2D/__init__.py
diff --git a/DeepINN/geometry/domains/domain2D/circle.py b/DeepINN/geometry_legacy/domains/domain2D/circle.py
similarity index 100%
rename from DeepINN/geometry/domains/domain2D/circle.py
rename to DeepINN/geometry_legacy/domains/domain2D/circle.py
diff --git a/DeepINN/geometry/domains/domain2D/parallelogram.py b/DeepINN/geometry_legacy/domains/domain2D/parallelogram.py
similarity index 100%
rename from DeepINN/geometry/domains/domain2D/parallelogram.py
rename to DeepINN/geometry_legacy/domains/domain2D/parallelogram.py
diff --git a/DeepINN/geometry/domains/domain2D/shapely_polygon.py b/DeepINN/geometry_legacy/domains/domain2D/shapely_polygon.py
similarity index 100%
rename from DeepINN/geometry/domains/domain2D/shapely_polygon.py
rename to DeepINN/geometry_legacy/domains/domain2D/shapely_polygon.py
diff --git a/DeepINN/geometry/domains/domain2D/triangle.py b/DeepINN/geometry_legacy/domains/domain2D/triangle.py
similarity index 100%
rename from DeepINN/geometry/domains/domain2D/triangle.py
rename to DeepINN/geometry_legacy/domains/domain2D/triangle.py
diff --git a/DeepINN/geometry/domains/domain3D/__init__.py b/DeepINN/geometry_legacy/domains/domain3D/__init__.py
similarity index 100%
rename from DeepINN/geometry/domains/domain3D/__init__.py
rename to DeepINN/geometry_legacy/domains/domain3D/__init__.py
diff --git a/DeepINN/geometry/domains/domain3D/sphere.py b/DeepINN/geometry_legacy/domains/domain3D/sphere.py
similarity index 100%
rename from DeepINN/geometry/domains/domain3D/sphere.py
rename to DeepINN/geometry_legacy/domains/domain3D/sphere.py
diff --git a/DeepINN/geometry/domains/domain3D/trimesh_polyhedron.py b/DeepINN/geometry_legacy/domains/domain3D/trimesh_polyhedron.py
similarity index 100%
rename from DeepINN/geometry/domains/domain3D/trimesh_polyhedron.py
rename to DeepINN/geometry_legacy/domains/domain3D/trimesh_polyhedron.py
diff --git a/DeepINN/geometry/domains/domainoperations/cut.py b/DeepINN/geometry_legacy/domains/domainoperations/cut.py
similarity index 100%
rename from DeepINN/geometry/domains/domainoperations/cut.py
rename to DeepINN/geometry_legacy/domains/domainoperations/cut.py
diff --git a/DeepINN/geometry/domains/domainoperations/intersection.py b/DeepINN/geometry_legacy/domains/domainoperations/intersection.py
similarity index 100%
rename from DeepINN/geometry/domains/domainoperations/intersection.py
rename to DeepINN/geometry_legacy/domains/domainoperations/intersection.py
diff --git a/DeepINN/geometry/domains/domainoperations/product.py b/DeepINN/geometry_legacy/domains/domainoperations/product.py
similarity index 100%
rename from DeepINN/geometry/domains/domainoperations/product.py
rename to DeepINN/geometry_legacy/domains/domainoperations/product.py
diff --git a/DeepINN/geometry/domains/domainoperations/rotate.py b/DeepINN/geometry_legacy/domains/domainoperations/rotate.py
similarity index 100%
rename from DeepINN/geometry/domains/domainoperations/rotate.py
rename to DeepINN/geometry_legacy/domains/domainoperations/rotate.py
diff --git a/DeepINN/geometry/domains/domainoperations/sampler_helper.py b/DeepINN/geometry_legacy/domains/domainoperations/sampler_helper.py
similarity index 100%
rename from DeepINN/geometry/domains/domainoperations/sampler_helper.py
rename to DeepINN/geometry_legacy/domains/domainoperations/sampler_helper.py
diff --git a/DeepINN/geometry/domains/domainoperations/translate.py b/DeepINN/geometry_legacy/domains/domainoperations/translate.py
similarity index 100%
rename from DeepINN/geometry/domains/domainoperations/translate.py
rename to DeepINN/geometry_legacy/domains/domainoperations/translate.py
diff --git a/DeepINN/geometry/domains/domainoperations/union.py b/DeepINN/geometry_legacy/domains/domainoperations/union.py
similarity index 100%
rename from DeepINN/geometry/domains/domainoperations/union.py
rename to DeepINN/geometry_legacy/domains/domainoperations/union.py
diff --git a/DeepINN/geometry/domains/functionsets/__init__.py b/DeepINN/geometry_legacy/domains/functionsets/__init__.py
similarity index 100%
rename from DeepINN/geometry/domains/functionsets/__init__.py
rename to DeepINN/geometry_legacy/domains/functionsets/__init__.py
diff --git a/DeepINN/geometry/domains/functionsets/functionset.py b/DeepINN/geometry_legacy/domains/functionsets/functionset.py
similarity index 100%
rename from DeepINN/geometry/domains/functionsets/functionset.py
rename to DeepINN/geometry_legacy/domains/functionsets/functionset.py
diff --git a/DeepINN/geometry/samplers/__init__.py b/DeepINN/geometry_legacy/samplers/__init__.py
similarity index 100%
rename from DeepINN/geometry/samplers/__init__.py
rename to DeepINN/geometry_legacy/samplers/__init__.py
diff --git a/DeepINN/geometry/samplers/data_samplers.py b/DeepINN/geometry_legacy/samplers/data_samplers.py
similarity index 100%
rename from DeepINN/geometry/samplers/data_samplers.py
rename to DeepINN/geometry_legacy/samplers/data_samplers.py
diff --git a/DeepINN/geometry/samplers/grid_samplers.py b/DeepINN/geometry_legacy/samplers/grid_samplers.py
similarity index 100%
rename from DeepINN/geometry/samplers/grid_samplers.py
rename to DeepINN/geometry_legacy/samplers/grid_samplers.py
diff --git a/DeepINN/geometry/samplers/plot_samplers.py b/DeepINN/geometry_legacy/samplers/plot_samplers.py
similarity index 100%
rename from DeepINN/geometry/samplers/plot_samplers.py
rename to DeepINN/geometry_legacy/samplers/plot_samplers.py
diff --git a/DeepINN/geometry/samplers/random_samplers.py b/DeepINN/geometry_legacy/samplers/random_samplers.py
similarity index 100%
rename from DeepINN/geometry/samplers/random_samplers.py
rename to DeepINN/geometry_legacy/samplers/random_samplers.py
diff --git a/DeepINN/geometry/samplers/sampler_base.py b/DeepINN/geometry_legacy/samplers/sampler_base.py
similarity index 100%
rename from DeepINN/geometry/samplers/sampler_base.py
rename to DeepINN/geometry_legacy/samplers/sampler_base.py
diff --git a/DeepINN/geometry_legacy/spaces/__init__.py b/DeepINN/geometry_legacy/spaces/__init__.py
new file mode 100644
index 0000000..3606008
--- /dev/null
+++ b/DeepINN/geometry_legacy/spaces/__init__.py
@@ -0,0 +1,17 @@
+"""Contains the Spaces and Points classes.
+
+Spaces
+ It's purpose is to define variable names and dimensions that can
+ be used in functions, domains, models and more.
+
+Points
+ The ``Points`` object is a central part of TorchPhysics. They consit of a PyTorch-Tensor
+ and a space. ``Points`` store data in a tensor with 2-axis, the first corresponding
+ the batch-dimension in a batch of multiple points.
+ The second axis collects the space dimensionalities.
+"""
+
+from .space import (Space,
+ R1, R2, R3, Rn)
+from .points import Points
+from .functionspace import FunctionSpace
\ No newline at end of file
diff --git a/DeepINN/geometry/spaces/functionspace.py b/DeepINN/geometry_legacy/spaces/functionspace.py
similarity index 100%
rename from DeepINN/geometry/spaces/functionspace.py
rename to DeepINN/geometry_legacy/spaces/functionspace.py
diff --git a/DeepINN/geometry/spaces/points.py b/DeepINN/geometry_legacy/spaces/points.py
similarity index 100%
rename from DeepINN/geometry/spaces/points.py
rename to DeepINN/geometry_legacy/spaces/points.py
diff --git a/DeepINN/geometry_legacy/spaces/space.py b/DeepINN/geometry_legacy/spaces/space.py
new file mode 100644
index 0000000..c3f10ba
--- /dev/null
+++ b/DeepINN/geometry_legacy/spaces/space.py
@@ -0,0 +1,198 @@
+from collections import Counter, OrderedDict
+
+
+class Space(Counter, OrderedDict):
+ """A Space defines (and assigns) the dimensions of the variables
+ that appear in the differentialequation. This class sholud not be instanced
+ directly, rather the corresponding child classes.
+
+ Parameters
+ ----------
+ variables_dims : dict
+ A dictionary containing the name of the variables and the dimension
+ of the respective variable.
+ """
+ def __init__(self, variables_dims):
+ # set counter of variable names and their dimensionalities
+ super().__init__(variables_dims)
+
+ def __mul__(self, other):
+ """Creates the product space of the two input spaces. Allows the
+ construction of higher dimensional spaces with 'mixed' variable names.
+ E.g R1('x')*R1('y') is a two dimensional space where one axis is 'x'
+ and the other stands for 'y'.
+ """
+ assert isinstance(other, Space)
+ return Space(self + other)
+
+ def __contains__(self, space):
+ """Checks if the variables of the other space are contained in this
+ space.
+
+ Parameters
+ ----------
+ space : torchphysics.spaces.Space
+ The other Space that should be checked if this is included.
+ """
+ if isinstance(space, str):
+ return super().__contains__(space)
+ if isinstance(space, Space):
+ return (self & space) == space
+ else:
+ return False
+
+ def __getitem__(self, val):
+ """Returns a part of the Space dicitionary, specified in the
+ input. Mathematically, this constructs a subspace.
+
+ Parameters
+ ----------
+ val : str, slice, list or tuple
+ The keys that correspond to the variables that should be used in the
+ subspace.
+ """
+ if isinstance(val, slice):
+ keys = list(self.keys())
+ new_slice = slice(keys.index(val.start) if val.start is not None else None,
+ keys.index(val.stop) if val.stop is not None else None,
+ val.step)
+ new_keys = keys[new_slice]
+ return Space({k: self[k] for k in new_keys})
+ if isinstance(val, list) or isinstance(val, tuple):
+ return Space({k: self[k] for k in val})
+ else:
+ return super().__getitem__(val)
+
+ @property
+ def dim(self):
+ """Returns the dimension of the space (sum of factor spaces)
+ """
+ return sum(self.values())
+
+ @property
+ def variables(self):
+ """
+ A unordered (!) set of variables.
+ """
+ return set(self.keys())
+
+ def __eq__(self, o: object) -> bool:
+ # use OrderedDict equal methode to get order-sensitive comparision
+ return OrderedDict.__eq__(self, o)
+
+ def __ne__(self, o: object) -> bool:
+ return OrderedDict.__ne__(self, o)
+
+ """
+ Python recipe (see official Python docs) to maintain the insertion order.
+ This way, dimensions with identical variable names will be joined, all
+ other dimensions will be kept in the order of their creation by products
+ or __init__.
+ """
+ def __repr__(self):
+ return '%s(%r)' % (self.__class__.__name__, dict(OrderedDict(self)))
+
+ def __reduce__(self):
+ return self.__class__, (OrderedDict(self),)
+
+ def check_values_in_space(self, values):
+ """Checks if a given tensor is valid to belong to this space.
+
+ Parameters
+ ----------
+ values : torch.tensor
+ A tensor of values that should be checked.
+ Generally the last dimension of the tensor has to fit
+ the dimension of this space.
+
+ Returns
+ -------
+ torch.tensor
+ In the case, that the values have not the corrected shape, but can
+ be reshaped, thet reshaped values are returned.
+ This is used in the matrix-space.
+ """
+ assert values.shape[-1] == self.dim
+ return values
+
+
+class R1(Space):
+ """The space for one dimensional real numbers.
+
+ Parameters
+ ----------
+ variable_name: str
+ The name of the variable that belongs to this space.
+ """
+ def __init__(self, variable_name):
+ super().__init__({variable_name: 1})
+
+
+class R2(Space):
+ """The space for two dimensional real numbers.
+
+ Parameters
+ ----------
+ variable_name: str
+ The name of the variable that belongs to this space.
+ """
+ def __init__(self, variable_name):
+ super().__init__({variable_name: 2})
+
+
+class R3(Space):
+ """The space for three dimensional real numbers.
+
+ Parameters
+ ----------
+ variable_name: str
+ The name of the variable that belongs to this space.
+ """
+ def __init__(self, variable_name):
+ super().__init__({variable_name: 3})
+
+
+class Rn(Space):
+ """The space for n dimensional real numbers.
+
+ Parameters
+ ----------
+ variable_name: str
+ The name of the variable that belongs to this space.
+ n : int
+ The dimension of this space.
+ """
+ def __init__(self, variable_name, n : int):
+ super().__init__({variable_name: n})
+
+
+# class M(Space):
+# """The space for n x m matricies. (currently only real numbers)
+
+# Parameters
+# ----------
+# variable_name: str
+# The name of the variable that belongs to this space.
+# n : int
+# The number of rows of the matricies.
+# m : int
+# The number of columns.
+# """
+# def __init__(self, variable_name, n : int, m : int):
+# self.rows = n
+# self.columns = m
+# super().__init__({variable_name: n*m})
+
+# def __mul__(self, other):
+# raise NotImplementedError("Matrix-spaces can not be multiplied!")
+
+# def check_values_in_space(self, values):
+# v_shape = values.shape
+# if len(v_shape) >= 3 and v_shape[-2] == self.rows and v_shape[-1] == self.columns:
+# # values aready in correct shape
+# return values
+# if values.shape[-1] == self.dim:
+# # maybe values are given as a vector with correct dimension
+# # -> reshape to matrix
+# return values.reshape(-1, self.rows, self.columns)
+# raise AssertionError("Values do not belong to a matrix-space")
\ No newline at end of file
diff --git a/geometry_test.py b/geometry_test.py
new file mode 100644
index 0000000..640bab9
--- /dev/null
+++ b/geometry_test.py
@@ -0,0 +1,17 @@
+import sys
+sys.path.append("DeepINN/geometry/spaces")
+
+from space import Space, R1, R2, R3
+
+space1 = Space({'x': 1})
+space2 = Space({'x': 2, 'y': 3})
+
+# Support for multiple spaces has been dropped
+# result = space1 * space2
+# print(result)
+
+# #print(space1.__contains__(space2))
+
+# space_obj = Space({'a': 1, 'b': 2, 'c': 3, 'd': 4})
+# sub_space = space_obj['a':'c'] # returns a Space with {'a': 1, 'b': 2, 'c': 3}
+
From 4ed7f50a982ebbec9a3d0fa12d1c70e4e11f8138 Mon Sep 17 00:00:00 2001
From: Prakhar Sharma <1915438@swansea.ac.uk>
Date: Thu, 9 Nov 2023 16:52:20 +0000
Subject: [PATCH 4/5] geometry refactor in future
---
DeepINN/geometry/__init__.py | 6 +-
.../conditions/__init__.py | 0
.../conditions/condition.py | 0
.../conditions/deeponet_condition.py | 0
.../domains/__init__.py | 0
.../domains/domain.py | 0
.../domains/domain0D/__init__.py | 0
.../domains/domain0D/point.py | 0
.../domains/domain1D/__init__.py | 0
.../domains/domain1D/interval.py | 0
.../domains/domain2D/__init__.py | 0
.../domains/domain2D/circle.py | 0
.../domains/domain2D/parallelogram.py | 0
.../domains/domain2D/shapely_polygon.py | 0
.../domains/domain2D/triangle.py | 0
.../domains/domain3D/__init__.py | 0
.../domains/domain3D/sphere.py | 0
.../domains/domain3D/trimesh_polyhedron.py | 0
.../domains/domainoperations/cut.py | 0
.../domains/domainoperations/intersection.py | 0
.../domains/domainoperations/product.py | 0
.../domains/domainoperations/rotate.py | 0
.../domainoperations/sampler_helper.py | 0
.../domains/domainoperations/translate.py | 0
.../domains/domainoperations/union.py | 0
.../domains/functionsets/__init__.py | 0
.../domains/functionsets/functionset.py | 0
.../samplers/__init__.py | 0
.../samplers/data_samplers.py | 0
.../samplers/grid_samplers.py | 0
.../samplers/plot_samplers.py | 0
.../samplers/random_samplers.py | 0
.../samplers/sampler_base.py | 0
DeepINN/geometry/spaces/__init__.py | 18 +-
.../spaces/functionspace.py | 0
.../spaces/points.py | 0
DeepINN/geometry/spaces/space.py | 273 +++++++++++-------
DeepINN/geometry_legacy/__init__.py | 5 -
DeepINN/geometry_legacy/spaces/__init__.py | 17 --
DeepINN/geometry_legacy/spaces/space.py | 198 -------------
DeepINN/geometry_refactor/__init__.py | 1 +
.../{geometry => geometry_refactor}/points.py | 0
DeepINN/geometry_refactor/spaces/__init__.py | 1 +
DeepINN/geometry_refactor/spaces/space.py | 147 ++++++++++
DeepINN/model.py | 6 +-
Tutorials/5. FCNN/3. model.ipynb | 150 +++++++---
todo.md | 4 +-
47 files changed, 454 insertions(+), 372 deletions(-)
rename DeepINN/{geometry_legacy => geometry}/conditions/__init__.py (100%)
rename DeepINN/{geometry_legacy => geometry}/conditions/condition.py (100%)
rename DeepINN/{geometry_legacy => geometry}/conditions/deeponet_condition.py (100%)
rename DeepINN/{geometry_legacy => geometry}/domains/__init__.py (100%)
rename DeepINN/{geometry_legacy => geometry}/domains/domain.py (100%)
rename DeepINN/{geometry_legacy => geometry}/domains/domain0D/__init__.py (100%)
rename DeepINN/{geometry_legacy => geometry}/domains/domain0D/point.py (100%)
rename DeepINN/{geometry_legacy => geometry}/domains/domain1D/__init__.py (100%)
rename DeepINN/{geometry_legacy => geometry}/domains/domain1D/interval.py (100%)
rename DeepINN/{geometry_legacy => geometry}/domains/domain2D/__init__.py (100%)
rename DeepINN/{geometry_legacy => geometry}/domains/domain2D/circle.py (100%)
rename DeepINN/{geometry_legacy => geometry}/domains/domain2D/parallelogram.py (100%)
rename DeepINN/{geometry_legacy => geometry}/domains/domain2D/shapely_polygon.py (100%)
rename DeepINN/{geometry_legacy => geometry}/domains/domain2D/triangle.py (100%)
rename DeepINN/{geometry_legacy => geometry}/domains/domain3D/__init__.py (100%)
rename DeepINN/{geometry_legacy => geometry}/domains/domain3D/sphere.py (100%)
rename DeepINN/{geometry_legacy => geometry}/domains/domain3D/trimesh_polyhedron.py (100%)
rename DeepINN/{geometry_legacy => geometry}/domains/domainoperations/cut.py (100%)
rename DeepINN/{geometry_legacy => geometry}/domains/domainoperations/intersection.py (100%)
rename DeepINN/{geometry_legacy => geometry}/domains/domainoperations/product.py (100%)
rename DeepINN/{geometry_legacy => geometry}/domains/domainoperations/rotate.py (100%)
rename DeepINN/{geometry_legacy => geometry}/domains/domainoperations/sampler_helper.py (100%)
rename DeepINN/{geometry_legacy => geometry}/domains/domainoperations/translate.py (100%)
rename DeepINN/{geometry_legacy => geometry}/domains/domainoperations/union.py (100%)
rename DeepINN/{geometry_legacy => geometry}/domains/functionsets/__init__.py (100%)
rename DeepINN/{geometry_legacy => geometry}/domains/functionsets/functionset.py (100%)
rename DeepINN/{geometry_legacy => geometry}/samplers/__init__.py (100%)
rename DeepINN/{geometry_legacy => geometry}/samplers/data_samplers.py (100%)
rename DeepINN/{geometry_legacy => geometry}/samplers/grid_samplers.py (100%)
rename DeepINN/{geometry_legacy => geometry}/samplers/plot_samplers.py (100%)
rename DeepINN/{geometry_legacy => geometry}/samplers/random_samplers.py (100%)
rename DeepINN/{geometry_legacy => geometry}/samplers/sampler_base.py (100%)
rename DeepINN/{geometry_legacy => geometry}/spaces/functionspace.py (100%)
rename DeepINN/{geometry_legacy => geometry}/spaces/points.py (100%)
delete mode 100644 DeepINN/geometry_legacy/__init__.py
delete mode 100644 DeepINN/geometry_legacy/spaces/__init__.py
delete mode 100644 DeepINN/geometry_legacy/spaces/space.py
create mode 100644 DeepINN/geometry_refactor/__init__.py
rename DeepINN/{geometry => geometry_refactor}/points.py (100%)
create mode 100644 DeepINN/geometry_refactor/spaces/__init__.py
create mode 100644 DeepINN/geometry_refactor/spaces/space.py
diff --git a/DeepINN/geometry/__init__.py b/DeepINN/geometry/__init__.py
index fc80254..3fc0761 100644
--- a/DeepINN/geometry/__init__.py
+++ b/DeepINN/geometry/__init__.py
@@ -1 +1,5 @@
-pass
\ No newline at end of file
+# Make the subdirectory callable
+from . import domains
+#from . import conditions
+from . import samplers
+from . import spaces
\ No newline at end of file
diff --git a/DeepINN/geometry_legacy/conditions/__init__.py b/DeepINN/geometry/conditions/__init__.py
similarity index 100%
rename from DeepINN/geometry_legacy/conditions/__init__.py
rename to DeepINN/geometry/conditions/__init__.py
diff --git a/DeepINN/geometry_legacy/conditions/condition.py b/DeepINN/geometry/conditions/condition.py
similarity index 100%
rename from DeepINN/geometry_legacy/conditions/condition.py
rename to DeepINN/geometry/conditions/condition.py
diff --git a/DeepINN/geometry_legacy/conditions/deeponet_condition.py b/DeepINN/geometry/conditions/deeponet_condition.py
similarity index 100%
rename from DeepINN/geometry_legacy/conditions/deeponet_condition.py
rename to DeepINN/geometry/conditions/deeponet_condition.py
diff --git a/DeepINN/geometry_legacy/domains/__init__.py b/DeepINN/geometry/domains/__init__.py
similarity index 100%
rename from DeepINN/geometry_legacy/domains/__init__.py
rename to DeepINN/geometry/domains/__init__.py
diff --git a/DeepINN/geometry_legacy/domains/domain.py b/DeepINN/geometry/domains/domain.py
similarity index 100%
rename from DeepINN/geometry_legacy/domains/domain.py
rename to DeepINN/geometry/domains/domain.py
diff --git a/DeepINN/geometry_legacy/domains/domain0D/__init__.py b/DeepINN/geometry/domains/domain0D/__init__.py
similarity index 100%
rename from DeepINN/geometry_legacy/domains/domain0D/__init__.py
rename to DeepINN/geometry/domains/domain0D/__init__.py
diff --git a/DeepINN/geometry_legacy/domains/domain0D/point.py b/DeepINN/geometry/domains/domain0D/point.py
similarity index 100%
rename from DeepINN/geometry_legacy/domains/domain0D/point.py
rename to DeepINN/geometry/domains/domain0D/point.py
diff --git a/DeepINN/geometry_legacy/domains/domain1D/__init__.py b/DeepINN/geometry/domains/domain1D/__init__.py
similarity index 100%
rename from DeepINN/geometry_legacy/domains/domain1D/__init__.py
rename to DeepINN/geometry/domains/domain1D/__init__.py
diff --git a/DeepINN/geometry_legacy/domains/domain1D/interval.py b/DeepINN/geometry/domains/domain1D/interval.py
similarity index 100%
rename from DeepINN/geometry_legacy/domains/domain1D/interval.py
rename to DeepINN/geometry/domains/domain1D/interval.py
diff --git a/DeepINN/geometry_legacy/domains/domain2D/__init__.py b/DeepINN/geometry/domains/domain2D/__init__.py
similarity index 100%
rename from DeepINN/geometry_legacy/domains/domain2D/__init__.py
rename to DeepINN/geometry/domains/domain2D/__init__.py
diff --git a/DeepINN/geometry_legacy/domains/domain2D/circle.py b/DeepINN/geometry/domains/domain2D/circle.py
similarity index 100%
rename from DeepINN/geometry_legacy/domains/domain2D/circle.py
rename to DeepINN/geometry/domains/domain2D/circle.py
diff --git a/DeepINN/geometry_legacy/domains/domain2D/parallelogram.py b/DeepINN/geometry/domains/domain2D/parallelogram.py
similarity index 100%
rename from DeepINN/geometry_legacy/domains/domain2D/parallelogram.py
rename to DeepINN/geometry/domains/domain2D/parallelogram.py
diff --git a/DeepINN/geometry_legacy/domains/domain2D/shapely_polygon.py b/DeepINN/geometry/domains/domain2D/shapely_polygon.py
similarity index 100%
rename from DeepINN/geometry_legacy/domains/domain2D/shapely_polygon.py
rename to DeepINN/geometry/domains/domain2D/shapely_polygon.py
diff --git a/DeepINN/geometry_legacy/domains/domain2D/triangle.py b/DeepINN/geometry/domains/domain2D/triangle.py
similarity index 100%
rename from DeepINN/geometry_legacy/domains/domain2D/triangle.py
rename to DeepINN/geometry/domains/domain2D/triangle.py
diff --git a/DeepINN/geometry_legacy/domains/domain3D/__init__.py b/DeepINN/geometry/domains/domain3D/__init__.py
similarity index 100%
rename from DeepINN/geometry_legacy/domains/domain3D/__init__.py
rename to DeepINN/geometry/domains/domain3D/__init__.py
diff --git a/DeepINN/geometry_legacy/domains/domain3D/sphere.py b/DeepINN/geometry/domains/domain3D/sphere.py
similarity index 100%
rename from DeepINN/geometry_legacy/domains/domain3D/sphere.py
rename to DeepINN/geometry/domains/domain3D/sphere.py
diff --git a/DeepINN/geometry_legacy/domains/domain3D/trimesh_polyhedron.py b/DeepINN/geometry/domains/domain3D/trimesh_polyhedron.py
similarity index 100%
rename from DeepINN/geometry_legacy/domains/domain3D/trimesh_polyhedron.py
rename to DeepINN/geometry/domains/domain3D/trimesh_polyhedron.py
diff --git a/DeepINN/geometry_legacy/domains/domainoperations/cut.py b/DeepINN/geometry/domains/domainoperations/cut.py
similarity index 100%
rename from DeepINN/geometry_legacy/domains/domainoperations/cut.py
rename to DeepINN/geometry/domains/domainoperations/cut.py
diff --git a/DeepINN/geometry_legacy/domains/domainoperations/intersection.py b/DeepINN/geometry/domains/domainoperations/intersection.py
similarity index 100%
rename from DeepINN/geometry_legacy/domains/domainoperations/intersection.py
rename to DeepINN/geometry/domains/domainoperations/intersection.py
diff --git a/DeepINN/geometry_legacy/domains/domainoperations/product.py b/DeepINN/geometry/domains/domainoperations/product.py
similarity index 100%
rename from DeepINN/geometry_legacy/domains/domainoperations/product.py
rename to DeepINN/geometry/domains/domainoperations/product.py
diff --git a/DeepINN/geometry_legacy/domains/domainoperations/rotate.py b/DeepINN/geometry/domains/domainoperations/rotate.py
similarity index 100%
rename from DeepINN/geometry_legacy/domains/domainoperations/rotate.py
rename to DeepINN/geometry/domains/domainoperations/rotate.py
diff --git a/DeepINN/geometry_legacy/domains/domainoperations/sampler_helper.py b/DeepINN/geometry/domains/domainoperations/sampler_helper.py
similarity index 100%
rename from DeepINN/geometry_legacy/domains/domainoperations/sampler_helper.py
rename to DeepINN/geometry/domains/domainoperations/sampler_helper.py
diff --git a/DeepINN/geometry_legacy/domains/domainoperations/translate.py b/DeepINN/geometry/domains/domainoperations/translate.py
similarity index 100%
rename from DeepINN/geometry_legacy/domains/domainoperations/translate.py
rename to DeepINN/geometry/domains/domainoperations/translate.py
diff --git a/DeepINN/geometry_legacy/domains/domainoperations/union.py b/DeepINN/geometry/domains/domainoperations/union.py
similarity index 100%
rename from DeepINN/geometry_legacy/domains/domainoperations/union.py
rename to DeepINN/geometry/domains/domainoperations/union.py
diff --git a/DeepINN/geometry_legacy/domains/functionsets/__init__.py b/DeepINN/geometry/domains/functionsets/__init__.py
similarity index 100%
rename from DeepINN/geometry_legacy/domains/functionsets/__init__.py
rename to DeepINN/geometry/domains/functionsets/__init__.py
diff --git a/DeepINN/geometry_legacy/domains/functionsets/functionset.py b/DeepINN/geometry/domains/functionsets/functionset.py
similarity index 100%
rename from DeepINN/geometry_legacy/domains/functionsets/functionset.py
rename to DeepINN/geometry/domains/functionsets/functionset.py
diff --git a/DeepINN/geometry_legacy/samplers/__init__.py b/DeepINN/geometry/samplers/__init__.py
similarity index 100%
rename from DeepINN/geometry_legacy/samplers/__init__.py
rename to DeepINN/geometry/samplers/__init__.py
diff --git a/DeepINN/geometry_legacy/samplers/data_samplers.py b/DeepINN/geometry/samplers/data_samplers.py
similarity index 100%
rename from DeepINN/geometry_legacy/samplers/data_samplers.py
rename to DeepINN/geometry/samplers/data_samplers.py
diff --git a/DeepINN/geometry_legacy/samplers/grid_samplers.py b/DeepINN/geometry/samplers/grid_samplers.py
similarity index 100%
rename from DeepINN/geometry_legacy/samplers/grid_samplers.py
rename to DeepINN/geometry/samplers/grid_samplers.py
diff --git a/DeepINN/geometry_legacy/samplers/plot_samplers.py b/DeepINN/geometry/samplers/plot_samplers.py
similarity index 100%
rename from DeepINN/geometry_legacy/samplers/plot_samplers.py
rename to DeepINN/geometry/samplers/plot_samplers.py
diff --git a/DeepINN/geometry_legacy/samplers/random_samplers.py b/DeepINN/geometry/samplers/random_samplers.py
similarity index 100%
rename from DeepINN/geometry_legacy/samplers/random_samplers.py
rename to DeepINN/geometry/samplers/random_samplers.py
diff --git a/DeepINN/geometry_legacy/samplers/sampler_base.py b/DeepINN/geometry/samplers/sampler_base.py
similarity index 100%
rename from DeepINN/geometry_legacy/samplers/sampler_base.py
rename to DeepINN/geometry/samplers/sampler_base.py
diff --git a/DeepINN/geometry/spaces/__init__.py b/DeepINN/geometry/spaces/__init__.py
index 1515c26..3606008 100644
--- a/DeepINN/geometry/spaces/__init__.py
+++ b/DeepINN/geometry/spaces/__init__.py
@@ -1 +1,17 @@
-from .space import Space, R1, R2, R3
\ No newline at end of file
+"""Contains the Spaces and Points classes.
+
+Spaces
+ It's purpose is to define variable names and dimensions that can
+ be used in functions, domains, models and more.
+
+Points
+ The ``Points`` object is a central part of TorchPhysics. They consit of a PyTorch-Tensor
+ and a space. ``Points`` store data in a tensor with 2-axis, the first corresponding
+ the batch-dimension in a batch of multiple points.
+ The second axis collects the space dimensionalities.
+"""
+
+from .space import (Space,
+ R1, R2, R3, Rn)
+from .points import Points
+from .functionspace import FunctionSpace
\ No newline at end of file
diff --git a/DeepINN/geometry_legacy/spaces/functionspace.py b/DeepINN/geometry/spaces/functionspace.py
similarity index 100%
rename from DeepINN/geometry_legacy/spaces/functionspace.py
rename to DeepINN/geometry/spaces/functionspace.py
diff --git a/DeepINN/geometry_legacy/spaces/points.py b/DeepINN/geometry/spaces/points.py
similarity index 100%
rename from DeepINN/geometry_legacy/spaces/points.py
rename to DeepINN/geometry/spaces/points.py
diff --git a/DeepINN/geometry/spaces/space.py b/DeepINN/geometry/spaces/space.py
index 0512b90..c3f10ba 100644
--- a/DeepINN/geometry/spaces/space.py
+++ b/DeepINN/geometry/spaces/space.py
@@ -1,147 +1,198 @@
from collections import Counter, OrderedDict
-"""
-* A Counter is a dict subclass for counting hashable objects. It is a collection where elements are stored as dictionary keys and their counts are stored as dictionary values.
-* An OrderedDict is a dictionary subclass that remembers the order in which items are inserted.
-"""
class Space(Counter, OrderedDict):
- """
- Base class to define the dimensions of the variables in the differential equation.
-
+ """A Space defines (and assigns) the dimensions of the variables
+ that appear in the differentialequation. This class sholud not be instanced
+ directly, rather the corresponding child classes.
+
Parameters
----------
- variables_dims: dict
- A dict containing name of variables and the dimension of each variable.
+ variables_dims : dict
+ A dictionary containing the name of the variables and the dimension
+ of the respective variable.
"""
def __init__(self, variables_dims):
# set counter of variable names and their dimensionalities
- # Since the Counter is inherited first, if the super().__init__ is consumed by Counter then the second super class won't receive the call.
super().__init__(variables_dims)
- # # Adding a magic method to overload the multiply operator using __mul__
- # def __mul__(self, additional_space):
- # """
- # Combine two spaces to create higher dimension spaces.
- # E.g R1('x')*R1('y') is a two dimensional space where one axis is 'x'
- # and the other stands for 'y'.
- # """
- # assert isinstance(additional_space, Space), "The additional dimension isn't an instance of Space"
- # # Since we haven't defined __add__. Python will use Counter's __add__ method
- # return Space(self + additional_space)
-
- # # __contains__ is a predefined method checks if the key (a string) is present in the counter.
- # # whenever we use `in` keyword with if condition involving instances of Space object, this self.__contains__ will run be override python's default __contains__.
- # # here we override this functionpython's default __contains__
- # # So if we do addition __add__ we will end up executing self.__contains__
- # def __contains__(self, space):
- # """
- # Check if the variables of other space are container in this space.
- # There are two possibilities.
- # * method executed for internal dictionary operations such as addition
- # * method executed when checking if intersection of space and self is space.
- # That is why we need to modify python default __contains__ for instances of Space.
-
- # ChatGPT's description:
- # Override the membership test (in) for the Space class.
- # - If `space` is a string: Checks if the variable name (key) exists in this Space.
- # This is useful for both direct membership tests and internal operations
- # (e.g., during dictionary-style key checking in addition).
-
- # - If `space` is another Space object: Determines if the provided Space is
- # entirely contained within the current Space (i.e., if it's a subset).
- # """
- # if isinstance(space,str):
- # #print("Flag: string")
- # # check if the space already contains the variable names.
- # return super().__contains__(space)
- # if isinstance(space, Space):
- # #print("Flag: Space")
- # return (self & space) == space
- # else:
- # return False
-
- # # This is a special method in Python which is invoked when we try to access items from containers like array or dictionary.
- # # It's what gets called when you use square bracket notation to access elements, such as with lists, dictionaries, and strings.
- # def __getitem__(self, val):
- # """
- # Since __getitem__ is used to retrieve items. There are three ways to retrieve items. str, slice, list or tuple.
-
- # 1. In the case of a slice.
- # space_obj = Space({'a': 1, 'b': 2, 'c': 3, 'd': 4})
- # sub_space = space_obj['a':'c'] # returns a Space with {'a': 1, 'b': 2, 'c': 3}
-
- # 2. In the case of a tuple or a list
- # space_obj = Space({'a': 1, 'b': 2, 'c': 3, 'd': 4})
- # sub_space = space_obj[['a', 'c']] # returns a Space with {'a': 1, 'c': 3}
-
- # 3. In all other cases then use Counter's __getitem__.
- # space_obj = Space({'a': 1, 'b': 2, 'c': 3, 'd': 4})
- # value = space_obj['a'] # returns 1
-
- # Parameters
- # ----------
- # val : str, slice, list or tuple
- # The keys that correspond to the variables that should be used in the
- # subspace.
- # """
- # if isinstance(val, slice): # if val is a slice
- # keys = list(self.keys())
- # new_slice = slice(keys.index(val.start) if val.start is not None else None,
- # keys.index(val.stop) if val.stop is not None else None,
- # val.step)
- # new_keys = keys[new_slice]
- # return Space({k: self[k] for k in new_keys})
- # if isinstance(val, list) or isinstance(val, tuple):
- # return Space({k: self[k] for k in val})
- # else:
- # return super().__getitem__(val)
+ def __mul__(self, other):
+ """Creates the product space of the two input spaces. Allows the
+ construction of higher dimensional spaces with 'mixed' variable names.
+ E.g R1('x')*R1('y') is a two dimensional space where one axis is 'x'
+ and the other stands for 'y'.
+ """
+ assert isinstance(other, Space)
+ return Space(self + other)
+
+ def __contains__(self, space):
+ """Checks if the variables of the other space are contained in this
+ space.
+
+ Parameters
+ ----------
+ space : torchphysics.spaces.Space
+ The other Space that should be checked if this is included.
+ """
+ if isinstance(space, str):
+ return super().__contains__(space)
+ if isinstance(space, Space):
+ return (self & space) == space
+ else:
+ return False
- # # To promote encapsulation, @property decorator allows you to print internal read-only attributes of choice.
- # # @property also allows you to call a function without the parentheses. This is useful when these isn't any input attribute.
- # @property
- # def dim(self):
- # """
- # Return the dimension of the space.
- # """
- # # self is the class Space inheriting Counter, which inherits dict, so values() will return list of values for each key of variables_dims. then sum will sum them up.
- # return sum(self.values())
+ def __getitem__(self, val):
+ """Returns a part of the Space dicitionary, specified in the
+ input. Mathematically, this constructs a subspace.
+
+ Parameters
+ ----------
+ val : str, slice, list or tuple
+ The keys that correspond to the variables that should be used in the
+ subspace.
+ """
+ if isinstance(val, slice):
+ keys = list(self.keys())
+ new_slice = slice(keys.index(val.start) if val.start is not None else None,
+ keys.index(val.stop) if val.stop is not None else None,
+ val.step)
+ new_keys = keys[new_slice]
+ return Space({k: self[k] for k in new_keys})
+ if isinstance(val, list) or isinstance(val, tuple):
+ return Space({k: self[k] for k in val})
+ else:
+ return super().__getitem__(val)
+
+ @property
+ def dim(self):
+ """Returns the dimension of the space (sum of factor spaces)
+ """
+ return sum(self.values())
-class R1(Space):
+ @property
+ def variables(self):
+ """
+ A unordered (!) set of variables.
+ """
+ return set(self.keys())
+
+ def __eq__(self, o: object) -> bool:
+ # use OrderedDict equal methode to get order-sensitive comparision
+ return OrderedDict.__eq__(self, o)
+
+ def __ne__(self, o: object) -> bool:
+ return OrderedDict.__ne__(self, o)
+
"""
- Space to define 1D domain.
-
+ Python recipe (see official Python docs) to maintain the insertion order.
+ This way, dimensions with identical variable names will be joined, all
+ other dimensions will be kept in the order of their creation by products
+ or __init__.
+ """
+ def __repr__(self):
+ return '%s(%r)' % (self.__class__.__name__, dict(OrderedDict(self)))
+
+ def __reduce__(self):
+ return self.__class__, (OrderedDict(self),)
+
+ def check_values_in_space(self, values):
+ """Checks if a given tensor is valid to belong to this space.
+
+ Parameters
+ ----------
+ values : torch.tensor
+ A tensor of values that should be checked.
+ Generally the last dimension of the tensor has to fit
+ the dimension of this space.
+
+ Returns
+ -------
+ torch.tensor
+ In the case, that the values have not the corrected shape, but can
+ be reshaped, thet reshaped values are returned.
+ This is used in the matrix-space.
+ """
+ assert values.shape[-1] == self.dim
+ return values
+
+
+class R1(Space):
+ """The space for one dimensional real numbers.
+
Parameters
----------
variable_name: str
The name of the variable that belongs to this space.
- It can be any string for coordinate axes.
"""
def __init__(self, variable_name):
- super().__init__(variable_name, 1)
+ super().__init__({variable_name: 1})
+
class R2(Space):
- """
- Space to define 2D domain.
-
+ """The space for two dimensional real numbers.
+
Parameters
----------
variable_name: str
The name of the variable that belongs to this space.
- It can be any string for coordinate axes.
"""
def __init__(self, variable_name):
- super().__init__(variable_name, 2)
+ super().__init__({variable_name: 2})
+
class R3(Space):
- """
- Space to define 3D domain.
-
+ """The space for three dimensional real numbers.
+
Parameters
----------
variable_name: str
The name of the variable that belongs to this space.
- It can be any string for coordinate axes.
"""
def __init__(self, variable_name):
- super().__init__(variable_name, 3)
\ No newline at end of file
+ super().__init__({variable_name: 3})
+
+
+class Rn(Space):
+ """The space for n dimensional real numbers.
+
+ Parameters
+ ----------
+ variable_name: str
+ The name of the variable that belongs to this space.
+ n : int
+ The dimension of this space.
+ """
+ def __init__(self, variable_name, n : int):
+ super().__init__({variable_name: n})
+
+
+# class M(Space):
+# """The space for n x m matricies. (currently only real numbers)
+
+# Parameters
+# ----------
+# variable_name: str
+# The name of the variable that belongs to this space.
+# n : int
+# The number of rows of the matricies.
+# m : int
+# The number of columns.
+# """
+# def __init__(self, variable_name, n : int, m : int):
+# self.rows = n
+# self.columns = m
+# super().__init__({variable_name: n*m})
+
+# def __mul__(self, other):
+# raise NotImplementedError("Matrix-spaces can not be multiplied!")
+
+# def check_values_in_space(self, values):
+# v_shape = values.shape
+# if len(v_shape) >= 3 and v_shape[-2] == self.rows and v_shape[-1] == self.columns:
+# # values aready in correct shape
+# return values
+# if values.shape[-1] == self.dim:
+# # maybe values are given as a vector with correct dimension
+# # -> reshape to matrix
+# return values.reshape(-1, self.rows, self.columns)
+# raise AssertionError("Values do not belong to a matrix-space")
\ No newline at end of file
diff --git a/DeepINN/geometry_legacy/__init__.py b/DeepINN/geometry_legacy/__init__.py
deleted file mode 100644
index 3fc0761..0000000
--- a/DeepINN/geometry_legacy/__init__.py
+++ /dev/null
@@ -1,5 +0,0 @@
-# Make the subdirectory callable
-from . import domains
-#from . import conditions
-from . import samplers
-from . import spaces
\ No newline at end of file
diff --git a/DeepINN/geometry_legacy/spaces/__init__.py b/DeepINN/geometry_legacy/spaces/__init__.py
deleted file mode 100644
index 3606008..0000000
--- a/DeepINN/geometry_legacy/spaces/__init__.py
+++ /dev/null
@@ -1,17 +0,0 @@
-"""Contains the Spaces and Points classes.
-
-Spaces
- It's purpose is to define variable names and dimensions that can
- be used in functions, domains, models and more.
-
-Points
- The ``Points`` object is a central part of TorchPhysics. They consit of a PyTorch-Tensor
- and a space. ``Points`` store data in a tensor with 2-axis, the first corresponding
- the batch-dimension in a batch of multiple points.
- The second axis collects the space dimensionalities.
-"""
-
-from .space import (Space,
- R1, R2, R3, Rn)
-from .points import Points
-from .functionspace import FunctionSpace
\ No newline at end of file
diff --git a/DeepINN/geometry_legacy/spaces/space.py b/DeepINN/geometry_legacy/spaces/space.py
deleted file mode 100644
index c3f10ba..0000000
--- a/DeepINN/geometry_legacy/spaces/space.py
+++ /dev/null
@@ -1,198 +0,0 @@
-from collections import Counter, OrderedDict
-
-
-class Space(Counter, OrderedDict):
- """A Space defines (and assigns) the dimensions of the variables
- that appear in the differentialequation. This class sholud not be instanced
- directly, rather the corresponding child classes.
-
- Parameters
- ----------
- variables_dims : dict
- A dictionary containing the name of the variables and the dimension
- of the respective variable.
- """
- def __init__(self, variables_dims):
- # set counter of variable names and their dimensionalities
- super().__init__(variables_dims)
-
- def __mul__(self, other):
- """Creates the product space of the two input spaces. Allows the
- construction of higher dimensional spaces with 'mixed' variable names.
- E.g R1('x')*R1('y') is a two dimensional space where one axis is 'x'
- and the other stands for 'y'.
- """
- assert isinstance(other, Space)
- return Space(self + other)
-
- def __contains__(self, space):
- """Checks if the variables of the other space are contained in this
- space.
-
- Parameters
- ----------
- space : torchphysics.spaces.Space
- The other Space that should be checked if this is included.
- """
- if isinstance(space, str):
- return super().__contains__(space)
- if isinstance(space, Space):
- return (self & space) == space
- else:
- return False
-
- def __getitem__(self, val):
- """Returns a part of the Space dicitionary, specified in the
- input. Mathematically, this constructs a subspace.
-
- Parameters
- ----------
- val : str, slice, list or tuple
- The keys that correspond to the variables that should be used in the
- subspace.
- """
- if isinstance(val, slice):
- keys = list(self.keys())
- new_slice = slice(keys.index(val.start) if val.start is not None else None,
- keys.index(val.stop) if val.stop is not None else None,
- val.step)
- new_keys = keys[new_slice]
- return Space({k: self[k] for k in new_keys})
- if isinstance(val, list) or isinstance(val, tuple):
- return Space({k: self[k] for k in val})
- else:
- return super().__getitem__(val)
-
- @property
- def dim(self):
- """Returns the dimension of the space (sum of factor spaces)
- """
- return sum(self.values())
-
- @property
- def variables(self):
- """
- A unordered (!) set of variables.
- """
- return set(self.keys())
-
- def __eq__(self, o: object) -> bool:
- # use OrderedDict equal methode to get order-sensitive comparision
- return OrderedDict.__eq__(self, o)
-
- def __ne__(self, o: object) -> bool:
- return OrderedDict.__ne__(self, o)
-
- """
- Python recipe (see official Python docs) to maintain the insertion order.
- This way, dimensions with identical variable names will be joined, all
- other dimensions will be kept in the order of their creation by products
- or __init__.
- """
- def __repr__(self):
- return '%s(%r)' % (self.__class__.__name__, dict(OrderedDict(self)))
-
- def __reduce__(self):
- return self.__class__, (OrderedDict(self),)
-
- def check_values_in_space(self, values):
- """Checks if a given tensor is valid to belong to this space.
-
- Parameters
- ----------
- values : torch.tensor
- A tensor of values that should be checked.
- Generally the last dimension of the tensor has to fit
- the dimension of this space.
-
- Returns
- -------
- torch.tensor
- In the case, that the values have not the corrected shape, but can
- be reshaped, thet reshaped values are returned.
- This is used in the matrix-space.
- """
- assert values.shape[-1] == self.dim
- return values
-
-
-class R1(Space):
- """The space for one dimensional real numbers.
-
- Parameters
- ----------
- variable_name: str
- The name of the variable that belongs to this space.
- """
- def __init__(self, variable_name):
- super().__init__({variable_name: 1})
-
-
-class R2(Space):
- """The space for two dimensional real numbers.
-
- Parameters
- ----------
- variable_name: str
- The name of the variable that belongs to this space.
- """
- def __init__(self, variable_name):
- super().__init__({variable_name: 2})
-
-
-class R3(Space):
- """The space for three dimensional real numbers.
-
- Parameters
- ----------
- variable_name: str
- The name of the variable that belongs to this space.
- """
- def __init__(self, variable_name):
- super().__init__({variable_name: 3})
-
-
-class Rn(Space):
- """The space for n dimensional real numbers.
-
- Parameters
- ----------
- variable_name: str
- The name of the variable that belongs to this space.
- n : int
- The dimension of this space.
- """
- def __init__(self, variable_name, n : int):
- super().__init__({variable_name: n})
-
-
-# class M(Space):
-# """The space for n x m matricies. (currently only real numbers)
-
-# Parameters
-# ----------
-# variable_name: str
-# The name of the variable that belongs to this space.
-# n : int
-# The number of rows of the matricies.
-# m : int
-# The number of columns.
-# """
-# def __init__(self, variable_name, n : int, m : int):
-# self.rows = n
-# self.columns = m
-# super().__init__({variable_name: n*m})
-
-# def __mul__(self, other):
-# raise NotImplementedError("Matrix-spaces can not be multiplied!")
-
-# def check_values_in_space(self, values):
-# v_shape = values.shape
-# if len(v_shape) >= 3 and v_shape[-2] == self.rows and v_shape[-1] == self.columns:
-# # values aready in correct shape
-# return values
-# if values.shape[-1] == self.dim:
-# # maybe values are given as a vector with correct dimension
-# # -> reshape to matrix
-# return values.reshape(-1, self.rows, self.columns)
-# raise AssertionError("Values do not belong to a matrix-space")
\ No newline at end of file
diff --git a/DeepINN/geometry_refactor/__init__.py b/DeepINN/geometry_refactor/__init__.py
new file mode 100644
index 0000000..fc80254
--- /dev/null
+++ b/DeepINN/geometry_refactor/__init__.py
@@ -0,0 +1 @@
+pass
\ No newline at end of file
diff --git a/DeepINN/geometry/points.py b/DeepINN/geometry_refactor/points.py
similarity index 100%
rename from DeepINN/geometry/points.py
rename to DeepINN/geometry_refactor/points.py
diff --git a/DeepINN/geometry_refactor/spaces/__init__.py b/DeepINN/geometry_refactor/spaces/__init__.py
new file mode 100644
index 0000000..1515c26
--- /dev/null
+++ b/DeepINN/geometry_refactor/spaces/__init__.py
@@ -0,0 +1 @@
+from .space import Space, R1, R2, R3
\ No newline at end of file
diff --git a/DeepINN/geometry_refactor/spaces/space.py b/DeepINN/geometry_refactor/spaces/space.py
new file mode 100644
index 0000000..0512b90
--- /dev/null
+++ b/DeepINN/geometry_refactor/spaces/space.py
@@ -0,0 +1,147 @@
+from collections import Counter, OrderedDict
+
+"""
+* A Counter is a dict subclass for counting hashable objects. It is a collection where elements are stored as dictionary keys and their counts are stored as dictionary values.
+* An OrderedDict is a dictionary subclass that remembers the order in which items are inserted.
+"""
+
+class Space(Counter, OrderedDict):
+ """
+ Base class to define the dimensions of the variables in the differential equation.
+
+ Parameters
+ ----------
+ variables_dims: dict
+ A dict containing name of variables and the dimension of each variable.
+ """
+ def __init__(self, variables_dims):
+ # set counter of variable names and their dimensionalities
+ # Since the Counter is inherited first, if the super().__init__ is consumed by Counter then the second super class won't receive the call.
+ super().__init__(variables_dims)
+
+ # # Adding a magic method to overload the multiply operator using __mul__
+ # def __mul__(self, additional_space):
+ # """
+ # Combine two spaces to create higher dimension spaces.
+ # E.g R1('x')*R1('y') is a two dimensional space where one axis is 'x'
+ # and the other stands for 'y'.
+ # """
+ # assert isinstance(additional_space, Space), "The additional dimension isn't an instance of Space"
+ # # Since we haven't defined __add__. Python will use Counter's __add__ method
+ # return Space(self + additional_space)
+
+ # # __contains__ is a predefined method checks if the key (a string) is present in the counter.
+ # # whenever we use `in` keyword with if condition involving instances of Space object, this self.__contains__ will run be override python's default __contains__.
+ # # here we override this functionpython's default __contains__
+ # # So if we do addition __add__ we will end up executing self.__contains__
+ # def __contains__(self, space):
+ # """
+ # Check if the variables of other space are container in this space.
+ # There are two possibilities.
+ # * method executed for internal dictionary operations such as addition
+ # * method executed when checking if intersection of space and self is space.
+ # That is why we need to modify python default __contains__ for instances of Space.
+
+ # ChatGPT's description:
+ # Override the membership test (in) for the Space class.
+ # - If `space` is a string: Checks if the variable name (key) exists in this Space.
+ # This is useful for both direct membership tests and internal operations
+ # (e.g., during dictionary-style key checking in addition).
+
+ # - If `space` is another Space object: Determines if the provided Space is
+ # entirely contained within the current Space (i.e., if it's a subset).
+ # """
+ # if isinstance(space,str):
+ # #print("Flag: string")
+ # # check if the space already contains the variable names.
+ # return super().__contains__(space)
+ # if isinstance(space, Space):
+ # #print("Flag: Space")
+ # return (self & space) == space
+ # else:
+ # return False
+
+ # # This is a special method in Python which is invoked when we try to access items from containers like array or dictionary.
+ # # It's what gets called when you use square bracket notation to access elements, such as with lists, dictionaries, and strings.
+ # def __getitem__(self, val):
+ # """
+ # Since __getitem__ is used to retrieve items. There are three ways to retrieve items. str, slice, list or tuple.
+
+ # 1. In the case of a slice.
+ # space_obj = Space({'a': 1, 'b': 2, 'c': 3, 'd': 4})
+ # sub_space = space_obj['a':'c'] # returns a Space with {'a': 1, 'b': 2, 'c': 3}
+
+ # 2. In the case of a tuple or a list
+ # space_obj = Space({'a': 1, 'b': 2, 'c': 3, 'd': 4})
+ # sub_space = space_obj[['a', 'c']] # returns a Space with {'a': 1, 'c': 3}
+
+ # 3. In all other cases then use Counter's __getitem__.
+ # space_obj = Space({'a': 1, 'b': 2, 'c': 3, 'd': 4})
+ # value = space_obj['a'] # returns 1
+
+ # Parameters
+ # ----------
+ # val : str, slice, list or tuple
+ # The keys that correspond to the variables that should be used in the
+ # subspace.
+ # """
+ # if isinstance(val, slice): # if val is a slice
+ # keys = list(self.keys())
+ # new_slice = slice(keys.index(val.start) if val.start is not None else None,
+ # keys.index(val.stop) if val.stop is not None else None,
+ # val.step)
+ # new_keys = keys[new_slice]
+ # return Space({k: self[k] for k in new_keys})
+ # if isinstance(val, list) or isinstance(val, tuple):
+ # return Space({k: self[k] for k in val})
+ # else:
+ # return super().__getitem__(val)
+
+ # # To promote encapsulation, @property decorator allows you to print internal read-only attributes of choice.
+ # # @property also allows you to call a function without the parentheses. This is useful when these isn't any input attribute.
+ # @property
+ # def dim(self):
+ # """
+ # Return the dimension of the space.
+ # """
+ # # self is the class Space inheriting Counter, which inherits dict, so values() will return list of values for each key of variables_dims. then sum will sum them up.
+ # return sum(self.values())
+
+class R1(Space):
+ """
+ Space to define 1D domain.
+
+ Parameters
+ ----------
+ variable_name: str
+ The name of the variable that belongs to this space.
+ It can be any string for coordinate axes.
+ """
+ def __init__(self, variable_name):
+ super().__init__(variable_name, 1)
+
+class R2(Space):
+ """
+ Space to define 2D domain.
+
+ Parameters
+ ----------
+ variable_name: str
+ The name of the variable that belongs to this space.
+ It can be any string for coordinate axes.
+ """
+ def __init__(self, variable_name):
+ super().__init__(variable_name, 2)
+
+class R3(Space):
+ """
+ Space to define 3D domain.
+
+ Parameters
+ ----------
+ variable_name: str
+ The name of the variable that belongs to this space.
+ It can be any string for coordinate axes.
+ """
+ def __init__(self, variable_name):
+ super().__init__(variable_name, 3)
\ No newline at end of file
diff --git a/DeepINN/model.py b/DeepINN/model.py
index f74611d..5cc21cc 100644
--- a/DeepINN/model.py
+++ b/DeepINN/model.py
@@ -26,7 +26,7 @@ def compile(self, optimiser_string : str, lr : float, metrics_string : str, devi
self.compile_network()
def compile_domain(self):
- # sample collcation points
+ # sample collocation points
self.collocation_point_sample, self.collocation_point_labels = self.domain.sample_collocation_labels()
# sample boundary points
@@ -54,7 +54,7 @@ def train(self, iterations : int = None, display_every : int = None):
self.config.apply_float_type()
self.config.default_device()
- # In 1D problem we need to combine the BCs as there is only one point for each BC, which returns an underfined feature scaling because the ub and lb are same in the denominator
+ # In 1D problem we need to combine the BCs as there is only one point for each BC, which returns an undefined feature scaling because the ub and lb are same in the denominator, so we get infinity
# For problem with multiple points on each boundary, we don't need to combine them.
if self.boundary_point_sample[0].size()[0] == 1: # if row is 1 in the particular boundary tensor
self.boundary_point_sample = torch.cat(self.boundary_point_sample, dim=0)
@@ -80,7 +80,7 @@ def train(self, iterations : int = None, display_every : int = None):
# backprop the total loss
self.total_loss.backward()
- # Update model parameters based on the older values and the backproped gradient
+ # Update model parameters based on the older values and the backprop gradient
self.optimiser.step()
if self.iter % (self.iterations/10) == 0:
print(f"Iteration: {self.iter+1} \t BC Loss: {self.BC_loss:0.4f}\t PDE Loss: {self.PDE_loss:0.4f} \t Loss: {self.total_loss:0.4f}")
diff --git a/Tutorials/5. FCNN/3. model.ipynb b/Tutorials/5. FCNN/3. model.ipynb
index 5ef4669..a47a5c8 100644
--- a/Tutorials/5. FCNN/3. model.ipynb
+++ b/Tutorials/5. FCNN/3. model.ipynb
@@ -9,18 +9,9 @@
},
{
"cell_type": "code",
- "execution_count": 1,
+ "execution_count": 21,
"metadata": {},
- "outputs": [
- {
- "name": "stderr",
- "output_type": "stream",
- "text": [
- "Using default backend: PyTorch\n",
- "Using Pytorch: 2.0.1+cu117\n"
- ]
- }
- ],
+ "outputs": [],
"source": [
"# This is only valid when the package is not installed\n",
"import sys\n",
@@ -38,7 +29,7 @@
},
{
"cell_type": "code",
- "execution_count": 2,
+ "execution_count": 22,
"metadata": {},
"outputs": [],
"source": [
@@ -49,7 +40,7 @@
},
{
"cell_type": "code",
- "execution_count": 3,
+ "execution_count": 23,
"metadata": {},
"outputs": [],
"source": [
@@ -70,7 +61,7 @@
},
{
"cell_type": "code",
- "execution_count": 4,
+ "execution_count": 24,
"metadata": {},
"outputs": [],
"source": [
@@ -88,7 +79,7 @@
},
{
"cell_type": "code",
- "execution_count": 5,
+ "execution_count": 25,
"metadata": {},
"outputs": [],
"source": [
@@ -105,7 +96,7 @@
},
{
"cell_type": "code",
- "execution_count": 6,
+ "execution_count": 26,
"metadata": {},
"outputs": [],
"source": [
@@ -123,7 +114,7 @@
},
{
"cell_type": "code",
- "execution_count": 7,
+ "execution_count": 27,
"metadata": {},
"outputs": [],
"source": [
@@ -134,7 +125,7 @@
},
{
"cell_type": "code",
- "execution_count": 8,
+ "execution_count": 28,
"metadata": {},
"outputs": [],
"source": [
@@ -144,7 +135,7 @@
},
{
"cell_type": "code",
- "execution_count": 9,
+ "execution_count": 29,
"metadata": {},
"outputs": [
{
@@ -171,7 +162,7 @@
},
{
"cell_type": "code",
- "execution_count": 10,
+ "execution_count": 30,
"metadata": {},
"outputs": [
{
@@ -180,7 +171,7 @@
"(torch.optim.adam.Adam, 0.001, MSELoss())"
]
},
- "execution_count": 10,
+ "execution_count": 30,
"metadata": {},
"output_type": "execute_result"
}
@@ -191,41 +182,130 @@
},
{
"cell_type": "code",
- "execution_count": 11,
+ "execution_count": 31,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
- "Iteration: 1 \t BC Loss: 2.1174\t PDE Loss: 12.3646 \t Loss: 14.4820\n",
- "Iteration: 11 \t BC Loss: 1.9977\t PDE Loss: 11.2331 \t Loss: 13.2308\n",
- "Iteration: 21 \t BC Loss: 1.8826\t PDE Loss: 10.1766 \t Loss: 12.0593\n",
- "Iteration: 31 \t BC Loss: 1.7726\t PDE Loss: 9.2003 \t Loss: 10.9729\n",
- "Iteration: 41 \t BC Loss: 1.6678\t PDE Loss: 8.3045 \t Loss: 9.9723\n",
- "Iteration: 51 \t BC Loss: 1.5684\t PDE Loss: 7.4863 \t Loss: 9.0548\n",
- "Iteration: 61 \t BC Loss: 1.4745\t PDE Loss: 6.7411 \t Loss: 8.2156\n",
- "Iteration: 71 \t BC Loss: 1.3859\t PDE Loss: 6.0632 \t Loss: 7.4491\n",
- "Iteration: 81 \t BC Loss: 1.3025\t PDE Loss: 5.4470 \t Loss: 6.7495\n",
- "Iteration: 91 \t BC Loss: 1.2241\t PDE Loss: 4.8870 \t Loss: 6.1111\n",
- "Iteration: 101 \t BC Loss: 1.1505\t PDE Loss: 4.3783 \t Loss: 5.5287\n",
+ "Iteration: 1 \t BC Loss: 0.2236\t PDE Loss: 1.2173 \t Loss: 1.4410\n",
+ "Iteration: 501 \t BC Loss: 0.2387\t PDE Loss: 0.0058 \t Loss: 0.2445\n",
+ "Iteration: 1001 \t BC Loss: 0.2386\t PDE Loss: 0.0054 \t Loss: 0.2440\n",
+ "Iteration: 1501 \t BC Loss: 0.2385\t PDE Loss: 0.0055 \t Loss: 0.2440\n",
+ "Iteration: 2001 \t BC Loss: 0.2385\t PDE Loss: 0.0055 \t Loss: 0.2440\n",
+ "Iteration: 2501 \t BC Loss: 0.2385\t PDE Loss: 0.0055 \t Loss: 0.2440\n",
+ "Iteration: 3001 \t BC Loss: 0.2384\t PDE Loss: 0.0055 \t Loss: 0.2439\n",
+ "Iteration: 3501 \t BC Loss: 0.2384\t PDE Loss: 0.0055 \t Loss: 0.2439\n",
+ "Iteration: 4001 \t BC Loss: 0.2383\t PDE Loss: 0.0055 \t Loss: 0.2439\n",
+ "Iteration: 4501 \t BC Loss: 0.2383\t PDE Loss: 0.0056 \t Loss: 0.2438\n",
+ "Iteration: 5001 \t BC Loss: 0.2382\t PDE Loss: 0.0056 \t Loss: 0.2438\n",
"Training finished\n"
]
}
],
"source": [
- "model.train(iterations = 100)"
+ "model.train(iterations = 5000)"
]
},
{
"cell_type": "code",
- "execution_count": 12,
+ "execution_count": 32,
"metadata": {},
"outputs": [],
"source": [
"# model.iter = 1\n",
"# model.train(iterations = 2000)"
]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 33,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import matplotlib.pyplot as plt"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 34,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "tensor([[0.0476],\n",
+ " [0.0952],\n",
+ " [0.1429],\n",
+ " [0.1905],\n",
+ " [0.2381],\n",
+ " [0.2857],\n",
+ " [0.3333],\n",
+ " [0.3810],\n",
+ " [0.4286],\n",
+ " [0.4762],\n",
+ " [0.5238],\n",
+ " [0.5714],\n",
+ " [0.6190],\n",
+ " [0.6667],\n",
+ " [0.7143],\n",
+ " [0.7619],\n",
+ " [0.8095],\n",
+ " [0.8571],\n",
+ " [0.9048],\n",
+ " [0.9524]], device='cuda:0', requires_grad=True)"
+ ]
+ },
+ "execution_count": 34,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "model.collocation_point_sample"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 35,
+ "metadata": {},
+ "outputs": [
+ {
+ "ename": "TypeError",
+ "evalue": "can't convert cuda:0 device type tensor to numpy. Use Tensor.cpu() to copy the tensor to host memory first.",
+ "output_type": "error",
+ "traceback": [
+ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
+ "\u001b[0;31mTypeError\u001b[0m Traceback (most recent call last)",
+ "\u001b[1;32m/home/hell/Desktop/repos/DeepINN/Tutorials/5. FCNN/3. model.ipynb Cell 19\u001b[0m line \u001b[0;36m1\n\u001b[0;32m----> 1\u001b[0m plt\u001b[39m.\u001b[39;49mscatter(model\u001b[39m.\u001b[39;49mcollocation_point_sample, model\u001b[39m.\u001b[39;49mBC_forward)\n",
+ "File \u001b[0;32m~/Desktop/repos/DeepINN/.venv/lib/python3.8/site-packages/matplotlib/pyplot.py:2862\u001b[0m, in \u001b[0;36mscatter\u001b[0;34m(x, y, s, c, marker, cmap, norm, vmin, vmax, alpha, linewidths, edgecolors, plotnonfinite, data, **kwargs)\u001b[0m\n\u001b[1;32m 2857\u001b[0m \u001b[39m@_copy_docstring_and_deprecators\u001b[39m(Axes\u001b[39m.\u001b[39mscatter)\n\u001b[1;32m 2858\u001b[0m \u001b[39mdef\u001b[39;00m \u001b[39mscatter\u001b[39m(\n\u001b[1;32m 2859\u001b[0m x, y, s\u001b[39m=\u001b[39m\u001b[39mNone\u001b[39;00m, c\u001b[39m=\u001b[39m\u001b[39mNone\u001b[39;00m, marker\u001b[39m=\u001b[39m\u001b[39mNone\u001b[39;00m, cmap\u001b[39m=\u001b[39m\u001b[39mNone\u001b[39;00m, norm\u001b[39m=\u001b[39m\u001b[39mNone\u001b[39;00m,\n\u001b[1;32m 2860\u001b[0m vmin\u001b[39m=\u001b[39m\u001b[39mNone\u001b[39;00m, vmax\u001b[39m=\u001b[39m\u001b[39mNone\u001b[39;00m, alpha\u001b[39m=\u001b[39m\u001b[39mNone\u001b[39;00m, linewidths\u001b[39m=\u001b[39m\u001b[39mNone\u001b[39;00m, \u001b[39m*\u001b[39m,\n\u001b[1;32m 2861\u001b[0m edgecolors\u001b[39m=\u001b[39m\u001b[39mNone\u001b[39;00m, plotnonfinite\u001b[39m=\u001b[39m\u001b[39mFalse\u001b[39;00m, data\u001b[39m=\u001b[39m\u001b[39mNone\u001b[39;00m, \u001b[39m*\u001b[39m\u001b[39m*\u001b[39mkwargs):\n\u001b[0;32m-> 2862\u001b[0m __ret \u001b[39m=\u001b[39m gca()\u001b[39m.\u001b[39;49mscatter(\n\u001b[1;32m 2863\u001b[0m x, y, s\u001b[39m=\u001b[39;49ms, c\u001b[39m=\u001b[39;49mc, marker\u001b[39m=\u001b[39;49mmarker, cmap\u001b[39m=\u001b[39;49mcmap, norm\u001b[39m=\u001b[39;49mnorm,\n\u001b[1;32m 2864\u001b[0m vmin\u001b[39m=\u001b[39;49mvmin, vmax\u001b[39m=\u001b[39;49mvmax, alpha\u001b[39m=\u001b[39;49malpha, linewidths\u001b[39m=\u001b[39;49mlinewidths,\n\u001b[1;32m 2865\u001b[0m edgecolors\u001b[39m=\u001b[39;49medgecolors, plotnonfinite\u001b[39m=\u001b[39;49mplotnonfinite,\n\u001b[1;32m 2866\u001b[0m \u001b[39m*\u001b[39;49m\u001b[39m*\u001b[39;49m({\u001b[39m\"\u001b[39;49m\u001b[39mdata\u001b[39;49m\u001b[39m\"\u001b[39;49m: data} \u001b[39mif\u001b[39;49;00m data \u001b[39mis\u001b[39;49;00m \u001b[39mnot\u001b[39;49;00m \u001b[39mNone\u001b[39;49;00m \u001b[39melse\u001b[39;49;00m {}), \u001b[39m*\u001b[39;49m\u001b[39m*\u001b[39;49mkwargs)\n\u001b[1;32m 2867\u001b[0m sci(__ret)\n\u001b[1;32m 2868\u001b[0m \u001b[39mreturn\u001b[39;00m __ret\n",
+ "File \u001b[0;32m~/Desktop/repos/DeepINN/.venv/lib/python3.8/site-packages/matplotlib/__init__.py:1442\u001b[0m, in \u001b[0;36m_preprocess_data..inner\u001b[0;34m(ax, data, *args, **kwargs)\u001b[0m\n\u001b[1;32m 1439\u001b[0m \u001b[39m@functools\u001b[39m\u001b[39m.\u001b[39mwraps(func)\n\u001b[1;32m 1440\u001b[0m \u001b[39mdef\u001b[39;00m \u001b[39minner\u001b[39m(ax, \u001b[39m*\u001b[39margs, data\u001b[39m=\u001b[39m\u001b[39mNone\u001b[39;00m, \u001b[39m*\u001b[39m\u001b[39m*\u001b[39mkwargs):\n\u001b[1;32m 1441\u001b[0m \u001b[39mif\u001b[39;00m data \u001b[39mis\u001b[39;00m \u001b[39mNone\u001b[39;00m:\n\u001b[0;32m-> 1442\u001b[0m \u001b[39mreturn\u001b[39;00m func(ax, \u001b[39m*\u001b[39;49m\u001b[39mmap\u001b[39;49m(sanitize_sequence, args), \u001b[39m*\u001b[39;49m\u001b[39m*\u001b[39;49mkwargs)\n\u001b[1;32m 1444\u001b[0m bound \u001b[39m=\u001b[39m new_sig\u001b[39m.\u001b[39mbind(ax, \u001b[39m*\u001b[39margs, \u001b[39m*\u001b[39m\u001b[39m*\u001b[39mkwargs)\n\u001b[1;32m 1445\u001b[0m auto_label \u001b[39m=\u001b[39m (bound\u001b[39m.\u001b[39marguments\u001b[39m.\u001b[39mget(label_namer)\n\u001b[1;32m 1446\u001b[0m \u001b[39mor\u001b[39;00m bound\u001b[39m.\u001b[39mkwargs\u001b[39m.\u001b[39mget(label_namer))\n",
+ "File \u001b[0;32m~/Desktop/repos/DeepINN/.venv/lib/python3.8/site-packages/matplotlib/axes/_axes.py:4581\u001b[0m, in \u001b[0;36mAxes.scatter\u001b[0;34m(self, x, y, s, c, marker, cmap, norm, vmin, vmax, alpha, linewidths, edgecolors, plotnonfinite, **kwargs)\u001b[0m\n\u001b[1;32m 4578\u001b[0m x, y \u001b[39m=\u001b[39m \u001b[39mself\u001b[39m\u001b[39m.\u001b[39m_process_unit_info([(\u001b[39m\"\u001b[39m\u001b[39mx\u001b[39m\u001b[39m\"\u001b[39m, x), (\u001b[39m\"\u001b[39m\u001b[39my\u001b[39m\u001b[39m\"\u001b[39m, y)], kwargs)\n\u001b[1;32m 4579\u001b[0m \u001b[39m# np.ma.ravel yields an ndarray, not a masked array,\u001b[39;00m\n\u001b[1;32m 4580\u001b[0m \u001b[39m# unless its argument is a masked array.\u001b[39;00m\n\u001b[0;32m-> 4581\u001b[0m x \u001b[39m=\u001b[39m np\u001b[39m.\u001b[39;49mma\u001b[39m.\u001b[39;49mravel(x)\n\u001b[1;32m 4582\u001b[0m y \u001b[39m=\u001b[39m np\u001b[39m.\u001b[39mma\u001b[39m.\u001b[39mravel(y)\n\u001b[1;32m 4583\u001b[0m \u001b[39mif\u001b[39;00m x\u001b[39m.\u001b[39msize \u001b[39m!=\u001b[39m y\u001b[39m.\u001b[39msize:\n",
+ "File \u001b[0;32m~/Desktop/repos/DeepINN/.venv/lib/python3.8/site-packages/numpy/ma/core.py:6852\u001b[0m, in \u001b[0;36m_frommethod.__call__\u001b[0;34m(self, a, *args, **params)\u001b[0m\n\u001b[1;32m 6849\u001b[0m args \u001b[39m=\u001b[39m \u001b[39mlist\u001b[39m(args)\n\u001b[1;32m 6850\u001b[0m a, args[\u001b[39m0\u001b[39m] \u001b[39m=\u001b[39m args[\u001b[39m0\u001b[39m], a\n\u001b[0;32m-> 6852\u001b[0m marr \u001b[39m=\u001b[39m asanyarray(a)\n\u001b[1;32m 6853\u001b[0m method_name \u001b[39m=\u001b[39m \u001b[39mself\u001b[39m\u001b[39m.\u001b[39m\u001b[39m__name__\u001b[39m\n\u001b[1;32m 6854\u001b[0m method \u001b[39m=\u001b[39m \u001b[39mgetattr\u001b[39m(\u001b[39mtype\u001b[39m(marr), method_name, \u001b[39mNone\u001b[39;00m)\n",
+ "File \u001b[0;32m~/Desktop/repos/DeepINN/.venv/lib/python3.8/site-packages/numpy/ma/core.py:8132\u001b[0m, in \u001b[0;36masanyarray\u001b[0;34m(a, dtype)\u001b[0m\n\u001b[1;32m 8130\u001b[0m \u001b[39mif\u001b[39;00m \u001b[39misinstance\u001b[39m(a, MaskedArray) \u001b[39mand\u001b[39;00m (dtype \u001b[39mis\u001b[39;00m \u001b[39mNone\u001b[39;00m \u001b[39mor\u001b[39;00m dtype \u001b[39m==\u001b[39m a\u001b[39m.\u001b[39mdtype):\n\u001b[1;32m 8131\u001b[0m \u001b[39mreturn\u001b[39;00m a\n\u001b[0;32m-> 8132\u001b[0m \u001b[39mreturn\u001b[39;00m masked_array(a, dtype\u001b[39m=\u001b[39;49mdtype, copy\u001b[39m=\u001b[39;49m\u001b[39mFalse\u001b[39;49;00m, keep_mask\u001b[39m=\u001b[39;49m\u001b[39mTrue\u001b[39;49;00m, subok\u001b[39m=\u001b[39;49m\u001b[39mTrue\u001b[39;49;00m)\n",
+ "File \u001b[0;32m~/Desktop/repos/DeepINN/.venv/lib/python3.8/site-packages/numpy/ma/core.py:2820\u001b[0m, in \u001b[0;36mMaskedArray.__new__\u001b[0;34m(cls, data, mask, dtype, copy, subok, ndmin, fill_value, keep_mask, hard_mask, shrink, order)\u001b[0m\n\u001b[1;32m 2811\u001b[0m \u001b[39m\u001b[39m\u001b[39m\"\"\"\u001b[39;00m\n\u001b[1;32m 2812\u001b[0m \u001b[39mCreate a new masked array from scratch.\u001b[39;00m\n\u001b[1;32m 2813\u001b[0m \n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 2817\u001b[0m \n\u001b[1;32m 2818\u001b[0m \u001b[39m\"\"\"\u001b[39;00m\n\u001b[1;32m 2819\u001b[0m \u001b[39m# Process data.\u001b[39;00m\n\u001b[0;32m-> 2820\u001b[0m _data \u001b[39m=\u001b[39m np\u001b[39m.\u001b[39;49marray(data, dtype\u001b[39m=\u001b[39;49mdtype, copy\u001b[39m=\u001b[39;49mcopy,\n\u001b[1;32m 2821\u001b[0m order\u001b[39m=\u001b[39;49morder, subok\u001b[39m=\u001b[39;49m\u001b[39mTrue\u001b[39;49;00m, ndmin\u001b[39m=\u001b[39;49mndmin)\n\u001b[1;32m 2822\u001b[0m _baseclass \u001b[39m=\u001b[39m \u001b[39mgetattr\u001b[39m(data, \u001b[39m'\u001b[39m\u001b[39m_baseclass\u001b[39m\u001b[39m'\u001b[39m, \u001b[39mtype\u001b[39m(_data))\n\u001b[1;32m 2823\u001b[0m \u001b[39m# Check that we're not erasing the mask.\u001b[39;00m\n",
+ "File \u001b[0;32m~/Desktop/repos/DeepINN/.venv/lib/python3.8/site-packages/torch/_tensor.py:968\u001b[0m, in \u001b[0;36mTensor.__array__\u001b[0;34m(self, dtype)\u001b[0m\n\u001b[1;32m 966\u001b[0m \u001b[39mdef\u001b[39;00m \u001b[39m__array__\u001b[39m(\u001b[39mself\u001b[39m, dtype\u001b[39m=\u001b[39m\u001b[39mNone\u001b[39;00m):\n\u001b[1;32m 967\u001b[0m \u001b[39mif\u001b[39;00m has_torch_function_unary(\u001b[39mself\u001b[39m):\n\u001b[0;32m--> 968\u001b[0m \u001b[39mreturn\u001b[39;00m handle_torch_function(Tensor\u001b[39m.\u001b[39;49m__array__, (\u001b[39mself\u001b[39;49m,), \u001b[39mself\u001b[39;49m, dtype\u001b[39m=\u001b[39;49mdtype)\n\u001b[1;32m 969\u001b[0m \u001b[39mif\u001b[39;00m dtype \u001b[39mis\u001b[39;00m \u001b[39mNone\u001b[39;00m:\n\u001b[1;32m 970\u001b[0m \u001b[39mreturn\u001b[39;00m \u001b[39mself\u001b[39m\u001b[39m.\u001b[39mnumpy()\n",
+ "File \u001b[0;32m~/Desktop/repos/DeepINN/.venv/lib/python3.8/site-packages/torch/overrides.py:1534\u001b[0m, in \u001b[0;36mhandle_torch_function\u001b[0;34m(public_api, relevant_args, *args, **kwargs)\u001b[0m\n\u001b[1;32m 1530\u001b[0m \u001b[39mif\u001b[39;00m _is_torch_function_mode_enabled():\n\u001b[1;32m 1531\u001b[0m \u001b[39m# if we're here, the mode must be set to a TorchFunctionStackMode\u001b[39;00m\n\u001b[1;32m 1532\u001b[0m \u001b[39m# this unsets it and calls directly into TorchFunctionStackMode's torch function\u001b[39;00m\n\u001b[1;32m 1533\u001b[0m \u001b[39mwith\u001b[39;00m _pop_mode_temporarily() \u001b[39mas\u001b[39;00m mode:\n\u001b[0;32m-> 1534\u001b[0m result \u001b[39m=\u001b[39m mode\u001b[39m.\u001b[39;49m__torch_function__(public_api, types, args, kwargs)\n\u001b[1;32m 1535\u001b[0m \u001b[39mif\u001b[39;00m result \u001b[39mis\u001b[39;00m \u001b[39mnot\u001b[39;00m \u001b[39mNotImplemented\u001b[39m:\n\u001b[1;32m 1536\u001b[0m \u001b[39mreturn\u001b[39;00m result\n",
+ "File \u001b[0;32m~/Desktop/repos/DeepINN/.venv/lib/python3.8/site-packages/torch/utils/_device.py:62\u001b[0m, in \u001b[0;36mDeviceContext.__torch_function__\u001b[0;34m(self, func, types, args, kwargs)\u001b[0m\n\u001b[1;32m 60\u001b[0m \u001b[39mif\u001b[39;00m func \u001b[39min\u001b[39;00m _device_constructors() \u001b[39mand\u001b[39;00m kwargs\u001b[39m.\u001b[39mget(\u001b[39m'\u001b[39m\u001b[39mdevice\u001b[39m\u001b[39m'\u001b[39m) \u001b[39mis\u001b[39;00m \u001b[39mNone\u001b[39;00m:\n\u001b[1;32m 61\u001b[0m kwargs[\u001b[39m'\u001b[39m\u001b[39mdevice\u001b[39m\u001b[39m'\u001b[39m] \u001b[39m=\u001b[39m \u001b[39mself\u001b[39m\u001b[39m.\u001b[39mdevice\n\u001b[0;32m---> 62\u001b[0m \u001b[39mreturn\u001b[39;00m func(\u001b[39m*\u001b[39;49margs, \u001b[39m*\u001b[39;49m\u001b[39m*\u001b[39;49mkwargs)\n",
+ "File \u001b[0;32m~/Desktop/repos/DeepINN/.venv/lib/python3.8/site-packages/torch/_tensor.py:970\u001b[0m, in \u001b[0;36mTensor.__array__\u001b[0;34m(self, dtype)\u001b[0m\n\u001b[1;32m 968\u001b[0m \u001b[39mreturn\u001b[39;00m handle_torch_function(Tensor\u001b[39m.\u001b[39m__array__, (\u001b[39mself\u001b[39m,), \u001b[39mself\u001b[39m, dtype\u001b[39m=\u001b[39mdtype)\n\u001b[1;32m 969\u001b[0m \u001b[39mif\u001b[39;00m dtype \u001b[39mis\u001b[39;00m \u001b[39mNone\u001b[39;00m:\n\u001b[0;32m--> 970\u001b[0m \u001b[39mreturn\u001b[39;00m \u001b[39mself\u001b[39;49m\u001b[39m.\u001b[39;49mnumpy()\n\u001b[1;32m 971\u001b[0m \u001b[39melse\u001b[39;00m:\n\u001b[1;32m 972\u001b[0m \u001b[39mreturn\u001b[39;00m \u001b[39mself\u001b[39m\u001b[39m.\u001b[39mnumpy()\u001b[39m.\u001b[39mastype(dtype, copy\u001b[39m=\u001b[39m\u001b[39mFalse\u001b[39;00m)\n",
+ "\u001b[0;31mTypeError\u001b[0m: can't convert cuda:0 device type tensor to numpy. Use Tensor.cpu() to copy the tensor to host memory first."
+ ]
+ },
+ {
+ "data": {
+ "image/png": "iVBORw0KGgoAAAANSUhEUgAAAi4AAAGiCAYAAADA0E3hAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/bCgiHAAAACXBIWXMAAA9hAAAPYQGoP6dpAAAcw0lEQVR4nO3db2zdVf3A8U/b0VsItEzn2m0WKyiiAhturBYkiKk2gUz3wDjBbHPhj+AkuEZlY7CK6DoRyKIrLkwQH6ibEDDGLUOsLgapWdjWBGSDwMBNYwsT184iLWu/vweG+qvrYLf0z077eiX3wY7n3O+5Hkbf3H8tyLIsCwCABBSO9QYAAI6VcAEAkiFcAIBkCBcAIBnCBQBIhnABAJIhXACAZAgXACAZwgUASIZwAQCSkXe4/OEPf4h58+bF9OnTo6CgIH75y1++5Zpt27bFRz7ykcjlcvG+970v7r///iFsFQCY6PIOl66urpg5c2Y0NTUd0/wXXnghLrvssrjkkkuitbU1vvrVr8ZVV10VjzzySN6bBQAmtoK380sWCwoK4uGHH4758+cfdc6NN94Ymzdvjqeeeqp/7POf/3wcPHgwtm7dOtRLAwAT0KSRvkBLS0vU1tYOGKurq4uvfvWrR13T3d0d3d3d/X/u6+uLV155Jd75zndGQUHBSG0VABhGWZbFoUOHYvr06VFYODxvqx3xcGlra4vy8vIBY+Xl5dHZ2Rn//ve/48QTTzxiTWNjY9x6660jvTUAYBTs378/3v3udw/LfY14uAzFihUror6+vv/PHR0dcdppp8X+/fujtLR0DHcGAByrzs7OqKysjFNOOWXY7nPEw6WioiLa29sHjLW3t0dpaemgz7ZERORyucjlckeMl5aWChcASMxwvs1jxL/HpaamJpqbmweMPfroo1FTUzPSlwYAxpm8w+Vf//pXtLa2Rmtra0T85+POra2tsW/fvoj4z8s8ixYt6p9/7bXXxt69e+Mb3/hG7NmzJ+6+++74xS9+EcuWLRueRwAATBh5h8sTTzwR5513Xpx33nkREVFfXx/nnXderFq1KiIi/v73v/dHTETEe9/73ti8eXM8+uijMXPmzLjzzjvjRz/6UdTV1Q3TQwAAJoq39T0uo6WzszPKysqio6PDe1wAIBEj8fPb7yoCAJIhXACAZAgXACAZwgUASIZwAQCSIVwAgGQIFwAgGcIFAEiGcAEAkiFcAIBkCBcAIBnCBQBIhnABAJIhXACAZAgXACAZwgUASIZwAQCSIVwAgGQIFwAgGcIFAEiGcAEAkiFcAIBkCBcAIBnCBQBIhnABAJIhXACAZAgXACAZwgUASIZwAQCSIVwAgGQIFwAgGcIFAEiGcAEAkiFcAIBkCBcAIBnCBQBIhnABAJIhXACAZAgXACAZwgUASIZwAQCSIVwAgGQIFwAgGcIFAEiGcAEAkiFcAIBkCBcAIBnCBQBIhnABAJIhXACAZAgXACAZwgUASIZwAQCSIVwAgGQIFwAgGcIFAEiGcAEAkiFcAIBkCBcAIBnCBQBIhnABAJIhXACAZAgXACAZQwqXpqamqKqqipKSkqiuro7t27e/6fy1a9fGBz7wgTjxxBOjsrIyli1bFq+99tqQNgwATFx5h8umTZuivr4+GhoaYufOnTFz5syoq6uLl156adD5P/vZz2L58uXR0NAQu3fvjnvvvTc2bdoUN91009vePAAwseQdLnfddVdcffXVsWTJkvjQhz4U69evj5NOOinuu+++Qec//vjjceGFF8YVV1wRVVVV8alPfSouv/zyt3yWBgDgf+UVLj09PbFjx46ora397x0UFkZtbW20tLQMuuaCCy6IHTt29IfK3r17Y8uWLXHppZce9Trd3d3R2dk54AYAMCmfyQcOHIje3t4oLy8fMF5eXh579uwZdM0VV1wRBw4ciI997GORZVkcPnw4rr322jd9qaixsTFuvfXWfLYGAEwAI/6pom3btsXq1avj7rvvjp07d8ZDDz0Umzdvjttuu+2oa1asWBEdHR39t/3794/0NgGABOT1jMuUKVOiqKgo2tvbB4y3t7dHRUXFoGtuueWWWLhwYVx11VUREXHOOedEV1dXXHPNNbFy5cooLDyynXK5XORyuXy2BgBMAHk941JcXByzZ8+O5ubm/rG+vr5obm6OmpqaQde8+uqrR8RJUVFRRERkWZbvfgGACSyvZ1wiIurr62Px4sUxZ86cmDt3bqxduza6urpiyZIlERGxaNGimDFjRjQ2NkZExLx58+Kuu+6K8847L6qrq+O5556LW265JebNm9cfMAAAxyLvcFmwYEG8/PLLsWrVqmhra4tZs2bF1q1b+9+wu2/fvgHPsNx8881RUFAQN998c/ztb3+Ld73rXTFv3rz4zne+M3yPAgCYEAqyBF6v6ezsjLKysujo6IjS0tKx3g4AcAxG4ue331UEACRDuAAAyRAuAEAyhAsAkAzhAgAkQ7gAAMkQLgBAMoQLAJAM4QIAJEO4AADJEC4AQDKECwCQDOECACRDuAAAyRAuAEAyhAsAkAzhAgAkQ7gAAMkQLgBAMoQLAJAM4QIAJEO4AADJEC4AQDKECwCQDOECACRDuAAAyRAuAEAyhAsAkAzhAgAkQ7gAAMkQLgBAMoQLAJAM4QIAJEO4AADJEC4AQDKECwCQDOECACRDuAAAyRAuAEAyhAsAkAzhAgAkQ7gAAMkQLgBAMoQLAJAM4QIAJEO4AADJEC4AQDKECwCQDOECACRDuAAAyRAuAEAyhAsAkAzhAgAkQ7gAAMkQLgBAMoQLAJAM4QIAJEO4AADJEC4AQDKECwCQDOECACRDuAAAyRAuAEAyhhQuTU1NUVVVFSUlJVFdXR3bt29/0/kHDx6MpUuXxrRp0yKXy8WZZ54ZW7ZsGdKGAYCJa1K+CzZt2hT19fWxfv36qK6ujrVr10ZdXV0888wzMXXq1CPm9/T0xCc/+cmYOnVqPPjggzFjxoz4y1/+Eqeeeupw7B8AmEAKsizL8llQXV0d559/fqxbty4iIvr6+qKysjKuv/76WL58+RHz169fH9/73vdiz549ccIJJwxpk52dnVFWVhYdHR1RWlo6pPsAAEbXSPz8zuulop6entixY0fU1tb+9w4KC6O2tjZaWloGXfOrX/0qampqYunSpVFeXh5nn312rF69Onp7e496ne7u7ujs7BxwAwDIK1wOHDgQvb29UV5ePmC8vLw82traBl2zd+/eePDBB6O3tze2bNkSt9xyS9x5553x7W9/+6jXaWxsjLKysv5bZWVlPtsEAMapEf9UUV9fX0ydOjXuueeemD17dixYsCBWrlwZ69evP+qaFStWREdHR/9t//79I71NACABeb05d8qUKVFUVBTt7e0Dxtvb26OiomLQNdOmTYsTTjghioqK+sc++MEPRltbW/T09ERxcfERa3K5XORyuXy2BgBMAHk941JcXByzZ8+O5ubm/rG+vr5obm6OmpqaQddceOGF8dxzz0VfX1//2LPPPhvTpk0bNFoAAI4m75eK6uvrY8OGDfGTn/wkdu/eHdddd110dXXFkiVLIiJi0aJFsWLFiv751113Xbzyyitxww03xLPPPhubN2+O1atXx9KlS4fvUQAAE0Le3+OyYMGCePnll2PVqlXR1tYWs2bNiq1bt/a/YXffvn1RWPjfHqqsrIxHHnkkli1bFueee27MmDEjbrjhhrjxxhuH71EAABNC3t/jMhZ8jwsApGfMv8cFAGAsCRcAIBnCBQBIhnABAJIhXACAZAgXACAZwgUASIZwAQCSIVwAgGQIFwAgGcIFAEiGcAEAkiFcAIBkCBcAIBnCBQBIhnABAJIhXACAZAgXACAZwgUASIZwAQCSIVwAgGQIFwAgGcIFAEiGcAEAkiFcAIBkCBcAIBnCBQBIhnABAJIhXACAZAgXACAZwgUASIZwAQCSIVwAgGQIFwAgGcIFAEiGcAEAkiFcAIBkCBcAIBnCBQBIhnABAJIhXACAZAgXACAZwgUASIZwAQCSIVwAgGQIFwAgGcIFAEiGcAEAkiFcAIBkCBcAIBnCBQBIhnABAJIhXACAZAgXACAZwgUASIZwAQCSIVwAgGQIFwAgGcIFAEiGcAEAkiFcAIBkCBcAIBnCBQBIxpDCpampKaqqqqKkpCSqq6tj+/btx7Ru48aNUVBQEPPnzx/KZQGACS7vcNm0aVPU19dHQ0ND7Ny5M2bOnBl1dXXx0ksvvem6F198Mb72ta/FRRddNOTNAgATW97hctddd8XVV18dS5YsiQ996EOxfv36OOmkk+K+++476pre3t74whe+ELfeemucfvrpb3mN7u7u6OzsHHADAMgrXHp6emLHjh1RW1v73zsoLIza2tpoaWk56rpvfetbMXXq1LjyyiuP6TqNjY1RVlbWf6usrMxnmwDAOJVXuBw4cCB6e3ujvLx8wHh5eXm0tbUNuuaxxx6Le++9NzZs2HDM11mxYkV0dHT03/bv35/PNgGAcWrSSN75oUOHYuHChbFhw4aYMmXKMa/L5XKRy+VGcGcAQIryCpcpU6ZEUVFRtLe3Dxhvb2+PioqKI+Y///zz8eKLL8a8efP6x/r6+v5z4UmT4plnnokzzjhjKPsGACagvF4qKi4ujtmzZ0dzc3P/WF9fXzQ3N0dNTc0R888666x48skno7W1tf/26U9/Oi655JJobW313hUAIC95v1RUX18fixcvjjlz5sTcuXNj7dq10dXVFUuWLImIiEWLFsWMGTOisbExSkpK4uyzzx6w/tRTT42IOGIcAOCt5B0uCxYsiJdffjlWrVoVbW1tMWvWrNi6dWv/G3b37dsXhYW+kBcAGH4FWZZlY72Jt9LZ2RllZWXR0dERpaWlY70dAOAYjMTPb0+NAADJEC4AQDKECwCQDOECACRDuAAAyRAuAEAyhAsAkAzhAgAkQ7gAAMkQLgBAMoQLAJAM4QIAJEO4AADJEC4AQDKECwCQDOECACRDuAAAyRAuAEAyhAsAkAzhAgAkQ7gAAMkQLgBAMoQLAJAM4QIAJEO4AADJEC4AQDKECwCQDOECACRDuAAAyRAuAEAyhAsAkAzhAgAkQ7gAAMkQLgBAMoQLAJAM4QIAJEO4AADJEC4AQDKECwCQDOECACRDuAAAyRAuAEAyhAsAkAzhAgAkQ7gAAMkQLgBAMoQLAJAM4QIAJEO4AADJEC4AQDKECwCQDOECACRDuAAAyRAuAEAyhAsAkAzhAgAkQ7gAAMkQLgBAMoQLAJAM4QIAJEO4AADJEC4AQDKECwCQjCGFS1NTU1RVVUVJSUlUV1fH9u3bjzp3w4YNcdFFF8XkyZNj8uTJUVtb+6bzAQCOJu9w2bRpU9TX10dDQ0Ps3LkzZs6cGXV1dfHSSy8NOn/btm1x+eWXx+9///toaWmJysrK+NSnPhV/+9vf3vbmAYCJpSDLsiyfBdXV1XH++efHunXrIiKir68vKisr4/rrr4/ly5e/5fre3t6YPHlyrFu3LhYtWjTonO7u7uju7u7/c2dnZ1RWVkZHR0eUlpbms10AYIx0dnZGWVnZsP78zusZl56entixY0fU1tb+9w4KC6O2tjZaWlqO6T5effXVeP311+Md73jHUec0NjZGWVlZ/62ysjKfbQIA41Re4XLgwIHo7e2N8vLyAePl5eXR1tZ2TPdx4403xvTp0wfEz/9asWJFdHR09N/279+fzzYBgHFq0mhebM2aNbFx48bYtm1blJSUHHVeLpeLXC43ijsDAFKQV7hMmTIlioqKor29fcB4e3t7VFRUvOnaO+64I9asWRO//e1v49xzz81/pwDAhJfXS0XFxcUxe/bsaG5u7h/r6+uL5ubmqKmpOeq622+/PW677bbYunVrzJkzZ+i7BQAmtLxfKqqvr4/FixfHnDlzYu7cubF27dro6uqKJUuWRETEokWLYsaMGdHY2BgREd/97ndj1apV8bOf/Syqqqr63wtz8sknx8knnzyMDwUAGO/yDpcFCxbEyy+/HKtWrYq2traYNWtWbN26tf8Nu/v27YvCwv8+kfPDH/4wenp64rOf/eyA+2loaIhvfvObb2/3AMCEkvf3uIyFkfgcOAAwssb8e1wAAMaScAEAkiFcAIBkCBcAIBnCBQBIhnABAJIhXACAZAgXACAZwgUASIZwAQCSIVwAgGQIFwAgGcIFAEiGcAEAkiFcAIBkCBcAIBnCBQBIhnABAJIhXACAZAgXACAZwgUASIZwAQCSIVwAgGQIFwAgGcIFAEiGcAEAkiFcAIBkCBcAIBnCBQBIhnABAJIhXACAZAgXACAZwgUASIZwAQCSIVwAgGQIFwAgGcIFAEiGcAEAkiFcAIBkCBcAIBnCBQBIhnABAJIhXACAZAgXACAZwgUASIZwAQCSIVwAgGQIFwAgGcIFAEiGcAEAkiFcAIBkCBcAIBnCBQBIhnABAJIhXACAZAgXACAZwgUASIZwAQCSIVwAgGQIFwAgGcIFAEiGcAEAkiFcAIBkDClcmpqaoqqqKkpKSqK6ujq2b9/+pvMfeOCBOOuss6KkpCTOOeec2LJly5A2CwBMbHmHy6ZNm6K+vj4aGhpi586dMXPmzKirq4uXXnpp0PmPP/54XH755XHllVfGrl27Yv78+TF//vx46qmn3vbmAYCJpSDLsiyfBdXV1XH++efHunXrIiKir68vKisr4/rrr4/ly5cfMX/BggXR1dUVv/71r/vHPvrRj8asWbNi/fr1g16ju7s7uru7+//c0dERp512Wuzfvz9KS0vz2S4AMEY6OzujsrIyDh48GGVlZcNyn5PymdzT0xM7duyIFStW9I8VFhZGbW1ttLS0DLqmpaUl6uvrB4zV1dXFL3/5y6Nep7GxMW699dYjxisrK/PZLgBwHPjHP/4xNuFy4MCB6O3tjfLy8gHj5eXlsWfPnkHXtLW1DTq/ra3tqNdZsWLFgNg5ePBgvOc974l9+/YN2wNnaN6oZ89+jT1ncfxwFscX53H8eOMVk3e84x3Ddp95hctoyeVykcvljhgvKyvzD+FxorS01FkcJ5zF8cNZHF+cx/GjsHD4PsSc1z1NmTIlioqKor29fcB4e3t7VFRUDLqmoqIir/kAAEeTV7gUFxfH7Nmzo7m5uX+sr68vmpubo6amZtA1NTU1A+ZHRDz66KNHnQ8AcDR5v1RUX18fixcvjjlz5sTcuXNj7dq10dXVFUuWLImIiEWLFsWMGTOisbExIiJuuOGGuPjii+POO++Myy67LDZu3BhPPPFE3HPPPcd8zVwuFw0NDYO+fMTochbHD2dx/HAWxxfncfwYibPI++PQERHr1q2L733ve9HW1hazZs2K73//+1FdXR0RER//+Mejqqoq7r///v75DzzwQNx8883x4osvxvvf//64/fbb49JLLx22BwEATAxDChcAgLHgdxUBAMkQLgBAMoQLAJAM4QIAJOO4CZempqaoqqqKkpKSqK6uju3bt7/p/AceeCDOOuusKCkpiXPOOSe2bNkySjsd//I5iw0bNsRFF10UkydPjsmTJ0dtbe1bnh3HLt+/F2/YuHFjFBQUxPz580d2gxNIvmdx8ODBWLp0aUybNi1yuVyceeaZ/j01TPI9i7Vr18YHPvCBOPHEE6OysjKWLVsWr7322ijtdvz6wx/+EPPmzYvp06dHQUHBm/4Owjds27YtPvKRj0Qul4v3ve99Az6BfMyy48DGjRuz4uLi7L777sv+/Oc/Z1dffXV26qmnZu3t7YPO/+Mf/5gVFRVlt99+e/b0009nN998c3bCCSdkTz755CjvfPzJ9yyuuOKKrKmpKdu1a1e2e/fu7Itf/GJWVlaW/fWvfx3lnY8/+Z7FG1544YVsxowZ2UUXXZR95jOfGZ3NjnP5nkV3d3c2Z86c7NJLL80ee+yx7IUXXsi2bduWtba2jvLOx598z+KnP/1plsvlsp/+9KfZCy+8kD3yyCPZtGnTsmXLlo3yzsefLVu2ZCtXrsweeuihLCKyhx9++E3n7927NzvppJOy+vr67Omnn85+8IMfZEVFRdnWrVvzuu5xES5z587Nli5d2v/n3t7ebPr06VljY+Og8z/3uc9ll1122YCx6urq7Etf+tKI7nMiyPcs/tfhw4ezU045JfvJT34yUlucMIZyFocPH84uuOCC7Ec/+lG2ePFi4TJM8j2LH/7wh9npp5+e9fT0jNYWJ4x8z2Lp0qXZJz7xiQFj9fX12YUXXjii+5xojiVcvvGNb2Qf/vCHB4wtWLAgq6ury+taY/5SUU9PT+zYsSNqa2v7xwoLC6O2tjZaWloGXdPS0jJgfkREXV3dUedzbIZyFv/r1Vdfjddff31YfxPoRDTUs/jWt74VU6dOjSuvvHI0tjkhDOUsfvWrX0VNTU0sXbo0ysvL4+yzz47Vq1dHb2/vaG17XBrKWVxwwQWxY8eO/peT9u7dG1u2bPElqGNguH52j/lvhz5w4ED09vZGeXn5gPHy8vLYs2fPoGva2toGnd/W1jZi+5wIhnIW/+vGG2+M6dOnH/EPJ/kZylk89thjce+990Zra+so7HDiGMpZ7N27N373u9/FF77whdiyZUs899xz8eUvfzlef/31aGhoGI1tj0tDOYsrrrgiDhw4EB/72Mciy7I4fPhwXHvttXHTTTeNxpb5f472s7uzszP+/e9/x4knnnhM9zPmz7gwfqxZsyY2btwYDz/8cJSUlIz1diaUQ4cOxcKFC2PDhg0xZcqUsd7OhNfX1xdTp06Ne+65J2bPnh0LFiyIlStXxvr168d6axPOtm3bYvXq1XH33XfHzp0746GHHorNmzfHbbfdNtZbY4jG/BmXKVOmRFFRUbS3tw8Yb29vj4qKikHXVFRU5DWfYzOUs3jDHXfcEWvWrInf/va3ce65547kNieEfM/i+eefjxdffDHmzZvXP9bX1xcREZMmTYpnnnkmzjjjjJHd9Dg1lL8X06ZNixNOOCGKior6xz74wQ9GW1tb9PT0RHFx8YjuebwaylnccsstsXDhwrjqqqsiIuKcc86Jrq6uuOaaa2LlypVRWOi/30fL0X52l5aWHvOzLRHHwTMuxcXFMXv27Ghubu4f6+vri+bm5qipqRl0TU1NzYD5ERGPPvroUedzbIZyFhERt99+e9x2222xdevWmDNnzmhsddzL9yzOOuusePLJJ6O1tbX/9ulPfzouueSSaG1tjcrKytHc/rgylL8XF154YTz33HP98RgR8eyzz8a0adNEy9swlLN49dVXj4iTN4Iy86v6RtWw/ezO733DI2Pjxo1ZLpfL7r///uzpp5/OrrnmmuzUU0/N2trasizLsoULF2bLly/vn//HP/4xmzRpUnbHHXdku3fvzhoaGnwcepjkexZr1qzJiouLswcffDD7+9//3n87dOjQWD2EcSPfs/hfPlU0fPI9i3379mWnnHJK9pWvfCV75plnsl//+tfZ1KlTs29/+9tj9RDGjXzPoqGhITvllFOyn//859nevXuz3/zmN9kZZ5yRfe5znxurhzBuHDp0KNu1a1e2a9euLCKyu+66K9u1a1f2l7/8JcuyLFu+fHm2cOHC/vlvfBz661//erZ79+6sqakp3Y9DZ1mW/eAHP8hOO+20rLi4OJs7d272pz/9qf9/u/jii7PFixcPmP+LX/wiO/PMM7Pi4uLswx/+cLZ58+ZR3vH4lc9ZvOc978ki4ohbQ0PD6G98HMr378X/J1yGV75n8fjjj2fV1dVZLpfLTj/99Ow73/lOdvjw4VHe9fiUz1m8/vrr2Te/+c3sjDPOyEpKSrLKysrsy1/+cvbPf/5z9Dc+zvz+978f9N//b/z/v3jx4uziiy8+Ys2sWbOy4uLi7PTTT89+/OMf533dgizzXBkAkIYxf48LAMCxEi4AQDKECwCQDOECACRDuAAAyRAuAEAyhAsAkAzhAgAkQ7gAAMkQLgBAMoQLAJCM/wM9kKRvAVrZIAAAAABJRU5ErkJggg==",
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "plt.scatter(model.collocation_point_sample, model.BC_forward)"
+ ]
}
],
"metadata": {
diff --git a/todo.md b/todo.md
index 7eba18e..9f14fe2 100644
--- a/todo.md
+++ b/todo.md
@@ -2,9 +2,10 @@
Last work : `DeepINN/constraint/gradients.py`
## Geometry
-- [ ] Geometry added but lot of bloats from TorchPhysics. Clean up geometry folder.
+- [ ] Geometry added but lot of bloats from TorchPhysics. Clean up geometry folder. In progress in "DeepINN/geometry_refactor".
- [ ] Clean up utils folder.
- [ ] Implement anchor points.
+- [ ] Add prediction plot function.
## Gradients
- [x] Implement basic gradients.
@@ -26,6 +27,7 @@ Last work : `DeepINN/constraint/gradients.py`
- [x] Basic geometry tutorials.
- [x] Constraints tutorials.
- [ ] Add template PDE in constraint directory.
+- [ ] There is some problem with FCNN tutorial. probably the feature scaling isn't working.
## Misc
- [x] Migrate to JupyterBooks.
From b779149e2ffe98d12b85023e3859522413915e2f Mon Sep 17 00:00:00 2001
From: Prakhar Sharma <1915438@swansea.ac.uk>
Date: Fri, 10 Nov 2023 13:43:11 +0000
Subject: [PATCH 5/5] FCNN example working
---
DeepINN/model.py | 5 +
DeepINN/nn/__init__.py | 2 +-
DeepINN/utils/__init__.py | 2 +-
DeepINN/utils/plotting/scatter_points.py | 8 +-
DeepINN/utils/user_fun.py | 8 +-
Tutorials/3. Gradients/1. Gradients.ipynb | 2 +-
Tutorials/5. FCNN/3. model.ipynb | 182 +++++++++++++---------
7 files changed, 126 insertions(+), 83 deletions(-)
diff --git a/DeepINN/model.py b/DeepINN/model.py
index 5cc21cc..a205c3d 100644
--- a/DeepINN/model.py
+++ b/DeepINN/model.py
@@ -47,7 +47,9 @@ def compile_network(self):
print("Network compiled", file=sys.stderr, flush=True)
def train(self, iterations : int = None, display_every : int = None):
+
if self.iter == 0: # We are running a fresh training
+ self.training_history = [] # Initialize an empty list for storing loss values
self.iterations = iterations
# Load all the seeds, data types, devices etc.
self.config.apply_seeds()
@@ -85,6 +87,9 @@ def train(self, iterations : int = None, display_every : int = None):
if self.iter % (self.iterations/10) == 0:
print(f"Iteration: {self.iter+1} \t BC Loss: {self.BC_loss:0.4f}\t PDE Loss: {self.PDE_loss:0.4f} \t Loss: {self.total_loss:0.4f}")
+ # Append the total loss value to the training history list
+ self.training_history.append(self.total_loss.item())
+
self.iter = self.iter + 1
else:
print('Training finished')
diff --git a/DeepINN/nn/__init__.py b/DeepINN/nn/__init__.py
index e89231d..c5e41fd 100644
--- a/DeepINN/nn/__init__.py
+++ b/DeepINN/nn/__init__.py
@@ -1,2 +1,2 @@
from .FCNN import BaseNetwork, FullyConnected
-from.utils import activation, initialiser
\ No newline at end of file
+from .utils import activation, initialiser
\ No newline at end of file
diff --git a/DeepINN/utils/__init__.py b/DeepINN/utils/__init__.py
index db9a796..9536e21 100644
--- a/DeepINN/utils/__init__.py
+++ b/DeepINN/utils/__init__.py
@@ -20,7 +20,7 @@
from .data import PointsDataset, PointsDataLoader, DeepONetDataLoader
-from .user_fun import UserFunction
+from .user_fun import UserFunction, tensor2numpy
from .plotting import plot, animate, scatter
from .evaluation import compute_min_and_max
diff --git a/DeepINN/utils/plotting/scatter_points.py b/DeepINN/utils/plotting/scatter_points.py
index 89435b9..d9b1117 100644
--- a/DeepINN/utils/plotting/scatter_points.py
+++ b/DeepINN/utils/plotting/scatter_points.py
@@ -12,10 +12,10 @@ def scatter(subspace, *samplers, dpi=100, save=False):
Parameters
----------
- subspace : torchphysics.problem.Space
+ subspace : dp.problem.Space
The (sub-)space of which the points should be plotted.
Only plotting for dimensions <= 3 is possible.
- *samplers : torchphysics.problem.Samplers
+ *samplers : dp.problem.Samplers
The diffrent samplers for which the points should be plotted.
The plot for each sampler will be created in the order there were
passed in.
@@ -96,4 +96,6 @@ def _scatter_3D(points, labels, dpi, save):
ax.set_ylabel(labels[1])
ax.set_zlabel(labels[2])
if save:
- plt.savefig('geom.jpg', dpi = dpi,bbox_inches='tight',transparent=True)
\ No newline at end of file
+ plt.savefig('geom.jpg', dpi = dpi,bbox_inches='tight',transparent=True)
+
+
diff --git a/DeepINN/utils/user_fun.py b/DeepINN/utils/user_fun.py
index 3916c16..66aeb09 100644
--- a/DeepINN/utils/user_fun.py
+++ b/DeepINN/utils/user_fun.py
@@ -310,4 +310,10 @@ def evaluate_function(self, device='cpu', **inp):
self.fun = self.fun.to(device)
return self.fun
else:
- return torch.tensor(self.fun, device=device).float()
\ No newline at end of file
+ return torch.tensor(self.fun, device=device).float()
+
+def tensor2numpy(tensor_list):
+ """
+ Converts a list of torch.tensors to numpy arrays.
+ """
+ return [tensor.detach().cpu().numpy() for tensor in tensor_list]
diff --git a/Tutorials/3. Gradients/1. Gradients.ipynb b/Tutorials/3. Gradients/1. Gradients.ipynb
index 6302c71..086014a 100644
--- a/Tutorials/3. Gradients/1. Gradients.ipynb
+++ b/Tutorials/3. Gradients/1. Gradients.ipynb
@@ -1251,7 +1251,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
- "version": "3.10.6"
+ "version": "3.8.10"
},
"orig_nbformat": 4
},
diff --git a/Tutorials/5. FCNN/3. model.ipynb b/Tutorials/5. FCNN/3. model.ipynb
index a47a5c8..0ec7bcc 100644
--- a/Tutorials/5. FCNN/3. model.ipynb
+++ b/Tutorials/5. FCNN/3. model.ipynb
@@ -9,9 +9,18 @@
},
{
"cell_type": "code",
- "execution_count": 21,
+ "execution_count": 1,
"metadata": {},
- "outputs": [],
+ "outputs": [
+ {
+ "name": "stderr",
+ "output_type": "stream",
+ "text": [
+ "Using default backend: PyTorch\n",
+ "Using Pytorch: 2.0.1+cu117\n"
+ ]
+ }
+ ],
"source": [
"# This is only valid when the package is not installed\n",
"import sys\n",
@@ -29,7 +38,7 @@
},
{
"cell_type": "code",
- "execution_count": 22,
+ "execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
@@ -40,7 +49,7 @@
},
{
"cell_type": "code",
- "execution_count": 23,
+ "execution_count": 3,
"metadata": {},
"outputs": [],
"source": [
@@ -61,7 +70,7 @@
},
{
"cell_type": "code",
- "execution_count": 24,
+ "execution_count": 4,
"metadata": {},
"outputs": [],
"source": [
@@ -79,7 +88,7 @@
},
{
"cell_type": "code",
- "execution_count": 25,
+ "execution_count": 5,
"metadata": {},
"outputs": [],
"source": [
@@ -88,15 +97,15 @@
" 1D Laplace equation.\n",
" u__x = 0 \n",
" \"\"\"\n",
- " dy_x = dp.constraint.Jacobian(X, y)\n",
- " dy_xx = dp.constraint.Jacobian(X, y)(i = 0, j = 0)\n",
+ " dy_x = dp.constraint.Jacobian(X, y)(i=0, j=0)\n",
+ " dy_xx = dp.constraint.Jacobian(X, dy_x)(i = 0, j = 0)\n",
"\n",
" return dy_xx"
]
},
{
"cell_type": "code",
- "execution_count": 26,
+ "execution_count": 6,
"metadata": {},
"outputs": [],
"source": [
@@ -114,18 +123,18 @@
},
{
"cell_type": "code",
- "execution_count": 27,
+ "execution_count": 7,
"metadata": {},
"outputs": [],
"source": [
"activation = \"tanh\"\n",
"initialiser = \"Xavier normal\"\n",
- "layer_size = [1] + [5] * 1 + [1]"
+ "layer_size = [1] + [2] * 1 + [1]"
]
},
{
"cell_type": "code",
- "execution_count": 28,
+ "execution_count": 8,
"metadata": {},
"outputs": [],
"source": [
@@ -135,7 +144,7 @@
},
{
"cell_type": "code",
- "execution_count": 29,
+ "execution_count": 9,
"metadata": {},
"outputs": [
{
@@ -162,7 +171,7 @@
},
{
"cell_type": "code",
- "execution_count": 30,
+ "execution_count": 10,
"metadata": {},
"outputs": [
{
@@ -171,7 +180,7 @@
"(torch.optim.adam.Adam, 0.001, MSELoss())"
]
},
- "execution_count": 30,
+ "execution_count": 10,
"metadata": {},
"output_type": "execute_result"
}
@@ -182,35 +191,35 @@
},
{
"cell_type": "code",
- "execution_count": 31,
+ "execution_count": 11,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
- "Iteration: 1 \t BC Loss: 0.2236\t PDE Loss: 1.2173 \t Loss: 1.4410\n",
- "Iteration: 501 \t BC Loss: 0.2387\t PDE Loss: 0.0058 \t Loss: 0.2445\n",
- "Iteration: 1001 \t BC Loss: 0.2386\t PDE Loss: 0.0054 \t Loss: 0.2440\n",
- "Iteration: 1501 \t BC Loss: 0.2385\t PDE Loss: 0.0055 \t Loss: 0.2440\n",
- "Iteration: 2001 \t BC Loss: 0.2385\t PDE Loss: 0.0055 \t Loss: 0.2440\n",
- "Iteration: 2501 \t BC Loss: 0.2385\t PDE Loss: 0.0055 \t Loss: 0.2440\n",
- "Iteration: 3001 \t BC Loss: 0.2384\t PDE Loss: 0.0055 \t Loss: 0.2439\n",
- "Iteration: 3501 \t BC Loss: 0.2384\t PDE Loss: 0.0055 \t Loss: 0.2439\n",
- "Iteration: 4001 \t BC Loss: 0.2383\t PDE Loss: 0.0055 \t Loss: 0.2439\n",
- "Iteration: 4501 \t BC Loss: 0.2383\t PDE Loss: 0.0056 \t Loss: 0.2438\n",
- "Iteration: 5001 \t BC Loss: 0.2382\t PDE Loss: 0.0056 \t Loss: 0.2438\n",
+ "Iteration: 1 \t BC Loss: 0.4149\t PDE Loss: 0.0000 \t Loss: 0.4149\n",
+ "Iteration: 51 \t BC Loss: 0.3126\t PDE Loss: 0.0000 \t Loss: 0.3126\n",
+ "Iteration: 101 \t BC Loss: 0.2269\t PDE Loss: 0.0000 \t Loss: 0.2269\n",
+ "Iteration: 151 \t BC Loss: 0.1661\t PDE Loss: 0.0000 \t Loss: 0.1661\n",
+ "Iteration: 201 \t BC Loss: 0.1287\t PDE Loss: 0.0000 \t Loss: 0.1287\n",
+ "Iteration: 251 \t BC Loss: 0.1055\t PDE Loss: 0.0000 \t Loss: 0.1055\n",
+ "Iteration: 301 \t BC Loss: 0.0878\t PDE Loss: 0.0000 \t Loss: 0.0878\n",
+ "Iteration: 351 \t BC Loss: 0.0716\t PDE Loss: 0.0000 \t Loss: 0.0716\n",
+ "Iteration: 401 \t BC Loss: 0.0561\t PDE Loss: 0.0000 \t Loss: 0.0561\n",
+ "Iteration: 451 \t BC Loss: 0.0420\t PDE Loss: 0.0000 \t Loss: 0.0420\n",
+ "Iteration: 501 \t BC Loss: 0.0298\t PDE Loss: 0.0000 \t Loss: 0.0298\n",
"Training finished\n"
]
}
],
"source": [
- "model.train(iterations = 5000)"
+ "model.train(iterations = 500)"
]
},
{
"cell_type": "code",
- "execution_count": 32,
+ "execution_count": 12,
"metadata": {},
"outputs": [],
"source": [
@@ -220,7 +229,52 @@
},
{
"cell_type": "code",
- "execution_count": 33,
+ "execution_count": 13,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "FullyConnected(\n",
+ " (activation): Tanh()\n",
+ " (linears): ModuleList(\n",
+ " (0): Linear(in_features=1, out_features=2, bias=True)\n",
+ " (1): Linear(in_features=2, out_features=1, bias=True)\n",
+ " )\n",
+ ")"
+ ]
+ },
+ "execution_count": 13,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "model.network"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 15,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "coordinates_list = dp.utils.tensor2numpy([model.collocation_point_sample, model.boundary_point_sample])\n",
+ "solution_list = dp.utils.tensor2numpy([model.collocation_forward, model.BC_forward])"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 18,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "history = model.training_history"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 14,
"metadata": {},
"outputs": [],
"source": [
@@ -229,72 +283,45 @@
},
{
"cell_type": "code",
- "execution_count": 34,
+ "execution_count": 16,
"metadata": {},
"outputs": [
{
"data": {
+ "image/png": "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AADYijACAABsldVhJD8/X83NzcrPz7d7KhmNOluHWluDOluDOlsjFeqcFjewAgCAzJXVZ0YAAID9CCMAAMBWhBEAAGArwggAALBVxoeRTZs2qbS0VAUFBSovL9f+/fsn7P/zn/9c119/vQoKCnTzzTdr165dFs00vcVT5y1btqiyslJXXnmlrrzySlVXV1/yfxecF+9nOmzHjh1yOBy66667kjvBDBFvnf/85z9r9erVcrlcys/P17XXXst/PyYh3jq3tLTouuuu0+WXXy6v16sHH3xQn332mUWzTU9vvfWWlixZotmzZ8vhcOi///u/L3lMR0eHvva1ryk/P19f+cpX9MILLyR3kkYG27Fjh5GXl2ds27bN+N3vfmesWrXKuOKKK4z+/v6Y/d9++23D6XQazz77rPH+++8bjz32mJGbm2u89957Fs88vcRb52XLlhmbNm0y3n33XePw4cPGP/zDPxhf/OIXjRMnTlg88/QTb63DPvroI8PtdhuVlZVGTU2NNZNNY/HWeXh42Jg/f77xzW9+09i7d6/x0UcfGR0dHcahQ4csnnl6ibfOL7/8spGfn2+8/PLLxkcffWS89tprhsvlMh588EGLZ55edu3aZTz66KNGIBAwJBm/+MUvJux/7Ngxo7Cw0PD7/cb7779v/PjHPzacTqexe/fupM0xo8PIggULjNWrV49th0IhY/bs2cb69etj9v/2t79t3HnnnRFt5eXlxj/90z8ldZ7pLt46X+zzzz83ZsyYYbz44ovJmmLGmEqtP//8c+PWW281fvrTnxorV64kjExCvHX+yU9+Ylx99dXGyMiIVVPMCPHWefXq1cbf/M3fRLT5/X7jtttuS+o8M8lkwshDDz1k3HjjjRFtS5cuNRYvXpy0eWXsZZqRkREdOHBA1dXVY205OTmqrq5WV1dXzGO6uroi+kvS4sWLx+2PqdX5YkNDQwoGg7rqqquSNc2MMNVaP/nkk5o1a5a++93vWjHNtDeVOv/yl79URUWFVq9ereLiYt10001at26dQqGQVdNOO1Op86233qoDBw6MXco5duyYdu3apW9+85uWzDlb2PFvYVq8KG8qzpw5o1AopOLi4oj24uJiffDBBzGP6evri9m/r68vafNMd1Op88UefvhhzZ49O+rDj0hTqfXevXu1detWHTp0yIIZZoap1PnYsWN6/fXXdffdd2vXrl06evSoHnjgAQWDQTU3N1sx7bQzlTovW7ZMZ86c0e233y7DMPT555/re9/7nr7//e9bMeWsMd6/hQMDA/q///s/XX755Qn/nRl7ZgTp4ZlnntGOHTv0i1/8QgUFBXZPJ6OcO3dOy5cv15YtWzRz5ky7p5PRRkdHNWvWLP3Hf/yH5s2bp6VLl+rRRx/V5s2b7Z5aRuno6NC6dev0/PPP6+DBgwoEAnr11Vf11FNP2T01TFPGnhmZOXOmnE6n+vv7I9r7+/tVUlIS85iSkpK4+mNqdQ7bsGGDnnnmGf3617/WLbfcksxpZoR4a/2HP/xBH3/8sZYsWTLWNjo6Kkm67LLLdOTIEV1zzTXJnXQamspn2uVyKTc3V06nc6zthhtuUF9fn0ZGRpSXl5fUOaejqdT58ccf1/Lly3XvvfdKkm6++WYNDg7qvvvu06OPPqqcHP7/dSKM929hUVFRUs6KSBl8ZiQvL0/z5s1Te3v7WNvo6Kja29tVUVER85iKioqI/pLU1tY2bn9Mrc6S9Oyzz+qpp57S7t27NX/+fCummvbirfX111+v9957T4cOHRr7+ta3vqU77rhDhw4dktfrtXL6aWMqn+nbbrtNR48eHQt7kvThhx/K5XIRRMYxlToPDQ1FBY5wADR4zVrC2PJvYdJujU0BO3bsMPLz840XXnjBeP/994377rvPuOKKK4y+vj7DMAxj+fLlxiOPPDLW/+233zYuu+wyY8OGDcbhw4eN5uZmHu2dhHjr/Mwzzxh5eXlGa2ur0dvbO/Z17tw5u/6EtBFvrS/G0zSTE2+djx8/bsyYMcOor683jhw5YvzP//yPMWvWLOPpp5+2609IC/HWubm52ZgxY4bxyiuvGMeOHTP27NljXHPNNca3v/1tu/6EtHDu3Dnj3XffNd59911DkrFx40bj3XffNT755BPDMAzjkUceMZYvXz7WP/xo77/8y78Yhw8fNjZt2sSjvdP14x//2Pjrv/5rIy8vz1iwYIHxm9/8ZmzfN77xDWPlypUR/f/rv/7LuPbaa428vDzjxhtvNF599VWLZ5ye4qnzl7/8ZUNS1Fdzc7P1E09D8X6mL0QYmbx467xv3z6jvLzcyM/PN66++mrjBz/4gfH5559bPOv0E0+dg8Gg8cQTTxjXXHONUVBQYHi9XuOBBx4w/vSnP1k/8TTyxhtvxPxvbri2K1euNL7xjW9EHVNWVmbk5eUZV199tfGf//mfSZ2jwzA4twUAAOyTsfeMAACA9EAYAQAAtiKMAAAAWxFGAACArQgjAADAVoQRAABgK8IIAACwFWEEAADYijACAABsRRgBAAC2IowAAABbEUYAAICt/j+6RqLRkmH71AAAAABJRU5ErkJggg==",
"text/plain": [
- "tensor([[0.0476],\n",
- " [0.0952],\n",
- " [0.1429],\n",
- " [0.1905],\n",
- " [0.2381],\n",
- " [0.2857],\n",
- " [0.3333],\n",
- " [0.3810],\n",
- " [0.4286],\n",
- " [0.4762],\n",
- " [0.5238],\n",
- " [0.5714],\n",
- " [0.6190],\n",
- " [0.6667],\n",
- " [0.7143],\n",
- " [0.7619],\n",
- " [0.8095],\n",
- " [0.8571],\n",
- " [0.9048],\n",
- " [0.9524]], device='cuda:0', requires_grad=True)"
+ ""
]
},
- "execution_count": 34,
"metadata": {},
- "output_type": "execute_result"
+ "output_type": "display_data"
}
],
"source": [
- "model.collocation_point_sample"
+ "plt.figure(1)\n",
+ "plt.scatter(coordinates_list[0], solution_list[0], label = \"collocation points\", color = \"red\")\n",
+ "plt.scatter(coordinates_list[1], solution_list[1], label = \"boundary points\", color = \"blue\")\n",
+ "plt.grid('minor')"
]
},
{
"cell_type": "code",
- "execution_count": 35,
+ "execution_count": 23,
"metadata": {},
"outputs": [
{
- "ename": "TypeError",
- "evalue": "can't convert cuda:0 device type tensor to numpy. Use Tensor.cpu() to copy the tensor to host memory first.",
- "output_type": "error",
- "traceback": [
- "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
- "\u001b[0;31mTypeError\u001b[0m Traceback (most recent call last)",
- "\u001b[1;32m/home/hell/Desktop/repos/DeepINN/Tutorials/5. FCNN/3. model.ipynb Cell 19\u001b[0m line \u001b[0;36m1\n\u001b[0;32m----> 1\u001b[0m plt\u001b[39m.\u001b[39;49mscatter(model\u001b[39m.\u001b[39;49mcollocation_point_sample, model\u001b[39m.\u001b[39;49mBC_forward)\n",
- "File \u001b[0;32m~/Desktop/repos/DeepINN/.venv/lib/python3.8/site-packages/matplotlib/pyplot.py:2862\u001b[0m, in \u001b[0;36mscatter\u001b[0;34m(x, y, s, c, marker, cmap, norm, vmin, vmax, alpha, linewidths, edgecolors, plotnonfinite, data, **kwargs)\u001b[0m\n\u001b[1;32m 2857\u001b[0m \u001b[39m@_copy_docstring_and_deprecators\u001b[39m(Axes\u001b[39m.\u001b[39mscatter)\n\u001b[1;32m 2858\u001b[0m \u001b[39mdef\u001b[39;00m \u001b[39mscatter\u001b[39m(\n\u001b[1;32m 2859\u001b[0m x, y, s\u001b[39m=\u001b[39m\u001b[39mNone\u001b[39;00m, c\u001b[39m=\u001b[39m\u001b[39mNone\u001b[39;00m, marker\u001b[39m=\u001b[39m\u001b[39mNone\u001b[39;00m, cmap\u001b[39m=\u001b[39m\u001b[39mNone\u001b[39;00m, norm\u001b[39m=\u001b[39m\u001b[39mNone\u001b[39;00m,\n\u001b[1;32m 2860\u001b[0m vmin\u001b[39m=\u001b[39m\u001b[39mNone\u001b[39;00m, vmax\u001b[39m=\u001b[39m\u001b[39mNone\u001b[39;00m, alpha\u001b[39m=\u001b[39m\u001b[39mNone\u001b[39;00m, linewidths\u001b[39m=\u001b[39m\u001b[39mNone\u001b[39;00m, \u001b[39m*\u001b[39m,\n\u001b[1;32m 2861\u001b[0m edgecolors\u001b[39m=\u001b[39m\u001b[39mNone\u001b[39;00m, plotnonfinite\u001b[39m=\u001b[39m\u001b[39mFalse\u001b[39;00m, data\u001b[39m=\u001b[39m\u001b[39mNone\u001b[39;00m, \u001b[39m*\u001b[39m\u001b[39m*\u001b[39mkwargs):\n\u001b[0;32m-> 2862\u001b[0m __ret \u001b[39m=\u001b[39m gca()\u001b[39m.\u001b[39;49mscatter(\n\u001b[1;32m 2863\u001b[0m x, y, s\u001b[39m=\u001b[39;49ms, c\u001b[39m=\u001b[39;49mc, marker\u001b[39m=\u001b[39;49mmarker, cmap\u001b[39m=\u001b[39;49mcmap, norm\u001b[39m=\u001b[39;49mnorm,\n\u001b[1;32m 2864\u001b[0m vmin\u001b[39m=\u001b[39;49mvmin, vmax\u001b[39m=\u001b[39;49mvmax, alpha\u001b[39m=\u001b[39;49malpha, linewidths\u001b[39m=\u001b[39;49mlinewidths,\n\u001b[1;32m 2865\u001b[0m edgecolors\u001b[39m=\u001b[39;49medgecolors, plotnonfinite\u001b[39m=\u001b[39;49mplotnonfinite,\n\u001b[1;32m 2866\u001b[0m \u001b[39m*\u001b[39;49m\u001b[39m*\u001b[39;49m({\u001b[39m\"\u001b[39;49m\u001b[39mdata\u001b[39;49m\u001b[39m\"\u001b[39;49m: data} \u001b[39mif\u001b[39;49;00m data \u001b[39mis\u001b[39;49;00m \u001b[39mnot\u001b[39;49;00m \u001b[39mNone\u001b[39;49;00m \u001b[39melse\u001b[39;49;00m {}), \u001b[39m*\u001b[39;49m\u001b[39m*\u001b[39;49mkwargs)\n\u001b[1;32m 2867\u001b[0m sci(__ret)\n\u001b[1;32m 2868\u001b[0m \u001b[39mreturn\u001b[39;00m __ret\n",
- "File \u001b[0;32m~/Desktop/repos/DeepINN/.venv/lib/python3.8/site-packages/matplotlib/__init__.py:1442\u001b[0m, in \u001b[0;36m_preprocess_data..inner\u001b[0;34m(ax, data, *args, **kwargs)\u001b[0m\n\u001b[1;32m 1439\u001b[0m \u001b[39m@functools\u001b[39m\u001b[39m.\u001b[39mwraps(func)\n\u001b[1;32m 1440\u001b[0m \u001b[39mdef\u001b[39;00m \u001b[39minner\u001b[39m(ax, \u001b[39m*\u001b[39margs, data\u001b[39m=\u001b[39m\u001b[39mNone\u001b[39;00m, \u001b[39m*\u001b[39m\u001b[39m*\u001b[39mkwargs):\n\u001b[1;32m 1441\u001b[0m \u001b[39mif\u001b[39;00m data \u001b[39mis\u001b[39;00m \u001b[39mNone\u001b[39;00m:\n\u001b[0;32m-> 1442\u001b[0m \u001b[39mreturn\u001b[39;00m func(ax, \u001b[39m*\u001b[39;49m\u001b[39mmap\u001b[39;49m(sanitize_sequence, args), \u001b[39m*\u001b[39;49m\u001b[39m*\u001b[39;49mkwargs)\n\u001b[1;32m 1444\u001b[0m bound \u001b[39m=\u001b[39m new_sig\u001b[39m.\u001b[39mbind(ax, \u001b[39m*\u001b[39margs, \u001b[39m*\u001b[39m\u001b[39m*\u001b[39mkwargs)\n\u001b[1;32m 1445\u001b[0m auto_label \u001b[39m=\u001b[39m (bound\u001b[39m.\u001b[39marguments\u001b[39m.\u001b[39mget(label_namer)\n\u001b[1;32m 1446\u001b[0m \u001b[39mor\u001b[39;00m bound\u001b[39m.\u001b[39mkwargs\u001b[39m.\u001b[39mget(label_namer))\n",
- "File \u001b[0;32m~/Desktop/repos/DeepINN/.venv/lib/python3.8/site-packages/matplotlib/axes/_axes.py:4581\u001b[0m, in \u001b[0;36mAxes.scatter\u001b[0;34m(self, x, y, s, c, marker, cmap, norm, vmin, vmax, alpha, linewidths, edgecolors, plotnonfinite, **kwargs)\u001b[0m\n\u001b[1;32m 4578\u001b[0m x, y \u001b[39m=\u001b[39m \u001b[39mself\u001b[39m\u001b[39m.\u001b[39m_process_unit_info([(\u001b[39m\"\u001b[39m\u001b[39mx\u001b[39m\u001b[39m\"\u001b[39m, x), (\u001b[39m\"\u001b[39m\u001b[39my\u001b[39m\u001b[39m\"\u001b[39m, y)], kwargs)\n\u001b[1;32m 4579\u001b[0m \u001b[39m# np.ma.ravel yields an ndarray, not a masked array,\u001b[39;00m\n\u001b[1;32m 4580\u001b[0m \u001b[39m# unless its argument is a masked array.\u001b[39;00m\n\u001b[0;32m-> 4581\u001b[0m x \u001b[39m=\u001b[39m np\u001b[39m.\u001b[39;49mma\u001b[39m.\u001b[39;49mravel(x)\n\u001b[1;32m 4582\u001b[0m y \u001b[39m=\u001b[39m np\u001b[39m.\u001b[39mma\u001b[39m.\u001b[39mravel(y)\n\u001b[1;32m 4583\u001b[0m \u001b[39mif\u001b[39;00m x\u001b[39m.\u001b[39msize \u001b[39m!=\u001b[39m y\u001b[39m.\u001b[39msize:\n",
- "File \u001b[0;32m~/Desktop/repos/DeepINN/.venv/lib/python3.8/site-packages/numpy/ma/core.py:6852\u001b[0m, in \u001b[0;36m_frommethod.__call__\u001b[0;34m(self, a, *args, **params)\u001b[0m\n\u001b[1;32m 6849\u001b[0m args \u001b[39m=\u001b[39m \u001b[39mlist\u001b[39m(args)\n\u001b[1;32m 6850\u001b[0m a, args[\u001b[39m0\u001b[39m] \u001b[39m=\u001b[39m args[\u001b[39m0\u001b[39m], a\n\u001b[0;32m-> 6852\u001b[0m marr \u001b[39m=\u001b[39m asanyarray(a)\n\u001b[1;32m 6853\u001b[0m method_name \u001b[39m=\u001b[39m \u001b[39mself\u001b[39m\u001b[39m.\u001b[39m\u001b[39m__name__\u001b[39m\n\u001b[1;32m 6854\u001b[0m method \u001b[39m=\u001b[39m \u001b[39mgetattr\u001b[39m(\u001b[39mtype\u001b[39m(marr), method_name, \u001b[39mNone\u001b[39;00m)\n",
- "File \u001b[0;32m~/Desktop/repos/DeepINN/.venv/lib/python3.8/site-packages/numpy/ma/core.py:8132\u001b[0m, in \u001b[0;36masanyarray\u001b[0;34m(a, dtype)\u001b[0m\n\u001b[1;32m 8130\u001b[0m \u001b[39mif\u001b[39;00m \u001b[39misinstance\u001b[39m(a, MaskedArray) \u001b[39mand\u001b[39;00m (dtype \u001b[39mis\u001b[39;00m \u001b[39mNone\u001b[39;00m \u001b[39mor\u001b[39;00m dtype \u001b[39m==\u001b[39m a\u001b[39m.\u001b[39mdtype):\n\u001b[1;32m 8131\u001b[0m \u001b[39mreturn\u001b[39;00m a\n\u001b[0;32m-> 8132\u001b[0m \u001b[39mreturn\u001b[39;00m masked_array(a, dtype\u001b[39m=\u001b[39;49mdtype, copy\u001b[39m=\u001b[39;49m\u001b[39mFalse\u001b[39;49;00m, keep_mask\u001b[39m=\u001b[39;49m\u001b[39mTrue\u001b[39;49;00m, subok\u001b[39m=\u001b[39;49m\u001b[39mTrue\u001b[39;49;00m)\n",
- "File \u001b[0;32m~/Desktop/repos/DeepINN/.venv/lib/python3.8/site-packages/numpy/ma/core.py:2820\u001b[0m, in \u001b[0;36mMaskedArray.__new__\u001b[0;34m(cls, data, mask, dtype, copy, subok, ndmin, fill_value, keep_mask, hard_mask, shrink, order)\u001b[0m\n\u001b[1;32m 2811\u001b[0m \u001b[39m\u001b[39m\u001b[39m\"\"\"\u001b[39;00m\n\u001b[1;32m 2812\u001b[0m \u001b[39mCreate a new masked array from scratch.\u001b[39;00m\n\u001b[1;32m 2813\u001b[0m \n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 2817\u001b[0m \n\u001b[1;32m 2818\u001b[0m \u001b[39m\"\"\"\u001b[39;00m\n\u001b[1;32m 2819\u001b[0m \u001b[39m# Process data.\u001b[39;00m\n\u001b[0;32m-> 2820\u001b[0m _data \u001b[39m=\u001b[39m np\u001b[39m.\u001b[39;49marray(data, dtype\u001b[39m=\u001b[39;49mdtype, copy\u001b[39m=\u001b[39;49mcopy,\n\u001b[1;32m 2821\u001b[0m order\u001b[39m=\u001b[39;49morder, subok\u001b[39m=\u001b[39;49m\u001b[39mTrue\u001b[39;49;00m, ndmin\u001b[39m=\u001b[39;49mndmin)\n\u001b[1;32m 2822\u001b[0m _baseclass \u001b[39m=\u001b[39m \u001b[39mgetattr\u001b[39m(data, \u001b[39m'\u001b[39m\u001b[39m_baseclass\u001b[39m\u001b[39m'\u001b[39m, \u001b[39mtype\u001b[39m(_data))\n\u001b[1;32m 2823\u001b[0m \u001b[39m# Check that we're not erasing the mask.\u001b[39;00m\n",
- "File \u001b[0;32m~/Desktop/repos/DeepINN/.venv/lib/python3.8/site-packages/torch/_tensor.py:968\u001b[0m, in \u001b[0;36mTensor.__array__\u001b[0;34m(self, dtype)\u001b[0m\n\u001b[1;32m 966\u001b[0m \u001b[39mdef\u001b[39;00m \u001b[39m__array__\u001b[39m(\u001b[39mself\u001b[39m, dtype\u001b[39m=\u001b[39m\u001b[39mNone\u001b[39;00m):\n\u001b[1;32m 967\u001b[0m \u001b[39mif\u001b[39;00m has_torch_function_unary(\u001b[39mself\u001b[39m):\n\u001b[0;32m--> 968\u001b[0m \u001b[39mreturn\u001b[39;00m handle_torch_function(Tensor\u001b[39m.\u001b[39;49m__array__, (\u001b[39mself\u001b[39;49m,), \u001b[39mself\u001b[39;49m, dtype\u001b[39m=\u001b[39;49mdtype)\n\u001b[1;32m 969\u001b[0m \u001b[39mif\u001b[39;00m dtype \u001b[39mis\u001b[39;00m \u001b[39mNone\u001b[39;00m:\n\u001b[1;32m 970\u001b[0m \u001b[39mreturn\u001b[39;00m \u001b[39mself\u001b[39m\u001b[39m.\u001b[39mnumpy()\n",
- "File \u001b[0;32m~/Desktop/repos/DeepINN/.venv/lib/python3.8/site-packages/torch/overrides.py:1534\u001b[0m, in \u001b[0;36mhandle_torch_function\u001b[0;34m(public_api, relevant_args, *args, **kwargs)\u001b[0m\n\u001b[1;32m 1530\u001b[0m \u001b[39mif\u001b[39;00m _is_torch_function_mode_enabled():\n\u001b[1;32m 1531\u001b[0m \u001b[39m# if we're here, the mode must be set to a TorchFunctionStackMode\u001b[39;00m\n\u001b[1;32m 1532\u001b[0m \u001b[39m# this unsets it and calls directly into TorchFunctionStackMode's torch function\u001b[39;00m\n\u001b[1;32m 1533\u001b[0m \u001b[39mwith\u001b[39;00m _pop_mode_temporarily() \u001b[39mas\u001b[39;00m mode:\n\u001b[0;32m-> 1534\u001b[0m result \u001b[39m=\u001b[39m mode\u001b[39m.\u001b[39;49m__torch_function__(public_api, types, args, kwargs)\n\u001b[1;32m 1535\u001b[0m \u001b[39mif\u001b[39;00m result \u001b[39mis\u001b[39;00m \u001b[39mnot\u001b[39;00m \u001b[39mNotImplemented\u001b[39m:\n\u001b[1;32m 1536\u001b[0m \u001b[39mreturn\u001b[39;00m result\n",
- "File \u001b[0;32m~/Desktop/repos/DeepINN/.venv/lib/python3.8/site-packages/torch/utils/_device.py:62\u001b[0m, in \u001b[0;36mDeviceContext.__torch_function__\u001b[0;34m(self, func, types, args, kwargs)\u001b[0m\n\u001b[1;32m 60\u001b[0m \u001b[39mif\u001b[39;00m func \u001b[39min\u001b[39;00m _device_constructors() \u001b[39mand\u001b[39;00m kwargs\u001b[39m.\u001b[39mget(\u001b[39m'\u001b[39m\u001b[39mdevice\u001b[39m\u001b[39m'\u001b[39m) \u001b[39mis\u001b[39;00m \u001b[39mNone\u001b[39;00m:\n\u001b[1;32m 61\u001b[0m kwargs[\u001b[39m'\u001b[39m\u001b[39mdevice\u001b[39m\u001b[39m'\u001b[39m] \u001b[39m=\u001b[39m \u001b[39mself\u001b[39m\u001b[39m.\u001b[39mdevice\n\u001b[0;32m---> 62\u001b[0m \u001b[39mreturn\u001b[39;00m func(\u001b[39m*\u001b[39;49margs, \u001b[39m*\u001b[39;49m\u001b[39m*\u001b[39;49mkwargs)\n",
- "File \u001b[0;32m~/Desktop/repos/DeepINN/.venv/lib/python3.8/site-packages/torch/_tensor.py:970\u001b[0m, in \u001b[0;36mTensor.__array__\u001b[0;34m(self, dtype)\u001b[0m\n\u001b[1;32m 968\u001b[0m \u001b[39mreturn\u001b[39;00m handle_torch_function(Tensor\u001b[39m.\u001b[39m__array__, (\u001b[39mself\u001b[39m,), \u001b[39mself\u001b[39m, dtype\u001b[39m=\u001b[39mdtype)\n\u001b[1;32m 969\u001b[0m \u001b[39mif\u001b[39;00m dtype \u001b[39mis\u001b[39;00m \u001b[39mNone\u001b[39;00m:\n\u001b[0;32m--> 970\u001b[0m \u001b[39mreturn\u001b[39;00m \u001b[39mself\u001b[39;49m\u001b[39m.\u001b[39;49mnumpy()\n\u001b[1;32m 971\u001b[0m \u001b[39melse\u001b[39;00m:\n\u001b[1;32m 972\u001b[0m \u001b[39mreturn\u001b[39;00m \u001b[39mself\u001b[39m\u001b[39m.\u001b[39mnumpy()\u001b[39m.\u001b[39mastype(dtype, copy\u001b[39m=\u001b[39m\u001b[39mFalse\u001b[39;00m)\n",
- "\u001b[0;31mTypeError\u001b[0m: can't convert cuda:0 device type tensor to numpy. Use Tensor.cpu() to copy the tensor to host memory first."
- ]
+ "data": {
+ "text/plain": [
+ "Text(0, 0.5, 'Loss')"
+ ]
+ },
+ "execution_count": 23,
+ "metadata": {},
+ "output_type": "execute_result"
},
{
"data": {
- "image/png": "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",
+ "image/png": "iVBORw0KGgoAAAANSUhEUgAAAkAAAAGwCAYAAABB4NqyAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/bCgiHAAAACXBIWXMAAA9hAAAPYQGoP6dpAABQtklEQVR4nO3deVxUZf8//tfMwAz7IsuwODogKuICioq4lySalWaLmncUbXdaffNHyy13pW13aIu3udxa3rdptmh1p/npNsxGUVMERXFBxA0EhRlAhAGUbeb8/qCmJpeAgTkD83o+HufxyHOuc3ifY8XrcZ3rXJdEEAQBRERERHZEKnYBRERERNbGAERERER2hwGIiIiI7A4DEBEREdkdBiAiIiKyOwxAREREZHcYgIiIiMjuOIhdgC0yGo0oLi6Gu7s7JBKJ2OUQERFRCwiCgOrqagQFBUEqvXUfDwPQDRQXF0OlUoldBhEREbVBUVERunfvfss2DEA34O7uDqD5AXp4eIhcDREREbWEXq+HSqUy/R6/FQagG/j1tZeHhwcDEBERUSfTkuErHARNREREdocBiIiIiOwOAxARERHZHQYgIiIisjsMQERERGR3GICIiIjI7jAAERERkd1hACIiIiK7wwBEREREdocBiIiIiOwOAxARERHZHQYgIiIisjsMQFZ2tKgSFbUNYpdBRERk1xiArOjt709i6sp9WLP3vNilEBER2TUGICsaHtINAPDp/gJUXmUvEBERkVgYgKzojggl+gV6oLbBgLX7CsQuh4iIyG4xAFmRRCLBc7eHAQA+2ZcPfV2jyBURERHZJwYgK5vUPwC9/d1QXdeE9ewFIiIiEgUDkJVJpRI8+0sv0H/25aOmvknkioiIiOwPA5AI7hoUhFBfV1RebcSG9Atil0NERGR3GIBEIJNK8Mxtzb1A/957Hlcb2AtERERkTQxAIpkaFYQe3VxwubYBX2QUil0OERGRXWEAEomDTIq543sBAD7acx51jQaRKyIiIrIfNhGAVq5cCbVaDScnJ8TExCAzM7NF523cuBESiQTTpk0z2y8IAhYsWIDAwEA4OzsjLi4OZ86c6YDKLTN9SHcEezmjrLoemw4WiV0OERGR3RA9AG3atAlJSUlYuHAhDh8+jMjISMTHx6O0tPSW5xUUFODFF1/EmDFjrjv27rvvYtmyZVi9ejUyMjLg6uqK+Ph41NXVddRttIncQYqnf+kFWpV2DvVN7AUiIiKyBtED0JIlS/Dkk08iMTERERERWL16NVxcXLB27dqbnmMwGDB79my88cYbCA0NNTsmCAKWLl2KV199FVOnTsWgQYPw6aefori4GFu2bOngu2m9B6K7Q+mhgFZfh2+yLopdDhERkV0QNQA1NDQgKysLcXFxpn1SqRRxcXFIT0+/6Xlvvvkm/P398fjjj193LD8/H1qt1uyanp6eiImJuek16+vrodfrzTZrcXKU4elxzb1A/9p1Do0Go9V+NhERkb0SNQCVl5fDYDBAqVSa7VcqldBqtTc85+eff8Z//vMfrFmz5obHfz2vNddMSUmBp6enaVOpVK29FYvMGt4Dvm4KXKq8hs2HL1n1ZxMREdkj0V+BtUZ1dTUefvhhrFmzBr6+vu123eTkZFRVVZm2oiLrDkh2cpThqbEhAICVaWfRxF4gIiKiDuUg5g/39fWFTCaDTqcz26/T6RAQEHBd+3PnzqGgoAB33323aZ/R2BwWHBwckJeXZzpPp9MhMDDQ7JpRUVE3rEOhUEChUFh6OxaZHdMTq3efx4XLV7H1aDGmD+kuaj1ERERdmag9QHK5HNHR0dBoNKZ9RqMRGo0GsbGx17UPDw/H8ePHkZ2dbdruuece3HbbbcjOzoZKpUJISAgCAgLMrqnX65GRkXHDa9oKV4UDHh/d3Au0YtdZGIyCyBURERF1XaL2AAFAUlISHnnkEQwdOhTDhw/H0qVLUVtbi8TERABAQkICgoODkZKSAicnJwwYMMDsfC8vLwAw2z9v3jy8/fbb6N27N0JCQvDaa68hKCjouvmCbE1CbE98vOc8zpfVYtvxEtwdGSR2SURERF2S6AFoxowZKCsrw4IFC6DVahEVFYXU1FTTIObCwkJIpa3rqHr55ZdRW1uLp556CpWVlRg9ejRSU1Ph5OTUEbfQbtydHPHYqBD886fTWL7zDKYMDIRUKhG7LCIioi5HIggC37X8gV6vh6enJ6qqquDh4WHVn111rRGjF+1EdX0TVv9lCCYNCPzzk4iIiKhVv7871Vdg9sDT2RGPjlIDAJZpzoL5lIiIqP0xANmgx0aFwFUuw8kSPTS5t14ShIiIiFqPAcgGebvK8ZfYngCA5TvPsBeIiIionTEA2agnx4TCyVGKoxersOdMudjlEBERdSkMQDbK102B2THNvUDLNOwFIiIiak8MQDbsr2NDIXeQIuvCFaSfuyx2OURERF0GA5AN8/dwwqxhzQuzfqg5I3I1REREXQcDkI3767hecJRJkJFfgcz8CrHLISIi6hIYgGxckJczHhja3Au0fCd7gYiIiNoDA1AnMGdcLzhIJdh7phyHC6+IXQ4REVGnxwDUCai6ueDewcEAmr8IIyIiIsswAHUSz9wWBplUgrS8MhwtqhS7HCIiok6NAaiTUPu6YlpUcy8QvwgjIiKyDANQJ/Lc7c29QDtPlbIXiIiIyAIMQJ3I73uBlv50WuRqiIiIOi8GoE7m116gXXllyGYvEBERUZswAHUyZmOB2AtERETUJgxAnRB7gYiIiCzDANQJsReIiIjIMgxAnRR7gYiIiNqOAaiTUvu6mmaHZi8QERFR6zAAdWLP3vZbL9ARrhFGRETUYgxAnZhZLxBnhyYiImoxBqBO7tnfrRHGXiAiIqKWYQDq5NgLRERE1HoMQF0Ae4GIiIhahwGoC2AvEBERUeswAHURv84LxF4gIiKiP8cA1EX09HHF9MG/rhTPXiAiIqJbYQDqQp79pRdo9+kyHGYvEBER0U0xAHUhv+8F+pC9QERERDfFANTFsBeIiIjozzEAdTEcC0RERPTnbCIArVy5Emq1Gk5OToiJiUFmZuZN23777bcYOnQovLy84OrqiqioKGzYsMGszaOPPgqJRGK2TZo0qaNvw2Y8d3tvOEgl2HO6DAcLKsQuh4iIyOaIHoA2bdqEpKQkLFy4EIcPH0ZkZCTi4+NRWlp6w/bdunXDK6+8gvT0dBw7dgyJiYlITEzE9u3bzdpNmjQJJSUlpu3LL7+0xu3YhB4+LnhgaHcAwAc/5olcDRERke0RPQAtWbIETz75JBITExEREYHVq1fDxcUFa9euvWH78ePH495770W/fv3Qq1cvPP/88xg0aBB+/vlns3YKhQIBAQGmzdvb2xq3YzOevb035DIpDpyvwP6z5WKXQ0REZFNEDUANDQ3IyspCXFycaZ9UKkVcXBzS09P/9HxBEKDRaJCXl4exY8eaHUtLS4O/vz/69u2LOXPm4PLlyze9Tn19PfR6vdnW2QV7OWPWcBUA4IMdpyEIgsgVERER2Q5RA1B5eTkMBgOUSqXZfqVSCa1We9Pzqqqq4ObmBrlcjilTpmD58uW44447TMcnTZqETz/9FBqNBosXL8bu3bsxefJkGAyGG14vJSUFnp6epk2lUrXPDYrsmdvCoHCQIuvCFaSdLhO7HCIiIpvhIHYBbeHu7o7s7GzU1NRAo9EgKSkJoaGhGD9+PABg5syZprYDBw7EoEGD0KtXL6SlpWHChAnXXS85ORlJSUmmP+v1+i4Rgvw9nJAQ2xNr9uZjyY+nMb6PHyQSidhlERERiU7UHiBfX1/IZDLodDqz/TqdDgEBATc9TyqVIiwsDFFRUXjhhRdw//33IyUl5abtQ0ND4evri7Nnz97wuEKhgIeHh9nWVTw9rhdc5DIcv1SFH0/q/vwEIiIiOyBqAJLL5YiOjoZGozHtMxqN0Gg0iI2NbfF1jEYj6uvrb3r84sWLuHz5MgIDAy2qtzPycVMgcZQaAPDPHadhNHIsEBERkehfgSUlJWHNmjVYv349cnNzMWfOHNTW1iIxMREAkJCQgOTkZFP7lJQU7NixA+fPn0dubi4++OADbNiwAX/5y18AADU1NXjppZdw4MABFBQUQKPRYOrUqQgLC0N8fLwo9yi2J8eEwl3hgFPaamw7USJ2OURERKITfQzQjBkzUFZWhgULFkCr1SIqKgqpqammgdGFhYWQSn/LabW1tZg7dy4uXrwIZ2dnhIeH47PPPsOMGTMAADKZDMeOHcP69etRWVmJoKAgTJw4EW+99RYUCoUo9yg2Lxc5nhgTin/+dBr/3HEakwcEQiblWCAiIrJfEoHfR19Hr9fD09MTVVVVXWY8UHVdI8a8uwuVVxux5MFITB/SXeySiIiI2lVrfn+L/gqMrMPdyRF/HdsLQPMaYY0Go8gVERERiYcByI48MrInfN3kKKy4iv9mXRS7HCIiItEwANkRF7kD5owPAwAs05xBfdONJ4YkIiLq6hiA7MzsmB5QeihQXFWHTQeLxC6HiIhIFAxAdsbJUYZnb2vuBVqx8yzqGtkLRERE9ocByA49OEyFYC9nlFbX47MDF8Quh4iIyOoYgOyQwkGG/zehuRdoVdo51NY3iVwRERGRdTEA2anpQ7pD7eOCy7UNWLe/QOxyiIiIrIoByE45yqSYF9cHAPDR7nOoutoockVERETWwwBkx+6ODEJfpTv0dU1Yveec2OUQERFZDQOQHZNJJXgxvi8A4JN9+SjV14lcERERkXUwANm5uH7+GNLDC3WNRizfeVbscoiIiKyCAcjOSSQSvBQfDgD4MrMQhZevilwRERFRx2MAIsT28sHYPn5oMgpYsiNP7HKIiIg6HAMQAQBe/mUs0HdHi3FKqxe5GiIioo7FAEQAgAHBnpgyMBCCALy/nb1ARETUtTEAkUnSxD6QSSX4KbcUWRcqxC6HiIiowzAAkUkvPzfcP6Q7AGBxah4EQRC5IiIioo7BAERmno/rDbmDFJn5Fdh9ukzscoiIiDoEAxCZCfJyRsKIngCA97bnwWhkLxAREXU9DEB0nbm3hcFN4YCcYj22nSgRuxwiIqJ2xwBE1+nmKscTY0IAAB/8eBqNBqPIFREREbUvBiC6oSfGhKKbqxz55bX4Juui2OUQERG1KwYguiE3hQOeuS0MALD0p9O41mAQuSIiIqL2wwBEN/WXET0Q7OUMnb4ea/fli10OERFRu2EAoptSOMjw0i9LZKxKO4fLNfUiV0RERNQ+GIDolu6JDEL/IA/U1Ddh+c6zYpdDRETULhiA6JakUgmSJ/cDAHyecQEXLteKXBEREZHlGIDoT43u7YuxffzQaBDwHhdKJSKiLoABiFpk/qRwSCTA98dKcLSoUuxyiIiILMIARC0SEeSBewcHAwDe2ZbLhVKJiKhTYwCiFnthYl/IHaTIyK/ArrxSscshIiJqMwYgarFgL2ckjlQDABb9cAoGLpRKRESdlE0EoJUrV0KtVsPJyQkxMTHIzMy8adtvv/0WQ4cOhZeXF1xdXREVFYUNGzaYtREEAQsWLEBgYCCcnZ0RFxeHM2fOdPRt2IW548Pg6eyI07oa/JdLZBARUSclegDatGkTkpKSsHDhQhw+fBiRkZGIj49HaemNX7F069YNr7zyCtLT03Hs2DEkJiYiMTER27dvN7V59913sWzZMqxevRoZGRlwdXVFfHw86urqrHVbXZaniyOe/WWJjCU7uEQGERF1ThJB5NGsMTExGDZsGFasWAEAMBqNUKlUeO655zB//vwWXWPIkCGYMmUK3nrrLQiCgKCgILzwwgt48cUXAQBVVVVQKpVYt24dZs6ced359fX1qK//bZZjvV4PlUqFqqoqeHh4tMNddi11jQZM+GA3LlVew0vxfU1rhhEREYlJr9fD09OzRb+/Re0BamhoQFZWFuLi4kz7pFIp4uLikJ6e/qfnC4IAjUaDvLw8jB07FgCQn58PrVZrdk1PT0/ExMTc9JopKSnw9PQ0bSqVysI769qcHH9bImN12jlU1DaIXBEREVHriBqAysvLYTAYoFQqzfYrlUpotdqbnldVVQU3NzfI5XJMmTIFy5cvxx133AEApvNac83k5GRUVVWZtqKiIktuyy78ukRGdX0Tlmk4voqIiDoX0ccAtYW7uzuys7Nx8OBB/OMf/0BSUhLS0tLafD2FQgEPDw+zjW7tj0tk5JdziQwiIuo8RA1Avr6+kMlk0Ol0Zvt1Oh0CAgJuep5UKkVYWBiioqLwwgsv4P7770dKSgoAmM5r7TWp9Ub39sX4vs1LZKRsyxW7HCIiohYTNQDJ5XJER0dDo9GY9hmNRmg0GsTGxrb4Okaj0TSIOSQkBAEBAWbX1Ov1yMjIaNU1qWVeubMfZFIJfjypQ/q5y2KXQ0RE1CKivwJLSkrCmjVrsH79euTm5mLOnDmora1FYmIiACAhIQHJycmm9ikpKdixYwfOnz+P3NxcfPDBB9iwYQP+8pe/AAAkEgnmzZuHt99+G1u3bsXx48eRkJCAoKAgTJs2TYxb7NJ6K93x0PAeAIC3/3eSkyMSEVGn4CB2ATNmzEBZWRkWLFgArVaLqKgopKammgYxFxYWQir9LafV1tZi7ty5uHjxIpydnREeHo7PPvsMM2bMMLV5+eWXUVtbi6eeegqVlZUYPXo0UlNT4eTkZPX7swfz4npjS/Yl5BTr8e3hi3hgKL+iIyIi2yb6PEC2qDXzCFCzj/ecwzvbTsHfXYFdL46Hq0L0bE1ERHam08wDRF3HIyPV6NHNBaXV9fhoz3mxyyEiIrolBiBqFwoHGZInhwNo7g0qqbomckVEREQ3xwBE7WbSgAAMV3dDXaMR76XmiV0OERHRTTEAUbuRSCR49a7myRG/PXIJxy5WilsQERHRTTAAUbsa1N0L0wcHAwDe+v4kOMaeiIhsEQMQtbuXJvWFk6MUBwuuIPXEzdd0IyIiEgsDELW7QE9nPDW2FwAg5YdTqG8yiFwRERGROQYg6hBPjwuF0kOBwoqr+M/P+WKXQ0REZIYBiDqEi9wB83/5LH7FzrPQVtWJXBEREdFvGICow0yLCsaQHl642mDAoh+4WjwREdkOBiDqMBKJBG/cMwASCbAluxiHCirELomIiAgAAxB1sIHdPTFzWPPiqAu35nC1eCIisgkMQNThXpzYF+5ODsgp1mPTwSKxyyEiImIAoo7n46ZA0h19AADvbT+FqquNIldERET2jgGIrOIvI3qij9INV6424p8/nRa7HCIisnMMQGQVjjIpFt7dHwCw4cAF5GmrRa6IiIjsGQMQWc2oMF9M6h8Ag1HAG/+Xw3XCiIhINAxAZFWvTOkHhYMU+89d5jphREQkGgYgsipVNxf8dVzzOmFv/y8X1xq4ThgREVkfAxBZ3ZxxvRDk6YRLldewKu2s2OUQEZEdYgAiq3OWy/DaXREAgNW7z+N8WY3IFRERkb1hACJRTBoQgHF9/NBgMGLhVg6IJiIi62IAIlE0rxPWH3IHKfaeKce24xwQTURE1sMARKJR+7pi7vjmAdFvfp+DmvomkSsiIiJ7wQBEonp6XC/09HGBTl+PpTs4QzQREVkHAxCJyslRhtfvaZ4h+pP9BTil1YtcERER2QMGIBLdbX39MXlA8wzRr24+AaORA6KJiKhjMQCRTXjtrgi4yGU4dOEK/nv4otjlEBFRF8cARDYhyMsZz0/oDQBY9MMpVF5tELkiIiLqyhiAyGY8NjoEvf3dcLm2AYtT88Quh4iIujAGILIZjjIp3p42AADwZWYhDhZUiFwRERF1VQxAZFNiQn0wc5gKAJD87XHUN3GxVCIian82EYBWrlwJtVoNJycnxMTEIDMz86Zt16xZgzFjxsDb2xve3t6Ii4u7rv2jjz4KiURitk2aNKmjb4PaSfLkfvB1U+BsaQ1Wp50XuxwiIuqCRA9AmzZtQlJSEhYuXIjDhw8jMjIS8fHxKC0tvWH7tLQ0zJo1C7t27UJ6ejpUKhUmTpyIS5cumbWbNGkSSkpKTNuXX35pjduhduDp4oiFdzcvlrpy11mcLeViqURE1L4kgsirUMbExGDYsGFYsWIFAMBoNEKlUuG5557D/Pnz//R8g8EAb29vrFixAgkJCQCae4AqKyuxZcuWNtWk1+vh6emJqqoqeHh4tOkaZBlBEPDYuoPYlVeG4epu2PjUCEilErHLIiIiG9aa39+i9gA1NDQgKysLcXFxpn1SqRRxcXFIT09v0TWuXr2KxsZGdOvWzWx/Wloa/P390bdvX8yZMweXL1++6TXq6+uh1+vNNhKXRCLBW9MGwEUuQ2ZBBTYdKhK7JCIi6kJEDUDl5eUwGAxQKpVm+5VKJbTalq0O/re//Q1BQUFmIWrSpEn49NNPodFosHjxYuzevRuTJ0+GwXDjAbUpKSnw9PQ0bSqVqu03Re2mu7cLXpjYFwDwzrZclOrrRK6IiIi6CtHHAFli0aJF2LhxIzZv3gwnJyfT/pkzZ+Kee+7BwIEDMW3aNHz//fc4ePAg0tLSbnid5ORkVFVVmbaiIvY22IpHR6oxqLsnquua8Mb3J8Uuh4iIughRA5Cvry9kMhl0Op3Zfp1Oh4CAgFue+/7772PRokX48ccfMWjQoFu2DQ0Nha+vL86ePXvD4wqFAh4eHmYb2QaZVIJ37h0ImVSC/x0rgSZX9+cnERER/QlRA5BcLkd0dDQ0Go1pn9FohEajQWxs7E3Pe/fdd/HWW28hNTUVQ4cO/dOfc/HiRVy+fBmBgYHtUjdZ14BgTzwxOgQA8NqWE6iuaxS5IiIi6uxEfwWWlJSENWvWYP369cjNzcWcOXNQW1uLxMREAEBCQgKSk5NN7RcvXozXXnsNa9euhVqthlarhVarRU1N86fSNTU1eOmll3DgwAEUFBRAo9Fg6tSpCAsLQ3x8vCj3SJabF9cHPbq5oLiqDik/nBK7HCIi6uRED0AzZszA+++/jwULFiAqKgrZ2dlITU01DYwuLCxESUmJqf2qVavQ0NCA+++/H4GBgabt/fffBwDIZDIcO3YM99xzD/r06YPHH38c0dHR2Lt3LxQKhSj3SJZzlsuw+L7mV51fZBRi/9lykSsiIqLOTPR5gGwR5wGyXa9uOY7PDhSiu7czts8bC1eFg9glERGRjeg08wARtdb8yf0Q7OWMi1eu4d1UvgojIqK2YQCiTsVN4WB6FbY+/QIOnL/5BJdEREQ3wwBEnc7o3r6YNbx5ssq//fcYrjVwxXgiImodBiDqlJLv7IdATydcuHwV723PE7scIiLqZBiAqFPycHJEyvSBAIBP9ufjUEGFyBUREVFnwgBEndb4vv64P7o7BAF4+ZtjqGvkqzAiImqZNgWgoqIiXLx40fTnzMxMzJs3Dx9//HG7FUbUEq9NiYDSQ4Hz5bVYzK/CiIiohdoUgB566CHs2rULAKDVanHHHXcgMzMTr7zyCt588812LZDoVjxdHLHol6/CPtlXgH2cIJGIiFqgTQHoxIkTGD58OADgq6++woABA7B//358/vnnWLduXXvWR/Snbuvrj9kxPQAAL359FFXXuFYYERHdWpsCUGNjo2lZiZ9++gn33HMPACA8PNxs2Qoia3llSj+ofVxQUlWH17fmiF0OERHZuDYFoP79+2P16tXYu3cvduzYgUmTJgEAiouL4ePj064FErWEi9wBS2ZEQSoBNh+5hP8dYxAnIqKba1MAWrx4MT766COMHz8es2bNQmRkJABg69atpldjRNY2pIc35o4PAwC8suU4SvV1IldERES2qs2LoRoMBuj1enh7e5v2FRQUwMXFBf7+/u1WoBi4GGrn1dBkxL3/2oecYj3G9fHDusRhkEgkYpdFRERW0OGLoV67dg319fWm8HPhwgUsXboUeXl5nT78UOcmd5Bi6YwoyB2k2H26DJ9lFIpdEhER2aA2BaCpU6fi008/BQBUVlYiJiYGH3zwAaZNm4ZVq1a1a4FErdVb6Y6X4/sCAN75Xy7Ol9WIXBEREdmaNgWgw4cPY8yYMQCAb775BkqlEhcuXMCnn36KZcuWtWuBRG3x2KgQxIb64FqjAfM2ZaOhySh2SUREZEPaFICuXr0Kd3d3AMCPP/6I6dOnQyqVYsSIEbhw4UK7FkjUFlKpBB88GAlPZ0ccu1iFD3ZwwVQiIvpNmwJQWFgYtmzZgqKiImzfvh0TJ04EAJSWlnLQMNmMIC9nLL6vecHUj3afx94zZSJXREREtqJNAWjBggV48cUXoVarMXz4cMTGxgJo7g0aPHhwuxZIZIlJAwLx0C+zRCd9dRTlNfUiV0RERLagzZ/Ba7ValJSUIDIyElJpc47KzMyEh4cHwsPD27VIa+Nn8F3LtQYD7lnxM86U1uC2vn5Y+yg/jSci6oo6/DN4AAgICMDgwYNRXFxsWhl++PDhnT78UNfjLJdh+UODIXeQYldeGT7ZVyB2SUREJLI2BSCj0Yg333wTnp6e6NmzJ3r27AkvLy+89dZbMBr5tQ3ZnvAAD7w6pR8AYNEPp3DiUpXIFRERkZjaFIBeeeUVrFixAosWLcKRI0dw5MgRvPPOO1i+fDlee+219q6RqF08PKIn4vop0WAw4v9tPILa+iaxSyIiIpG0aQxQUFAQVq9ebVoF/lffffcd5s6di0uXLrVbgWLgGKCu60ptAyZ/uBdafR2mRgVh6YwojgciIuoiOnwMUEVFxQ3H+oSHh6OioqItlySyCm9XOVY8NBgyqQTfZRfji0wulUFEZI/aFIAiIyOxYsWK6/avWLECgwYNsrgooo40VN0Nf5vUvFTGG1tPcjwQEZEdcmjLSe+++y6mTJmCn376yTQHUHp6OoqKirBt27Z2LZCoIzw5JhSZ+VfwU64Ocz8/jP97bjQ8nR3FLouIiKykTT1A48aNw+nTp3HvvfeisrISlZWVmD59OnJycrBhw4b2rpGo3UkkEnzwQCS6ezujsOIqXv7mKNo4JRYREXVCbZ4I8UaOHj2KIUOGwGAwtNclRcFB0Pbj2MVK3L8qHQ0GI16d0g9PjAkVuyQiImojq0yESNQVDOruhVfv+m1+oKwLHMRPRGQPGIDI7j08oifuGhSIJqOApz87jFJ9ndglERFRB2MAIrsnkUiw+L5B6KN0Q1l1PeZ8fhgNTZzRnIioK2vVV2DTp0+/5fHKykpLaiESjavCAR8/PBR3r/gZWReu4M3vc/D2tIFil0VERB2kVT1Anp6et9x69uyJhISEVhexcuVKqNVqODk5ISYmBpmZmTdtu2bNGowZMwbe3t7w9vZGXFzcde0FQcCCBQsQGBgIZ2dnxMXF4cyZM62ui+yL2tcVH86MgkQCfHagEJsOcpJEIqKuql2/AmuLTZs2ISEhAatXr0ZMTAyWLl2Kr7/+Gnl5efD397+u/ezZszFq1CiMHDkSTk5OWLx4MTZv3oycnBwEBwcDABYvXoyUlBSsX78eISEheO2113D8+HGcPHkSTk5Of1oTvwKzb8s1Z/DBjtOQy6T46ulYRKm8xC6JiIhaoDW/v0UPQDExMRg2bJhpZmmj0QiVSoXnnnsO8+fP/9PzDQYDvL29sWLFCiQkJEAQBAQFBeGFF17Aiy++CACoqqqCUqnEunXrMHPmzOuuUV9fj/r6etOf9Xo9VCoVA5CdMhoF/PWzLOw4qUOAhxP+77nR8HNXiF0WERH9iU7zGXxDQwOysrIQFxdn2ieVShEXF4f09PQWXePq1atobGxEt27dAAD5+fnQarVm1/T09ERMTMxNr5mSkmL2Kk+lUllwV9TZSaUSLHkwEqF+rtDq6zD38yzUN3Xuua2IiMicqAGovLwcBoMBSqXSbL9SqYRWq23RNf72t78hKCjIFHh+Pa8110xOTkZVVZVpKyoqau2tUBfj7uSIjx8eCneFAw4WXMGrm09wpmgioi6kU38Gv2jRImzcuBGbN29u0diem1EoFPDw8DDbiML83bD8ocGQSoCvsy5izd7zYpdERETtRNQA5OvrC5lMBp1OZ7Zfp9MhICDglue+//77WLRoEX788UezFeh/Pa8t1yT6o/F9/fHaXREAgJQfTuGnk7o/OYOIiDoDUQOQXC5HdHQ0NBqNaZ/RaIRGozGtMn8j7777Lt566y2kpqZi6NChZsdCQkIQEBBgdk29Xo+MjIxbXpPoZh4dqcbsmB4QBOD5jUeQW6IXuyQiIrKQ6K/AkpKSsGbNGqxfvx65ubmYM2cOamtrkZiYCABISEhAcnKyqf3ixYvx2muvYe3atVCr1dBqtdBqtaipqQHQPKvvvHnz8Pbbb2Pr1q04fvw4EhISEBQUhGnTpolxi9TJSSQSvH5Pf4zs5YPaBgOeWH8IZdX1f34iERHZrFbNBN0RZsyYgbKyMixYsABarRZRUVFITU01DWIuLCyEVPpbTlu1ahUaGhpw//33m11n4cKFeP311wEAL7/8Mmpra/HUU0+hsrISo0ePRmpqqkXjhMi+Ocqk+NfsIbj3X/uRX16Lv244hC+eHAEnR5nYpRERURuIPg+QLeJEiHQz58tqMG3lPujrmnDnwACsmDUEUqlE7LKIiAidaB4gos4m1M8NHz08FHKZFNuOa/GPbblil0RERG3AAETUSrG9fPDeA81fHv7n53z8m5/HExF1OgxARG0wNSoY8yeHAwD+sS0X246XiFwRERG1BgMQURv9dWwoEmJ7QhCAeZuycbCgQuySiIiohRiAiNpIIpFg4d39cUeEEg1NRjyx/hDOllaLXRYREbUAAxCRBWRSCZbNHIwolReqrjUi4T+ZuFR5TeyyiIjoTzAAEVnIWS7Dfx4ZilA/VxRX1eHhf2egvIYTJRIR2TIGIKJ24OOmwGePxyDYyxnny2vxyNpM6OsaxS6LiIhuggGIqJ0EeTljw+PD4eMqR06xHk+sO4S6RoPYZRER0Q0wABG1o1A/N6x/bDjcFQ7ILKjA3M8Po9FgFLssIiL6AwYgonY2INgTaxOHwclRip2nSvHCV0dhMHLFGSIiW8IARNQBhqm7YdXsaDhIJdh6tBgvf3OMIYiIyIYwABF1kNvC/bFs1mDIpBL89/BFJH97DEaGICIim8AARNSB7hwYiKUzoiCVAF8duohXthxnCCIisgEMQEQd7O7IIPzzlxD0ZWYRFmw9AUFgCCIiEhMDEJEVTI0KxvsPREIiAT47UIjXt+YwBBERiYgBiMhKpg/pjnfvGwSJBFiffgELvsvh6zAiIpEwABFZ0QNDVVg0fSAkEmDDgQt4+b/8OoyISAwMQERWNmNYDyx5MBJSCfBN1kU8v/EIJ0skIrIyBiAiEdw7uDtWPjQEjjIJvj9WgjmfHeayGUREVsQARCSSyQMD8fHDQyF3kOKnXB2e/PQQrjUwBBERWQMDEJGIbgv3x7pHh8FFLsPeM+VIWJuBqqtcRZ6IqKMxABGJbGSYLzY8PhzuTg44WHAFD36UjpKqa2KXRUTUpTEAEdmA6J7d8PXTsVB6KJCnq8Z9/9qPs6XVYpdFRNRlMQAR2YjwAA/8d85IhPq5oriqDvetSkfWhQqxyyIi6pIYgIhsSHdvF/z36ZEY3MMLVdcaMfvfGfjppE7ssoiIuhwGICIb4+0qx+dPxOD2cH/UNRrx1IZD+DS9QOyyiIi6FAYgIhvkInfARw9H48Gh3WEUgAXf5eD1rTlo4oSJRETtggGIyEY5yqRYfN8gvDypLwBg3f4CPPHpIVTX8TN5IiJLMQAR2TCJRIK548OwavYQODlKkZZXhvtXpePilatil0ZE1KkxABF1ApMHBmLTU7Hwc2/+TH7ayv04XHhF7LKIiDotBiCiTiJS5YXvnhmFfoEeKK+px8yPDmBjZqHYZRERdUqiB6CVK1dCrVbDyckJMTExyMzMvGnbnJwc3HfffVCr1ZBIJFi6dOl1bV5//XVIJBKzLTw8vAPvgMh6gryc8fXTsYjvr0SDwYj53x5H8rfHUd/ENcSIiFpD1AC0adMmJCUlYeHChTh8+DAiIyMRHx+P0tLSG7a/evUqQkNDsWjRIgQEBNz0uv3790dJSYlp+/nnnzvqFoiszk3hgFWzo/FSfF9IJMCXmYWY+fEB6PR1YpdGRNRpiBqAlixZgieffBKJiYmIiIjA6tWr4eLigrVr196w/bBhw/Dee+9h5syZUCgUN72ug4MDAgICTJuvr29H3QKRKKRSCZ65LQxrHx0GDycHHCmsxF3Lf8ahAs4cTUTUEqIFoIaGBmRlZSEuLu63YqRSxMXFIT093aJrnzlzBkFBQQgNDcXs2bNRWHjrcRL19fXQ6/VmG1FncFtff2x9djT6Kt1RVl2PmR8fwJo95yEIgtilERHZNNECUHl5OQwGA5RKpdl+pVIJrVbb5uvGxMRg3bp1SE1NxapVq5Cfn48xY8aguvrmC0umpKTA09PTtKlUqjb/fCJrU/u64tu5I3HXoEA0GQX8Y1sunlh/CFdqG8QujYjIZok+CLq9TZ48GQ888AAGDRqE+Ph4bNu2DZWVlfjqq69uek5ycjKqqqpMW1FRkRUrJrKcq8IBy2cNxtvTBkDuIIXmVCmmLNvLxVSJiG5CtADk6+sLmUwGnc58oUedTnfLAc6t5eXlhT59+uDs2bM3baNQKODh4WG2EXU2EokEfxnRE5vnjkSIb/OK8g9+dACrd5+D0chXYkREvydaAJLL5YiOjoZGozHtMxqN0Gg0iI2NbbefU1NTg3PnziEwMLDdrklky/oHeeL/nhuNeyKDYDAKWPTDKTzySSa/EiMi+h1RX4ElJSVhzZo1WL9+PXJzczFnzhzU1tYiMTERAJCQkIDk5GRT+4aGBmRnZyM7OxsNDQ24dOkSsrOzzXp3XnzxRezevRsFBQXYv38/7r33XshkMsyaNcvq90ckFjeFAz6cGYV37h0IJ0cp9p4pR/zSPdh2vETs0oiIbIKDmD98xowZKCsrw4IFC6DVahEVFYXU1FTTwOjCwkJIpb9ltOLiYgwePNj05/fffx/vv/8+xo0bh7S0NADAxYsXMWvWLFy+fBl+fn4YPXo0Dhw4AD8/P6veG5HYJBIJHorpgeEh3TBv0xGcuKTH3M8P474h3fH6PRFwd3IUu0QiItFIBH4vex29Xg9PT09UVVVxPBB1CQ1NRnyoOY1VaedgFIDu3s7454woDFN3E7s0IqJ205rf313uKzAiup7cQYqX4sOx6a+x6O7tjItXruHBj9Lx+tYcXG1oErs8IiKrYwAisiPD1N3ww/Nj8EB0dwgCsG5/AeKX7sH+s+Vil0ZEZFUMQER2xt3JEe89EIn1jw1HsJcziiqu4aF/ZyD52+PQ1zWKXR4RkVUwABHZqXF9/LD9/xuLh0f0BNC8qOrEJXuw85TuT84kIur8GICI7JibwgFvTRuAjU+NQE8fF2j1dXhs3SE88/lhlFRdE7s8IqIOwwBERBgR6oPU58fiyTEhkEkl+N/xEsR9sBv/3nsejQaj2OUREbU7BiAiAgA4y2V4ZUoE/u/Z0RjSwwu1DQa8/b9c3L38Zxws4JpiRNS1MAARkZmIIA988/RIvHvfIHi7OOKUthoPrE7Hi18fRVl1vdjlERG1CwYgIrqOVCrBg8NU2PnCeMwargIAfJN1Ebe9n4ZVaedQ12gQuUIiIstwJugb4EzQROayLlzB61tzcPxSFQBA1c0Z8yf1w50DAyCRSESujoioWWt+fzMA3QADENH1jEYB3x65hPe2n4JO3/wqbJjaG6/dFYFB3b3ELY6ICAxAFmMAIrq5qw1NWL37PD7ecw51jc1fiN07OBj/X1wf9PBxEbk6IrJnDEAWYgAi+nMlVdfwbmoeNh+5BABwlEnw0PAeePb23vBzV4hcHRHZIwYgCzEAEbXc8YtVeHf7Kew907yemLOjDI+PDsGTY0Ph6ewocnVEZE8YgCzEAETUevvPlmPx9jwcLaoEAHg6O2LO+F5IiO0JF7mDuMURkV1gALIQAxBR2wiCgB9P6vD+9jycKa0BAHRzleOJMSFIiFXDTcEgREQdhwHIQgxARJYxGAVsPnIJy3eewYXLVwEAXi6OeGJ0CBJGquHhxFdjRNT+GIAsxABE1D6aDEZsPVqMFTvP4nx5LQDAw8kBj48OxaOj1BwjRETtigHIQgxARO3LYBTw/bFiLNOcwbmy5iDkrnDAX2J7InGkGv4eTiJXSERdAQOQhRiAiDqGwShg2/ESLN95Bqd1zWOE5DIp7h0cjCfHhiLM303kComoM2MAshADEFHHMhoFaE6V4qPd53DowhXT/jsilPjr2FAMVXcTsToi6qwYgCzEAERkPVkXKvDR7vP48aTOtC+6pzeeGB2COyKUcJBxzWYiahkGIAsxABFZ39nSGvx773l8e/gSGgzNS2wEeTrh4Vg1Zg5TwdtVLnKFRGTrGIAsxABEJJ5SfR0+Tb+ALzILUVHbAABQODSPE3pkpBr9AvnfJBHdGAOQhRiAiMRX12jA/x0txrr9Bcgp1pv2jwjthkdHhiCunz9fjxGRGQYgCzEAEdkOQRBw6MIVrNtXgNQcLQzG5v9lBXo6YcYwFWYMUyHQ01nkKonIFjAAWYgBiMg2FVdew2cHLuDLzEJcudoIAJBKgNvDlZgd0wNj+/hBJpWIXCURiYUByEIMQES2ra7RgO05WnyeUYjM/ArT/mAvZ1OvkJKTKxLZHQYgCzEAEXUeZ0ur8UVGEf57+CKqrjX3CsmkEkwI98fM4SqM7e3HsUJEdoIByEIMQESdT12jAT+cKMEXGYU4WPDb5Ir+7grcOyQYD0R3R5i/u4gVElFHYwCyEAMQUed2WleNLzML8V12selTegCIUnnh/ujuuDsyiAuxEnVBDEAWYgAi6hoamozYeaoU32RdxK68UtMXZAoHKeL7B+D+6O4YFebLgdNEXQQDkIUYgIi6nrLqemw5cglfZxWZFmIFmj+nnzY4GNOigtE3gK/IiDqz1vz+Fn1k4MqVK6FWq+Hk5ISYmBhkZmbetG1OTg7uu+8+qNVqSCQSLF261OJrEpF98HNX4Mmxodg+byy2PjsKCbE94ensiJKqOqxKO4f4pXswaekerN59DsWV18Qul4g6mKgBaNOmTUhKSsLChQtx+PBhREZGIj4+HqWlpTdsf/XqVYSGhmLRokUICAhol2sSkX2RSCQY1N0Lb04dgIy/T8DKh4bgjgglHGUSnNJWY9EPpzBq8U7M/DgdGzMLTV+WEVHXIuorsJiYGAwbNgwrVqwAABiNRqhUKjz33HOYP3/+Lc9Vq9WYN28e5s2b127X/BVfgRHZn8qrDdh2XIst2ZfM5haSy6S4LdwP9w4Oxvi+/nBylIlYJRHdSmt+fztYqabrNDQ0ICsrC8nJyaZ9UqkUcXFxSE9Pt+o16+vrUV9fb/qzXq+/aVsi6pq8XOR4KKYHHorpgYtXrmLr0WJ8d6QYebpqbM/RYXuODu5ODrhzQCDujgzCiNBunF+IqBMTLQCVl5fDYDBAqVSa7VcqlTh16pRVr5mSkoI33nijTT+TiLqe7t4umDs+DHPHhyG3RI8t2ZewNbsYJVV12HSoCJsOFcHHVY5JAwJw16AgDA/pxi/JiDoZ0QKQLUlOTkZSUpLpz3q9HiqVSsSKiMhW9Av0QL9AD/wtPhwZ+RXYerQYqSdKcLm2AZ9nFOLzjEL4uStw54AA3BUZhOge3pAyDBHZPNECkK+vL2QyGXQ6ndl+nU530wHOHXVNhUIBhULRpp9JRPZBKpUgtpcPYnv54M2p/bH/3GX871gxUk9oUVZdj/XpF7A+/QICPJxw58BA3BUZiMEqL0gkDENEtki0F9hyuRzR0dHQaDSmfUajERqNBrGxsTZzTSKiP3KUSTGujx/evT8Sh169A2sfHYrpQ4LhrnCAVl+HtfvyMf1f+zF68S68sy0Xxy5WglOuEdkWUV+BJSUl4ZFHHsHQoUMxfPhwLF26FLW1tUhMTAQAJCQkIDg4GCkpKQCaBzmfPHnS9M+XLl1CdnY23NzcEBYW1qJrEhG1J7mDFLeHK3F7uBJ1jQbsOV2G74+V4KdcHS5VXsPHe87j4z3n0aObC+4cGIjJAwIwqLsne4aIRCb6TNArVqzAe++9B61Wi6ioKCxbtgwxMTEAgPHjx0OtVmPdunUAgIKCAoSEhFx3jXHjxiEtLa1F12wJfgZPRJaqazRg16lSfH+sBJpTOtQ1Gk3Hgr2cMWlAACYPCMAQjhkiajdcCsNCDEBE1J5q65uw81QpUk9osfNUKa41GkzH/N0VmDQgAJMGBGC4mp/WE1mCAchCDEBE1FGuNRiw+3QZUk+UQJNbiur6JtOxbq5yxPdXYtKAQIzs5QNHhiGiVmEAshADEBFZQ32TAfvOluOH41rsyNWh8upvy254ODkgLkKJOwcEYnRvX85ATdQCDEAWYgAiImtrNBiRcb4C206U4MccLcprGkzHXOUy3N5PiTsHBGBcXz+4yDmFG9GNMABZiAGIiMRkMAo4VFCBH05okXpCC62+znTMyVGK8X38MWlAAG4L94ens6OIlRLZFgYgCzEAEZGtMBoFZF+sROoJLX44UYKiimumYw6/TM4Y3z8AEyOU8PdwErFSIvExAFmIAYiIbJEgCMgp1uOHEyX4MUeHM6U1ZscH9/BCfP8AxPcPQIivq0hVEomHAchCDEBE1BmcL6v5ZaV6LbKLKs2O9fZ3M4WhAcEenHiR7AIDkIUYgIios9Hp6/DjSR1+zNEi/dxlNBl/+197sJcz7ohQYmJ/Jecaoi6NAchCDEBE1JlVXW3ErrxSbM/RIi2vzGziRW8XR0zop0R8/wCM4ef11MUwAFmIAYiIuoq6RgP2ninHjzla/JSrw5XfzTXk7CjDuD5+iB+gxO19lfB04Rdl1LkxAFmIAYiIuqImgxEHC65ge44WO042L9b6KwepBCNCfRDfX4mJ/QOg5Bdl1AkxAFmIAYiIurpfvyjbnqPF9hwtTuvMvyiLUjV/UTaxvxK9/NxEqpKodRiALMQARET2Jr+8Fj/+EoYOF1aaHQv1c8Ud/ZS4I0KJwT28IePq9WSjGIAsxABERPasVF+HHbk6bM/RIf1cORoNv/2a8HGV4/Zwf9wRocSY3n5wlnMQNdkOBiALMQARETWrrmvE7tNl2HFSh12nSqGv+231eoWDFGN6++KOCCVuD1fCz10hYqVEDEAWYwAiIrpeo8GIg/kV+PGk7rpB1BIJMFjlhTsiAnBHhBJh/hw3RNbHAGQhBiAiolsTBAGntNXY8UsYOn6pyux4qK8r4iKaxw0N4bghshIGIAsxABERtU5J1TX8lFuKHSevHzfUzWzckC9c5A4iVkpdGQOQhRiAiIjarrquEXtOl2PHSS123mDc0Oiw5nFDE/px3BC1LwYgCzEAERG1j0aDEQcLKkyvyi5eMR83FKXyal6nLKJ5viEu2kqWYACyEAMQEVH7EwQBebpq7MjRYUeuDscumo8bUvu4mHqGhvb05qKt1GoMQBZiACIi6njaqjr8lKv7ZdzQZTQYjKZjHk4OGN/XHxP6+WN8H3+uU0YtwgBkIQYgIiLrqqlvwp5f5xvKK0Xl7xZtlUkliO7pjQnh/pjQT4lefq58VUY3xABkIQYgIiLxGIwCjhRewU+5pdh5SnfdOmU9fVxwe7g/4vopMUzdDXIHviqjZgxAFmIAIiKyHUUVV7HzVCl+ytUh43yF2asyN4UDxvbxxe3hStzW1w8+bvyqzJ4xAFmIAYiIyDbV1Dfh5zPl0OQ2vyorr2kwHft1NuoJ/ZSY0M8ffZXufFVmZxiALMQARERk+4xGAccuVWFnrg4/5ZbiZIne7HiwlzNuD28eSD0i1AdOjly4tatjALIQAxARUedTUnUNO0+VQpNbin1ny1Hf9NurMmdHGUb39sWEcH/cHu4Pfw8nESuljsIAZCEGICKizu1agwH7z5VDc6oUO3NLodXXmR3vH+SB8X39ML6vPwarvDjnUBfBAGQhBiAioq5DEATkFOt/6R3S4egfJmD0cHLAmD5+uK2vP8b18ePyHJ0YA5CFGICIiLqu8pp67Dldhl15ZdhzugxV1xrNjg8M9vyld8gPUSquZN+ZMABZiAGIiMg+NBmMOHqxEml5ZUjLK8PxS+a9Q14ujhjT2w+39fXD2D5+8OVn9jaNAchCDEBERPaptLoOe06XY1deKfaeLjNbyV4iAQYFe2JcX3/c1tcPg7p7sXfIxrTm97dNjPpauXIl1Go1nJycEBMTg8zMzFu2//rrrxEeHg4nJycMHDgQ27ZtMzv+6KOPQiKRmG2TJk3qyFsgIqIuwN/dCfdHd8fKh4bg8Gt34OunY/HMbb0QEegBQQCOXqzCMs0Z3Puv/Rj69g48v/EINh+5iLLqerFLp1YSvQdo06ZNSEhIwOrVqxETE4OlS5fi66+/Rl5eHvz9/a9rv3//fowdOxYpKSm466678MUXX2Dx4sU4fPgwBgwYAKA5AOl0OnzyySem8xQKBby9vVtUE3uAiIjoj3T6OuzOK0Pa6VLsPVOO6t/1DgFARKAHxvTxxdjefhiq9obCgfMOWVunegUWExODYcOGYcWKFQAAo9EIlUqF5557DvPnz7+u/YwZM1BbW4vvv//etG/EiBGIiorC6tWrATQHoMrKSmzZsqVFNdTX16O+/rf0rtfroVKpGICIiOiGGg1GHL5wBWmnmwdS5xSbT8Lo5CjFiFAfjOnth3F9fNHLz42zUltBawKQg5VquqGGhgZkZWUhOTnZtE8qlSIuLg7p6ek3PCc9PR1JSUlm++Lj468LO2lpafD394e3tzduv/12vP322/Dx8bnhNVNSUvDGG29YdjNERGQ3HGVSxIT6ICbUB3+bFI7ymnr8fKYce86UYe+ZcpRV15sGVr8FIMjTCWN6+2FMH1+M6uULb1e52Ldg90QNQOXl5TAYDFAqlWb7lUolTp06dcNztFrtDdtrtVrTnydNmoTp06cjJCQE586dw9///ndMnjwZ6enpkMmu75JMTk42C1W/9gARERG1hK+bAtMGB2Pa4GAIgoBT2mrs/SUMZeRXoLiqDpsOFWHToaLmwdTdvTC2ty/G9PbD4B5ecOREjFYnagDqKDNnzjT988CBAzFo0CD06tULaWlpmDBhwnXtFQoFFAp+2khERJaTSCToF+iBfoEeeGpsL9Q1GpCRX4G9p5sDUZ6uGkeLKnG0qBLLd56Fm8IBsb18MKa3L0b28kUvP1e+LrMCUQOQr68vZDIZdDqd2X6dToeAgIAbnhMQENCq9gAQGhoKX19fnD179oYBiIiIqKM4Ocowro8fxvXxAwBoq+pMvUM/ny1HRW0DdpzUYcfJ5t9tSg8FRvXyxcgwX4zs5YMgL2cxy++yRA1Acrkc0dHR0Gg0mDZtGoDmQdAajQbPPvvsDc+JjY2FRqPBvHnzTPt27NiB2NjYm/6cixcv4vLlywgMDGzP8omIiFotwNMJDwxV4YGhKhiNzct07DlThn1ny3HowhXo9PX49sglfHvkEgAgxNcVI3v5YFSYL2JDfTh+qJ2I/hXYpk2b8Mgjj+Cjjz7C8OHDsXTpUnz11Vc4deoUlEolEhISEBwcjJSUFADNn8GPGzcOixYtwpQpU7Bx40a88847ps/ga2pq8MYbb+C+++5DQEAAzp07h5dffhnV1dU4fvx4i1518TN4IiISQ12jAVkXrmDf2XLsP3cZxy5Wwvi739ISCdAvwAOjwnwwMswXw9Xd4KrokqNZ2qTTfAUGNH/WXlZWhgULFkCr1SIqKgqpqammgc6FhYWQSn8bHDZy5Eh88cUXePXVV/H3v/8dvXv3xpYtW0xzAMlkMhw7dgzr169HZWUlgoKCMHHiRLz11lsc50NERDbNyVGGUWG+GBXmCwDQ1zUi43zFL4GoHKd1NThZosfJEj3W7M2Hg1SCwT28ENvLF6N6+WBwD2/IHTiguiVE7wGyRewBIiIiW1RaXYf0c5ex/+xl7DtXjotXrpkdd3KUIrqnN2JCfBAT0g1RPbzsakLGTjURoi1iACIios6g8PJV7DvX/Los/Vw5ymsazI7LHaQY0sOrORCFdsOQHt5wcuy6gYgByEIMQERE1NkIgoAzpTXIOH8ZB/IrkHG+AuU15muUyWVSRKo8MSLUBzEhPhjS0wsuctFHw7QbBiALMQAREVFnJwgCzpfX4sD5y8g4X4GM/MvQ6c0DkYNUgkHdPZtntQ7phqHqbnDrxIOqGYAsxABERERdjSAIuHD5KjLyfw1EFbhUaT6GSCaVICLQA9E9vTFU7Y2hPbshwNNJpIpbjwHIQgxARERkD4oqrjb3EOU39xAVVVy7rk13b2cM7emNaHU3DFN7o4+/O6RS25ypmgHIQgxARERkj0qqruFQwRVkXbiCgwUVyC3Rm81DBADuTg4Y0sMbw9TeiO7ZDVEqLzjLbWNgNQOQhRiAiIiIgJr6JmQXVuJgQQWyLlzB4cIruNpgMGvjIJWgf7Bncy9RT28M7uGFQE9xlu9gALIQAxAREdH1mgxGnNJW41BBBQ5euIKsgivQ6uuuaxfg4YTBPbx+2bwxMNjTKp/fMwBZiAGIiIjozwmCgEuVza/NDl2owJHCSpzSVsPwh/dmDlIJ+gV6/BaKVN7o6ePS7qveMwBZiAGIiIioba42NOH4xSocKarEkcIrOFxYibLq+uvazRquQsr0Qe36szvVWmBERETUdbjIHZrnFQr1AdDcS1RcVYcjhVdwpLA5FJ24pEd4gLgdDAxARERE1GEkEgmCvZwR7OWMuwYFAQDqmwzXvSazNgYgIiIisipbWKBVKnYBRERERNbGAERERER2hwGIiIiI7A4DEBEREdkdBiAiIiKyOwxAREREZHcYgIiIiMjuMAARERGR3WEAIiIiIrvDAERERER2hwGIiIiI7A4DEBEREdkdBiAiIiKyO1wN/gYEQQAA6PV6kSshIiKilvr19/avv8dvhQHoBqqrqwEAKpVK5EqIiIiotaqrq+Hp6XnLNhKhJTHJzhiNRhQXF8Pd3R0SiaRdr63X66FSqVBUVAQPD492vTb9hs/ZOvicrYPP2Tr4nK2jI5+zIAiorq5GUFAQpNJbj/JhD9ANSKVSdO/evUN/hoeHB/8DswI+Z+vgc7YOPmfr4HO2jo56zn/W8/MrDoImIiIiu8MARERERHaHAcjKFAoFFi5cCIVCIXYpXRqfs3XwOVsHn7N18Dlbh608Zw6CJiIiIrvDHiAiIiKyOwxAREREZHcYgIiIiMjuMAARERGR3WEAsqKVK1dCrVbDyckJMTExyMzMFLukTmXPnj24++67ERQUBIlEgi1btpgdFwQBCxYsQGBgIJydnREXF4czZ86YtamoqMDs2bPh4eEBLy8vPP7446ipqbHiXdi+lJQUDBs2DO7u7vD398e0adOQl5dn1qaurg7PPPMMfHx84Obmhvvuuw86nc6sTWFhIaZMmQIXFxf4+/vjpZdeQlNTkzVvxaatWrUKgwYNMk0GFxsbix9++MF0nM+4YyxatAgSiQTz5s0z7eOzttzrr78OiURitoWHh5uO2+QzFsgqNm7cKMjlcmHt2rVCTk6O8OSTTwpeXl6CTqcTu7ROY9u2bcIrr7wifPvttwIAYfPmzWbHFy1aJHh6egpbtmwRjh49Ktxzzz1CSEiIcO3aNVObSZMmCZGRkcKBAweEvXv3CmFhYcKsWbOsfCe2LT4+Xvjkk0+EEydOCNnZ2cKdd94p9OjRQ6ipqTG1efrppwWVSiVoNBrh0KFDwogRI4SRI0eajjc1NQkDBgwQ4uLihCNHjgjbtm0TfH19heTkZDFuySZt3bpV+N///iecPn1ayMvLE/7+978Ljo6OwokTJwRB4DPuCJmZmYJarRYGDRokPP/886b9fNaWW7hwodC/f3+hpKTEtJWVlZmO2+IzZgCykuHDhwvPPPOM6c8Gg0EICgoSUlJSRKyq8/pjADIajUJAQIDw3nvvmfZVVlYKCoVC+PLLLwVBEISTJ08KAISDBw+a2vzwww+CRCIRLl26ZLXaO5vS0lIBgLB7925BEJqfq6Ojo/D111+b2uTm5goAhPT0dEEQmsOqVCoVtFqtqc2qVasEDw8Pob6+3ro30Il4e3sL//73v/mMO0B1dbXQu3dvYceOHcK4ceNMAYjPun0sXLhQiIyMvOExW33GfAVmBQ0NDcjKykJcXJxpn1QqRVxcHNLT00WsrOvIz8+HVqs1e8aenp6IiYkxPeP09HR4eXlh6NChpjZxcXGQSqXIyMiwes2dRVVVFQCgW7duAICsrCw0NjaaPevw8HD06NHD7FkPHDgQSqXS1CY+Ph56vR45OTlWrL5zMBgM2LhxI2praxEbG8tn3AGeeeYZTJkyxeyZAvz3uT2dOXMGQUFBCA0NxezZs1FYWAjAdp8xF0O1gvLychgMBrO/WABQKpU4deqUSFV1LVqtFgBu+Ix/PabVauHv72923MHBAd26dTO1IXNGoxHz5s3DqFGjMGDAAADNz1Eul8PLy8us7R+f9Y3+Ln49Rs2OHz+O2NhY1NXVwc3NDZs3b0ZERASys7P5jNvRxo0bcfjwYRw8ePC6Y/z3uX3ExMRg3bp16Nu3L0pKSvDGG29gzJgxOHHihM0+YwYgIrqpZ555BidOnMDPP/8sdildUt++fZGdnY2qqip88803eOSRR7B7926xy+pSioqK8Pzzz2PHjh1wcnISu5wua/LkyaZ/HjRoEGJiYtCzZ0989dVXcHZ2FrGym+MrMCvw9fWFTCa7bsS7TqdDQECASFV1Lb8+x1s944CAAJSWlpodb2pqQkVFBf8ebuDZZ5/F999/j127dqF79+6m/QEBAWhoaEBlZaVZ+z8+6xv9Xfx6jJrJ5XKEhYUhOjoaKSkpiIyMxIcffshn3I6ysrJQWlqKIUOGwMHBAQ4ODti9ezeWLVsGBwcHKJVKPusO4OXlhT59+uDs2bM2++8zA5AVyOVyREdHQ6PRmPYZjUZoNBrExsaKWFnXERISgoCAALNnrNfrkZGRYXrGsbGxqKysRFZWlqnNzp07YTQaERMTY/WabZUgCHj22WexefNm7Ny5EyEhIWbHo6Oj4ejoaPas8/LyUFhYaPasjx8/bhY4d+zYAQ8PD0RERFjnRjoho9GI+vp6PuN2NGHCBBw/fhzZ2dmmbejQoZg9e7bpn/ms219NTQ3OnTuHwMBA2/33uUOGVtN1Nm7cKCgUCmHdunXCyZMnhaeeekrw8vIyG/FOt1ZdXS0cOXJEOHLkiABAWLJkiXDkyBHhwoULgiA0fwbv5eUlfPfdd8KxY8eEqVOn3vAz+MGDBwsZGRnCzz//LPTu3Zufwf/BnDlzBE9PTyEtLc3sk9arV6+a2jz99NNCjx49hJ07dwqHDh0SYmNjhdjYWNPxXz9pnThxopCdnS2kpqYKfn5+/Gz4d+bPny/s3r1byM/PF44dOybMnz9fkEgkwo8//igIAp9xR/r9V2CCwGfdHl544QUhLS1NyM/PF/bt2yfExcUJvr6+QmlpqSAItvmMGYCsaPny5UKPHj0EuVwuDB8+XDhw4IDYJXUqu3btEgBctz3yyCOCIDR/Cv/aa68JSqVSUCgUwoQJE4S8vDyza1y+fFmYNWuW4ObmJnh4eAiJiYlCdXW1CHdju270jAEIn3zyianNtWvXhLlz5wre3t6Ci4uLcO+99wolJSVm1ykoKBAmT54sODs7C76+vsILL7wgNDY2WvlubNdjjz0m9OzZU5DL5YKfn58wYcIEU/gRBD7jjvTHAMRnbbkZM2YIgYGBglwuF4KDg4UZM2YIZ8+eNR23xWcsEQRB6Ji+JSIiIiLbxDFAREREZHcYgIiIiMjuMAARERGR3WEAIiIiIrvDAERERER2hwGIiIiI7A4DEBEREdkdBiAiIiKyOwxAREQA1Go1li5dKnYZRGQlDEBEZHWPPvoopk2bBgAYP3485s2bZ7WfvW7dOnh5eV23/+DBg3jqqaesVgcRictB7AKIiNpDQ0MD5HJ5m8/38/Nrx2qIyNaxB4iIRPPoo49i9+7d+PDDDyGRSCCRSFBQUAAAOHHiBCZPngw3NzcolUo8/PDDKC8vN507fvx4PPvss5g3bx58fX0RHx8PAFiyZAkGDhwIV1dXqFQqzJ07FzU1NQCAtLQ0JCYmoqqqyvTzXn/9dQDXvwIrLCzE1KlT4ebmBg8PDzz44IPQ6XSm46+//jqioqKwYcMGqNVqeHp6YubMmaiurja1+eabbzBw4EA4OzvDx8cHcXFxqK2t7aCnSUStwQBERKL58MMPERsbiyeffBIlJSUoKSmBSqVCZWUlbr/9dgwePBiHDh1CamoqdDodHnzwQbPz169fD7lcjn379mH16tUAAKlUimXLliEnJwfr16/Hzp078fLLLwMARo4ciaVLl8LDw8P081588cXr6jIajZg6dSoqKiqwe/du7NixA+fPn8eMGTPM2p07dw5btmzB999/j++//x67d+/GokWLAAAlJSWYNWsWHnvsMeTm5iItLQ3Tp08H158msg18BUZEovH09IRcLoeLiwsCAgJM+1esWIHBgwfjnXfeMe1bu3YtVCoVTp8+jT59+gAAevfujXfffdfsmr8fT6RWq/H222/j6aefxr/+9S/I5XJ4enpCIpGY/bw/0mg0OH78OPLz86FSqQAAn376Kfr374+DBw9i2LBhAJqD0rp16+Du7g4AePjhh6HRaPCPf/wDJSUlaGpqwvTp09GzZ08AwMCBAy14WkTUntgDREQ25+jRo9i1axfc3NxMW3h4OIDmXpdfRUdHX3fuTz/9hAkTJiA4OBju7u54+OGHcfnyZVy9erXFPz83NxcqlcoUfgAgIiICXl5eyM3NNe1Tq9Wm8AMAgYGBKC0tBQBERkZiwoQJGDhwIB544AGsWbMGV65caflDIKIOxQBERDanpqYGd999N7Kzs822M2fOYOzYsaZ2rq6uZucVFBTgrrvuwqBBg/Df//4XWVlZWLlyJYDmQdLtzdHR0ezPEokERqMRACCTybBjxw788MMPiIiIwPLly9G3b1/k5+e3ex1E1HoMQEQkKrlcDoPBYLZvyJAhyMnJgVqtRlhYmNn2x9Dze1lZWTAajfjggw8wYsQI9OnTB8XFxX/68/6oX79+KCoqQlFRkWnfyZMnUVlZiYiIiBbfm0QiwahRo/DGG2/gyJEjkMvl2Lx5c4vPJ6KOwwBERKJSq9XIyMhAQUEBysvLYTQa8cwzz6CiogKzZs3CwYMHce7cOWzfvh2JiYm3DC9hYWFobGzE8uXLcf78eWzYsME0OPr3P6+mpgYajQbl5eU3fDUWFxeHgQMHYvbs2Th8+DAyMzORkJCAcePGYejQoS26r4yMDLzzzjs4dOgQCgsL8e2336KsrAz9+vVr3QMiog7BAEREonrxxRchk8kQEREBPz8/FBYWIigoCPv27YPBYMDEiRMxcOBAzJs3D15eXpBKb/6/rcjISCxZsgSLFy/GgAED8PnnnyMlJcWszciRI/H0009jxowZ8PPzu24QNdDcc/Pdd9/B29sbY8eORVxcHEJDQ7Fp06YW35eHhwf27NmDO++8E3369MGrr76KDz74AJMnT275wyGiDiMR+E0mERER2Rn2ABEREZHdYQAiIiIiu8MARERERHaHAYiIiIjsDgMQERER2R0GICIiIrI7DEBERERkdxiAiIiIyO4wABEREZHdYQAiIiIiu8MARERERHbn/wd+tIVvg/yl5QAAAABJRU5ErkJggg==",
"text/plain": [
""
]
@@ -304,7 +331,10 @@
}
],
"source": [
- "plt.scatter(model.collocation_point_sample, model.BC_forward)"
+ "plt.figure(2)\n",
+ "plt.plot(history)\n",
+ "plt.xlabel(\"Iterations\")\n",
+ "plt.ylabel(\"Loss\")"
]
}
],