Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tutorials #124

Closed
wants to merge 12 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .github/workflows/testing_pr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ on:
pull_request:
branches:
- "master"
- "v0.1"


jobs:
Expand All @@ -13,7 +14,7 @@ jobs:
fail-fast: false
matrix:
os: [windows-latest, macos-latest, ubuntu-latest]
python-version: [3.7, 3.8]
python-version: [3.7, 3.8, 3.9, 3.10]

steps:
- uses: actions/checkout@v2
Expand Down
2 changes: 1 addition & 1 deletion docs/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

# You can set these variables from the command line.
SPHINXOPTS =
SPHINXBUILD = python -msphinx #sphinx-build
SPHINXBUILD = sphinx-build
PAPER =
BUILDDIR = build

Expand Down
15 changes: 12 additions & 3 deletions docs/source/_rst/code.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,20 @@ Code Documentation

PINN <pinn.rst>
LabelTensor <label_tensor.rst>
Span <span.rst>
Operators <operators.rst>
Plotter <plotter.rst>
Condition <condition.rst>
Location <location.rst>
Operators <operators.rst>
Plotter <plotter.rst>

Geometries
----------

.. toctree::
:maxdepth: 3

Span <span.rst>
Ellipsoid <ellipsoid.rst>


Model
-----
Expand Down
10 changes: 10 additions & 0 deletions docs/source/_rst/ellipsoid.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
Ellipsoid
===========
.. currentmodule:: pina.ellipsoid

.. automodule:: pina.ellipsoid

.. autoclass:: Ellipsoid
:members:
:show-inheritance:
:noindex:
8 changes: 5 additions & 3 deletions pina/__init__.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
__all__ = [
'PINN',
'Trainer',
'LabelTensor',
'Plotter',
'Condition',
'Span',
'Location',
'CartesianDomain'
]

from .meta import *
from .label_tensor import LabelTensor
from .pinn import PINN
from .trainer import Trainer
from .plotter import Plotter
from .span import Span
from .condition import Condition
from .location import Location
from .geometry import Location
from .geometry import CartesianDomain
9 changes: 0 additions & 9 deletions pina/chebyshev.py

This file was deleted.

37 changes: 16 additions & 21 deletions pina/condition.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
""" Condition module. """
from .label_tensor import LabelTensor
from .location import Location
from .geometry import Location
from .equation.equation import Equation

def dummy(a):
"""Dummy function for testing purposes."""
Expand All @@ -17,13 +18,13 @@ class Condition:
case, the model is trained to produce the output points given the input
points.

2. By specifying the location and the function of the condition; in such
a case, the model is trained to minimize that function by evaluating it
at some samples of the location.
2. By specifying the location and the equation of the condition; in such
a case, the model is trained to minimize the equation residual by
evaluating it at some samples of the location.

3. By specifying the input points and the function of the condition; in
such a case, the model is trained to minimize that function by
evaluating it at the input points.
3. By specifying the input points and the equation of the condition; in
such a case, the model is trained to minimize the equation residual by
evaluating it at the passed input points.

Example::

Expand All @@ -40,15 +41,15 @@ class Condition:
>>> output_points=example_output_pts)
>>> Condition(
>>> location=example_domain,
>>> function=example_dirichlet)
>>> equation=example_dirichlet)
>>> Condition(
>>> input_points=example_input_pts,
>>> function=example_dirichlet)
>>> equation=example_dirichlet)

"""

__slots__ = [
'input_points', 'output_points', 'location', 'function',
'input_points', 'output_points', 'location', 'equation',
'data_weight'
]

Expand All @@ -70,8 +71,8 @@ def __init__(self, *args, **kwargs):

if (
sorted(kwargs.keys()) != sorted(['input_points', 'output_points']) and
sorted(kwargs.keys()) != sorted(['location', 'function']) and
sorted(kwargs.keys()) != sorted(['input_points', 'function'])
sorted(kwargs.keys()) != sorted(['location', 'equation']) and
sorted(kwargs.keys()) != sorted(['input_points', 'equation'])
):
raise ValueError(f'Invalid keyword arguments {kwargs.keys()}.')

Expand All @@ -81,14 +82,8 @@ def __init__(self, *args, **kwargs):
raise TypeError('`output_points` must be a torch.Tensor.')
if not self._dictvalue_isinstance(kwargs, 'location', Location):
raise TypeError('`location` must be a Location.')

if 'function' in kwargs:
kwargs['function'] = [kwargs['function']]

for i, func in enumerate(kwargs['function']):
if not callable(func):
raise TypeError(
f'`function[{i}]` must be a callable function.')
if not self._dictvalue_isinstance(kwargs, 'equation', Equation):
raise TypeError('`equation` must be a Equation.')

for key, value in kwargs.items():
setattr(self, key, value)
setattr(self, key, value)
127 changes: 127 additions & 0 deletions pina/dataset.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
class PinaDataset():

def __init__(self, pinn) -> None:
self.pinn = pinn

@property
def dataloader(self):
return self._create_dataloader()

@property
def dataset(self):
return [self.SampleDataset(key, val)
for key, val in self.input_pts.items()]

def _create_dataloader(self):
"""Private method for creating dataloader

:return: dataloader
:rtype: torch.utils.data.DataLoader
"""
if self.pinn.batch_size is None:
return {key: [{key: val}] for key, val in self.pinn.input_pts.items()}

def custom_collate(batch):
# extracting pts labels
_, pts = list(batch[0].items())[0]
labels = pts.labels
# calling default torch collate
collate_res = default_collate(batch)
# save collate result in dict
res = {}
for key, val in collate_res.items():
val.labels = labels
res[key] = val
def __getitem__(self, index):
tensor = self._tensor.select(0, index)
return {self._location: tensor}

def __len__(self):
return self._len

from torch.utils.data import Dataset, DataLoader
class LabelTensorDataset(Dataset):
def __init__(self, d):
for k, v in d.items():
setattr(self, k, v)
self.labels = list(d.keys())

def __getitem__(self, index):
print(index)
result = {}
for label in self.labels:
sample_tensor = getattr(self, label)

# print('porcodio')
# print(sample_tensor.shape[1])
# print(index)
# print(sample_tensor[index])
try:
result[label] = sample_tensor[index]
except IndexError:
result[label] = torch.tensor([])

print(result)
return result

def __len__(self):
return max([len(getattr(self, label)) for label in self.labels])


class LabelTensorDataLoader(DataLoader):

def collate_fn(self, data):
print(data)
gggggggggg
# return dict(zip(self.pinn.input_pts.keys(), dataloaders))

# class SampleDataset(torch.utils.data.Dataset):

# def __init__(self, location, tensor):
# self._tensor = tensor
# self._location = location
# self._len = len(tensor)

# def __getitem__(self, index):
# tensor = self._tensor.select(0, index)
# return {self._location: tensor}

# def __len__(self):
# return self._len

from torch.utils.data import Dataset, DataLoader
class LabelTensorDataset(Dataset):
def __init__(self, d):
for k, v in d.items():
setattr(self, k, v)
self.labels = list(d.keys())

def __getitem__(self, index):
print(index)
result = {}
for label in self.labels:
sample_tensor = getattr(self, label)

# print('porcodio')
# print(sample_tensor.shape[1])
# print(index)
# print(sample_tensor[index])
try:
result[label] = sample_tensor[index]
except IndexError:
result[label] = torch.tensor([])

print(result)
return result

def __len__(self):
return max([len(getattr(self, label)) for label in self.labels])

# TODO: working also for datapoints
class DummyLoader:

def __init__(self, data) -> None:
self.data = [data]

def __iter__(self):
return iter(self.data)
Empty file added pina/equation/__init__.py
Empty file.
10 changes: 10 additions & 0 deletions pina/equation/equation.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
""" Module """
from .equation_interface import EquationInterface

class Equation(EquationInterface):

def __init__(self, equation):
self.__equation = equation

def residual(self, input_, output_):
return self.__equation(input_, output_)
37 changes: 37 additions & 0 deletions pina/equation/equation_factory.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
""" Module """
from .equation import Equation
from ..operators import grad, div, nabla


class FixedValue(Equation):

def __init__(self, value, components=None):
def equation(input_, output_):
if components is None:
return output_ - value
return output_.extract(components) - value
super().__init__(equation)


class FixedGradient(Equation):

def __init__(self, value, components=None, d=None):
def equation(input_, output_):
return grad(output_, input_, components=components, d=d) - value
super().__init__(equation)


class FixedFlux(Equation):

def __init__(self, value, components=None, d=None):
def equation(input_, output_):
return div(output_, input_, components=components, d=d) - value
super().__init__(equation)


class Laplace(Equation):

def __init__(self, components=None, d=None):
def equation(input_, output_):
return nabla(output_, input_, components=components, d=d)
super().__init__(equation)
13 changes: 13 additions & 0 deletions pina/equation/equation_interface.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
""" Module for EquationInterface class """
from abc import ABCMeta, abstractmethod


class EquationInterface(metaclass=ABCMeta):
"""
The abstract `AbstractProblem` class. All the class defining a PINA Problem
should be inheritied from this class.

In the definition of a PINA problem, the fundamental elements are:
the output variables, the condition(s), and the domain(s) where the
conditions are applied.
"""
24 changes: 24 additions & 0 deletions pina/equation/system_equation.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
""" Module """
import torch
from .equation import Equation

class SystemEquation(Equation):

def __init__(self, list_equation):
if not isinstance(list_equation, list):
raise TypeError('list_equation must be a list of functions')

self.equations = []
for i, equation in enumerate(list_equation):
if not callable(equation):
raise TypeError('list_equation must be a list of functions')

self.equations.append(Equation(equation))

def residual(self, input_, output_):
return torch.mean(
torch.stack([
equation.residual(input_, output_)
for equation in self.equations
]),
dim=0)
Loading