fnn update, pinn torch models, tests update. (#88)

* fnn update, remove labeltensors
* allow custom torch models
* updating tests

---------

Co-authored-by: Dario Coscia <dariocoscia@Dario-Coscia.local>
Co-authored-by: Dario Coscia <dariocoscia@dhcp-031.eduroam.sissa.it>
This commit is contained in:
Dario Coscia
2023-05-02 15:19:48 +02:00
committed by Nicola Demo
parent c8fb7715c4
commit be11110bb2
11 changed files with 149 additions and 177 deletions

View File

@@ -1,13 +1,13 @@
import torch
import pytest
from pina import LabelTensor, Condition, Span, PINN
from pina import LabelTensor, Condition, CartesianDomain, PINN
from pina.problem import SpatialProblem
from pina.model import FeedForward
from pina.operators import nabla
example_domain = Span({'x': [0, 1], 'y': [0, 1]})
example_domain = CartesianDomain({'x': [0, 1], 'y': [0, 1]})
def example_dirichlet(input_, output_):
value = 0.0
return output_.extract(['u']) - value

View File

@@ -1,30 +0,0 @@
import pytest
import torch
from pina import LabelTensor
from pina.model import DeepONet
from pina.model import FeedForward as FFN
data = torch.rand((20, 3))
input_vars = ['a', 'b', 'c']
output_vars = ['d']
input_ = LabelTensor(data, input_vars)
def test_constructor():
branch = FFN(input_variables=['a', 'c'], output_variables=20)
trunk = FFN(input_variables=['b'], output_variables=20)
onet = DeepONet(nets=[trunk, branch], output_variables=output_vars)
def test_constructor_fails_when_invalid_inner_layer_size():
branch = FFN(input_variables=['a', 'c'], output_variables=20)
trunk = FFN(input_variables=['b'], output_variables=19)
with pytest.raises(ValueError):
DeepONet(nets=[trunk, branch], output_variables=output_vars)
def test_forward():
branch = FFN(input_variables=['a', 'c'], output_variables=10)
trunk = FFN(input_variables=['b'], output_variables=10)
onet = DeepONet(nets=[trunk, branch], output_variables=output_vars)
output_ = onet(input_)
assert output_.labels == output_vars

View File

@@ -1,58 +0,0 @@
import torch
import pytest
from pina import LabelTensor
from pina.model import FeedForward
class myFeature(torch.nn.Module):
"""
Feature: sin(pi*x)
"""
def __init__(self):
super(myFeature, self).__init__()
def forward(self, x):
return LabelTensor(torch.sin(torch.pi * x.extract('a')), 'sin(a)')
data = torch.rand((20, 3))
input_vars = ['a', 'b', 'c']
output_vars = ['d', 'e']
input_ = LabelTensor(data, input_vars)
def test_constructor():
FeedForward(input_vars, output_vars)
FeedForward(3, 4)
FeedForward(input_vars, output_vars, extra_features=[myFeature()])
FeedForward(input_vars, output_vars, inner_size=10, n_layers=20)
FeedForward(input_vars, output_vars, layers=[10, 20, 5, 2])
FeedForward(input_vars, output_vars, layers=[10, 20, 5, 2],
func=torch.nn.ReLU)
FeedForward(input_vars, output_vars, layers=[10, 20, 5, 2],
func=[torch.nn.ReLU, torch.nn.ReLU, None, torch.nn.Tanh])
def test_constructor_wrong():
with pytest.raises(RuntimeError):
FeedForward(input_vars, output_vars, layers=[10, 20, 5, 2],
func=[torch.nn.ReLU, torch.nn.ReLU])
def test_forward():
fnn = FeedForward(input_vars, output_vars)
output_ = fnn(input_)
assert output_.labels == output_vars
def test_forward2():
dim_in, dim_out = 3, 2
fnn = FeedForward(dim_in, dim_out)
output_ = fnn(input_)
assert output_.shape == (input_.shape[0], dim_out)
def test_forward_features():
fnn = FeedForward(input_vars, output_vars, extra_features=[myFeature()])
output_ = fnn(input_)
assert output_.labels == output_vars

View File

@@ -0,0 +1,31 @@
import pytest
import torch
from pina import LabelTensor
from pina.model import DeepONet
from pina.model import FeedForward as FFN
data = torch.rand((20, 3))
input_vars = ['a', 'b', 'c']
output_vars = ['d']
input_ = LabelTensor(data, input_vars)
# TODO
# def test_constructor():
# branch = FFN(input_variables=['a', 'c'], output_variables=20)
# trunk = FFN(input_variables=['b'], output_variables=20)
# onet = DeepONet(nets=[trunk, branch], output_variables=output_vars)
# def test_constructor_fails_when_invalid_inner_layer_size():
# branch = FFN(input_variables=['a', 'c'], output_variables=20)
# trunk = FFN(input_variables=['b'], output_variables=19)
# with pytest.raises(ValueError):
# DeepONet(nets=[trunk, branch], output_variables=output_vars)
# def test_forward():
# branch = FFN(input_variables=['a', 'c'], output_variables=10)
# trunk = FFN(input_variables=['b'], output_variables=10)
# onet = DeepONet(nets=[trunk, branch], output_variables=output_vars)
# output_ = onet(input_)
# assert output_.labels == output_vars

View File

@@ -0,0 +1,33 @@
import torch
import pytest
from pina.model import FeedForward
data = torch.rand((20, 3))
input_vars = 3
output_vars = 4
def test_constructor():
FeedForward(input_vars, output_vars)
FeedForward(input_vars, output_vars, inner_size=10, n_layers=20)
FeedForward(input_vars, output_vars, layers=[10, 20, 5, 2])
FeedForward(input_vars, output_vars, layers=[10, 20, 5, 2],
func=torch.nn.ReLU)
FeedForward(input_vars, output_vars, layers=[10, 20, 5, 2],
func=[torch.nn.ReLU, torch.nn.ReLU, None, torch.nn.Tanh])
def test_constructor_wrong():
with pytest.raises(RuntimeError):
FeedForward(input_vars, output_vars, layers=[10, 20, 5, 2],
func=[torch.nn.ReLU, torch.nn.ReLU])
def test_forward():
dim_in, dim_out = 3, 2
fnn = FeedForward(dim_in, dim_out)
output_ = fnn(data)
assert output_.shape == (data.shape[0], dim_out)

View File

@@ -1,38 +1,10 @@
import torch
import torch.nn as nn
import pytest
from pina.model import Network
from pina.model import Network, FeedForward
from pina import LabelTensor
class SimpleNet(nn.Module):
def __init__(self):
super().__init__()
self.layers = nn.Sequential(
nn.Linear(2, 20),
nn.Tanh(),
nn.Linear(20, 1)
)
def forward(self, x):
return self.layers(x)
class SimpleNetExtraFeat(nn.Module):
def __init__(self):
super().__init__()
self.layers = nn.Sequential(
nn.Linear(3, 20),
nn.Tanh(),
nn.Linear(20, 1)
)
def forward(self, x):
return self.layers(x)
class myFeature(torch.nn.Module):
"""
Feature: sin(x)
@@ -54,13 +26,13 @@ input_ = LabelTensor(data, input_variables)
def test_constructor():
net = SimpleNet()
net = FeedForward(2, 1)
pina_net = Network(model=net, input_variables=input_variables,
output_variables=output_variables)
def test_forward():
net = SimpleNet()
net = FeedForward(2, 1)
pina_net = Network(model=net, input_variables=input_variables,
output_variables=output_variables)
output_ = pina_net(input_)
@@ -68,14 +40,14 @@ def test_forward():
def test_constructor_extrafeat():
net = SimpleNetExtraFeat()
net = FeedForward(3, 1)
feat = [myFeature()]
pina_net = Network(model=net, input_variables=input_variables,
output_variables=output_variables, extra_features=feat)
def test_forward_extrafeat():
net = SimpleNetExtraFeat()
net = FeedForward(3, 1)
feat = [myFeature()]
pina_net = Network(model=net, input_variables=input_variables,
output_variables=output_variables, extra_features=feat)

View File

@@ -1,7 +1,7 @@
import torch
import pytest
from pina import LabelTensor, Condition, Span, PINN
from pina import LabelTensor, Condition, CartesianDomain, PINN
from pina.problem import SpatialProblem
from pina.model import FeedForward
from pina.operators import nabla
@@ -11,7 +11,7 @@ out_ = LabelTensor(torch.tensor([[0.]]), ['u'])
class Poisson(SpatialProblem):
output_variables = ['u']
spatial_domain = Span({'x': [0, 1], 'y': [0, 1]})
spatial_domain = CartesianDomain({'x': [0, 1], 'y': [0, 1]})
def laplace_equation(input_, output_):
force_term = (torch.sin(input_.extract(['x'])*torch.pi) *
@@ -25,19 +25,19 @@ class Poisson(SpatialProblem):
conditions = {
'gamma1': Condition(
location=Span({'x': [0, 1], 'y': 1}),
location=CartesianDomain({'x': [0, 1], 'y': 1}),
function=nil_dirichlet),
'gamma2': Condition(
location=Span({'x': [0, 1], 'y': 0}),
location=CartesianDomain({'x': [0, 1], 'y': 0}),
function=nil_dirichlet),
'gamma3': Condition(
location=Span({'x': 1, 'y': [0, 1]}),
location=CartesianDomain({'x': 1, 'y': [0, 1]}),
function=nil_dirichlet),
'gamma4': Condition(
location=Span({'x': 0, 'y': [0, 1]}),
location=CartesianDomain({'x': 0, 'y': [0, 1]}),
function=nil_dirichlet),
'D': Condition(
location=Span({'x': [0, 1], 'y': [0, 1]}),
location=CartesianDomain({'x': [0, 1], 'y': [0, 1]}),
function=laplace_equation),
'data': Condition(
input_points=in_,
@@ -53,15 +53,33 @@ class Poisson(SpatialProblem):
truth_solution = poisson_sol
problem = Poisson()
class myFeature(torch.nn.Module):
"""
Feature: sin(x)
"""
model = FeedForward(problem.input_variables, problem.output_variables)
def __init__(self):
super(myFeature, self).__init__()
def forward(self, x):
t = (torch.sin(x.extract(['x'])*torch.pi) *
torch.sin(x.extract(['y'])*torch.pi))
return LabelTensor(t, ['sin(x)sin(y)'])
problem = Poisson()
model = FeedForward(len(problem.input_variables),len(problem.output_variables))
model_extra_feat = FeedForward(len(problem.input_variables) + 1,len(problem.output_variables))
def test_constructor():
PINN(problem, model)
def test_constructor_extra_feats():
PINN(problem, model_extra_feat, [myFeature()])
def test_span_pts():
pinn = PINN(problem, model)
n = 10
@@ -133,6 +151,28 @@ def test_train_2():
assert list(pinn.history_loss.keys()) == truth_key
def test_train_extra_feats():
pinn = PINN(problem, model_extra_feat, [myFeature()])
boundaries = ['gamma1', 'gamma2', 'gamma3', 'gamma4']
n = 10
pinn.span_pts(n, 'grid', locations=boundaries)
pinn.span_pts(n, 'grid', locations=['D'])
pinn.train(5)
def test_train_2_extra_feats():
boundaries = ['gamma1', 'gamma2', 'gamma3', 'gamma4']
n = 10
expected_keys = [[], list(range(0, 50, 3))]
param = [0, 3]
for i, truth_key in zip(param, expected_keys):
pinn = PINN(problem, model_extra_feat, [myFeature()])
pinn.span_pts(n, 'grid', locations=boundaries)
pinn.span_pts(n, 'grid', locations=['D'])
pinn.train(50, save_loss=i)
assert list(pinn.history_loss.keys()) == truth_key
def test_train_with_optimizer_kwargs():
boundaries = ['gamma1', 'gamma2', 'gamma3', 'gamma4']
n = 10