Examples update for v0.1 (#206)

* modify examples/problems
* modify tutorials

---------

Co-authored-by: Dario Coscia <dariocoscia@dhcp-235.eduroam.sissa.it>
Co-authored-by: Dario Coscia <dariocoscia@dhcp-015.eduroam.sissa.it>
This commit is contained in:
Dario Coscia
2023-11-14 18:24:07 +01:00
committed by Nicola Demo
parent 0d38de5afe
commit ee39b39805
19 changed files with 605 additions and 613 deletions

View File

@@ -1,9 +1,5 @@
import torch
""" Burgers' problem. """
from pina.problem import TimeDependentProblem, SpatialProblem
from pina.operators import grad
from pina import Condition
from pina.span import Span
# ===================================================== #
# #
@@ -17,12 +13,16 @@ from pina.span import Span
# #
# ===================================================== #
class Burgers1D(TimeDependentProblem, SpatialProblem):
# assign output/ spatial and temporal variables
output_variables = ['u']
spatial_domain = Span({'x': [-1, 1]})
temporal_domain = Span({'t': [0, 1]})
import torch
from pina.geometry import CartesianDomain
from pina import Condition
from pina.problem import TimeDependentProblem, SpatialProblem
from pina.operators import grad
from pina.equation import FixedValue, Equation
class Burgers1D(TimeDependentProblem, SpatialProblem):
# define the burger equation
def burger_equation(input_, output_):
@@ -34,20 +34,20 @@ class Burgers1D(TimeDependentProblem, SpatialProblem):
(0.01/torch.pi)*ddu.extract(['ddudxdx'])
)
# define nill dirichlet boundary conditions
def nil_dirichlet(input_, output_):
u_expected = 0.0
return output_.extract(['u']) - u_expected
# define initial condition
def initial_condition(input_, output_):
u_expected = -torch.sin(torch.pi*input_.extract(['x']))
return output_.extract(['u']) - u_expected
# assign output/ spatial and temporal variables
output_variables = ['u']
spatial_domain = CartesianDomain({'x': [-1, 1]})
temporal_domain = CartesianDomain({'t': [0, 1]})
# problem condition statement
conditions = {
'gamma1': Condition(location=Span({'x': -1, 't': [0, 1]}), function=nil_dirichlet),
'gamma2': Condition(location=Span({'x': 1, 't': [0, 1]}), function=nil_dirichlet),
't0': Condition(location=Span({'x': [-1, 1], 't': 0}), function=initial_condition),
'D': Condition(location=Span({'x': [-1, 1], 't': [0, 1]}), function=burger_equation),
}
'gamma1': Condition(location=CartesianDomain({'x': -1, 't': [0, 1]}), equation=FixedValue(0.)),
'gamma2': Condition(location=CartesianDomain({'x': 1, 't': [0, 1]}), equation=FixedValue(0.)),
't0': Condition(location=CartesianDomain({'x': [-1, 1], 't': 0}), equation=Equation(initial_condition)),
'D': Condition(location=CartesianDomain({'x': [-1, 1], 't': [0, 1]}), equation=Equation(burger_equation)),
}

View File

@@ -1,47 +0,0 @@
# import torch
# from pina.problem import Problem
# from pina.segment import Segment
# from pina.cube import Cube
# from pina.problem2d import Problem2D
# xmin, xmax, ymin, ymax = -1, 1, -1, 1
# class EllipticOptimalControl(Problem2D):
# def __init__(self, alpha=1):
# def term1(input_, output_):
# grad_p = self.grad(output_.extract(['p']), input_)
# gradgrad_p_x1 = self.grad(grad_p.extract(['x1']), input_)
# gradgrad_p_x2 = self.grad(grad_p.extract(['x2']), input_)
# yd = 2.0
# return output_.extract(['y']) - yd - (gradgrad_p_x1.extract(['x1']) + gradgrad_p_x2.extract(['x2']))
# def term2(input_, output_):
# grad_y = self.grad(output_.extract(['y']), input_)
# gradgrad_y_x1 = self.grad(grad_y.extract(['x1']), input_)
# gradgrad_y_x2 = self.grad(grad_y.extract(['x2']), input_)
# return - (gradgrad_y_x1.extract(['x1']) + gradgrad_y_x2.extract(['x2'])) - output_.extract(['u'])
# def term3(input_, output_):
# return output_.extract(['p']) - output_.extract(['u'])*alpha
# def nil_dirichlet(input_, output_):
# y_value = 0.0
# p_value = 0.0
# return torch.abs(output_.extract(['y']) - y_value) + torch.abs(output_.extract(['p']) - p_value)
# self.conditions = {
# 'gamma1': {'location': Segment((xmin, ymin), (xmax, ymin)), 'func': nil_dirichlet},
# 'gamma2': {'location': Segment((xmax, ymin), (xmax, ymax)), 'func': nil_dirichlet},
# 'gamma3': {'location': Segment((xmax, ymax), (xmin, ymax)), 'func': nil_dirichlet},
# 'gamma4': {'location': Segment((xmin, ymax), (xmin, ymin)), 'func': nil_dirichlet},
# 'D1': {'location': Cube([[xmin, xmax], [ymin, ymax]]), 'func': [term1, term2, term3]},
# }
# self.input_variables = ['x1', 'x2']
# self.output_variables = ['u', 'p', 'y']
# self.spatial_domain = Cube([[xmin, xmax], [xmin, xmax]])
raise NotImplementedError('not available problem at the moment...')

View File

@@ -1,7 +1,5 @@
from pina.problem import SpatialProblem
from pina import Condition, Span
from pina.operators import grad
import torch
""" Simple ODE problem. """
# ===================================================== #
# #
@@ -11,16 +9,28 @@ import torch
# y --> field variable #
# x --> spatial variable #
# #
# The equation is: #
# dy(x)/dx + y(x) = x #
# #
# ===================================================== #
from pina.problem import SpatialProblem
from pina import Condition
from pina.geometry import CartesianDomain
from pina.operators import grad
from pina.equation import Equation, FixedValue
import torch
class FirstOrderODE(SpatialProblem):
# variable domain range
x_rng = [0, 5]
x_rng = [0., 5.]
# field variable
output_variables = ['y']
# create domain
spatial_domain = Span({'x': x_rng})
spatial_domain = CartesianDomain({'x': x_rng})
# define the ode
def ode(input_, output_):
@@ -28,11 +38,6 @@ class FirstOrderODE(SpatialProblem):
x = input_
return grad(y, x) + y - x
# define initial conditions
def fixed(input_, output_):
exp_value = 1.
return output_ - exp_value
# define real solution
def solution(self, input_):
x = input_
@@ -40,7 +45,8 @@ class FirstOrderODE(SpatialProblem):
# define problem conditions
conditions = {
'bc': Condition(location=Span({'x': x_rng[0]}), function=fixed),
'dd': Condition(location=Span({'x': x_rng}), function=ode),
'BC': Condition(location=CartesianDomain({'x': x_rng[0]}), equation=FixedValue(1.)),
'D': Condition(location=CartesianDomain({'x': x_rng}), equation=Equation(ode)),
}
truth_solution = solution

View File

@@ -1,52 +1,80 @@
import numpy as np
import torch
from pina.segment import Segment
from pina.cube import Cube
from pina.problem2d import Problem2D
xmin, xmax, ymin, ymax = -1, 1, -1, 1
class ParametricEllipticOptimalControl(Problem2D):
def __init__(self, alpha=1):
def term1(input_, param_, output_):
grad_p = self.grad(output_['p'], input_)
gradgrad_p_x1 = self.grad(grad_p['x1'], input_)
gradgrad_p_x2 = self.grad(grad_p['x2'], input_)
return output_['y'] - param_ - (gradgrad_p_x1['x1'] + gradgrad_p_x2['x2'])
def term2(input_, param_, output_):
grad_y = self.grad(output_['y'], input_)
gradgrad_y_x1 = self.grad(grad_y['x1'], input_)
gradgrad_y_x2 = self.grad(grad_y['x2'], input_)
return - (gradgrad_y_x1['x1'] + gradgrad_y_x2['x2']) - output_['u_param']
def term3(input_, param_, output_):
return output_['p'] - output_['u_param']*alpha
""" Poisson OCP problem. """
def term(input_, param_, output_):
return term1( input_, param_, output_) +term2( input_, param_, output_) + term3( input_, param_, output_)
from pina import Condition
from pina.geometry import CartesianDomain
from pina.equation import SystemEquation, FixedValue
from pina.problem import SpatialProblem, ParametricProblem
from pina.operators import laplacian
def nil_dirichlet(input_, param_, output_):
y_value = 0.0
p_value = 0.0
return torch.abs(output_['y'] - y_value) + torch.abs(output_['p'] - p_value)
# ===================================================== #
# #
# This script implements the two dimensional #
# Parametric Elliptic Optimal Control problem. #
# The ParametricEllipticOptimalControl class is #
# inherited from TimeDependentProblem, SpatialProblem #
# and we denote: #
# u --> field variable #
# p --> field variable #
# y --> field variable #
# x1, x2 --> spatial variables #
# mu, alpha --> problem parameters #
# #
# More info in https://arxiv.org/pdf/2110.13530.pdf #
# Section 4.2 of the article #
# ===================================================== #
self.conditions = {
'gamma1': {'location': Segment((xmin, ymin), (xmax, ymin)), 'func': nil_dirichlet},
'gamma2': {'location': Segment((xmax, ymin), (xmax, ymax)), 'func': nil_dirichlet},
'gamma3': {'location': Segment((xmax, ymax), (xmin, ymax)), 'func': nil_dirichlet},
'gamma4': {'location': Segment((xmin, ymax), (xmin, ymin)), 'func': nil_dirichlet},
'D1': {'location': Cube([[xmin, xmax], [ymin, ymax]]), 'func': term},
#'D2': {'location': Cube([[0, 1], [0, 1]]), 'func': term2},
#'D3': {'location': Cube([[0, 1], [0, 1]]), 'func': term3}
}
self.input_variables = ['x1', 'x2']
self.output_variables = ['u', 'p', 'y']
self.parameters = ['mu']
self.spatial_domain = Cube([[xmin, xmax], [xmin, xmax]])
self.parameter_domain = np.array([[0.5, 3]])
class ParametricEllipticOptimalControl(SpatialProblem, ParametricProblem):
# setting spatial variables ranges
xmin, xmax, ymin, ymax = -1, 1, -1, 1
x_range = [xmin, xmax]
y_range = [ymin, ymax]
# setting parameters range
amin, amax = 0.0001, 1
mumin, mumax = 0.5, 3
mu_range = [mumin, mumax]
a_range = [amin, amax]
# setting field variables
output_variables = ['u', 'p', 'y']
# setting spatial and parameter domain
spatial_domain = CartesianDomain({'x1': x_range, 'x2': y_range})
parameter_domain = CartesianDomain({'mu': mu_range, 'alpha': a_range})
# equation terms as in https://arxiv.org/pdf/2110.13530.pdf
def term1(input_, output_):
laplace_p = laplacian(output_, input_, components=['p'], d=['x1', 'x2'])
return output_.extract(['y']) - input_.extract(['mu']) - laplace_p
def term2(input_, output_):
laplace_y = laplacian(output_, input_, components=['y'], d=['x1', 'x2'])
return - laplace_y - output_.extract(['u'])
def fixed_y(input_, output_):
return output_.extract(['y'])
def fixed_p(input_, output_):
return output_.extract(['p'])
# setting problem condition formulation
conditions = {
'gamma1': Condition(
location=CartesianDomain({'x1': x_range, 'x2': 1, 'mu': mu_range, 'alpha': a_range}),
equation=SystemEquation([fixed_y, fixed_p])),
'gamma2': Condition(
location=CartesianDomain({'x1': x_range, 'x2': -1, 'mu': mu_range, 'alpha': a_range}),
equation=SystemEquation([fixed_y, fixed_p])),
'gamma3': Condition(
location=CartesianDomain({'x1': 1, 'x2': y_range, 'mu': mu_range, 'alpha': a_range}),
equation=SystemEquation([fixed_y, fixed_p])),
'gamma4': Condition(
location=CartesianDomain({'x1': -1, 'x2': y_range, 'mu': mu_range, 'alpha': a_range}),
equation=SystemEquation([fixed_y, fixed_p])),
'D': Condition(
location=CartesianDomain(
{'x1': x_range, 'x2': y_range,
'mu': mu_range, 'alpha': a_range
}),
equation=SystemEquation([term1, term2])),
}

View File

@@ -1,78 +0,0 @@
import numpy as np
import torch
from pina import Span, Condition
from pina.problem import SpatialProblem, ParametricProblem
from pina.operators import grad, laplacian
# ===================================================== #
# #
# This script implements the two dimensional #
# Parametric Elliptic Optimal Control problem. #
# The ParametricEllipticOptimalControl class is #
# inherited from TimeDependentProblem, SpatialProblem #
# and we denote: #
# u --> field variable #
# p --> field variable #
# y --> field variable #
# x1, x2 --> spatial variables #
# mu, alpha --> problem parameters #
# #
# More info in https://arxiv.org/pdf/2110.13530.pdf #
# Section 4.2 of the article #
# ===================================================== #
class ParametricEllipticOptimalControl(SpatialProblem, ParametricProblem):
# setting spatial variables ranges
xmin, xmax, ymin, ymax = -1, 1, -1, 1
x_range = [xmin, xmax]
y_range = [ymin, ymax]
# setting parameters range
amin, amax = 0.0001, 1
mumin, mumax = 0.5, 3
mu_range = [mumin, mumax]
a_range = [amin, amax]
# setting field variables
output_variables = ['u', 'p', 'y']
# setting spatial and parameter domain
spatial_domain = Span({'x1': x_range, 'x2': y_range})
parameter_domain = Span({'mu': mu_range, 'alpha': a_range})
# equation terms as in https://arxiv.org/pdf/2110.13530.pdf
def term1(input_, output_):
laplace_p = laplacian(output_, input_, components=['p'], d=['x1', 'x2'])
return output_.extract(['y']) - input_.extract(['mu']) - laplace_p
def term2(input_, output_):
laplace_y = laplacian(output_, input_, components=['y'], d=['x1', 'x2'])
return - laplace_y - output_.extract(['u_param'])
def state_dirichlet(input_, output_):
y_exp = 0.0
return output_.extract(['y']) - y_exp
def adj_dirichlet(input_, output_):
p_exp = 0.0
return output_.extract(['p']) - p_exp
# setting problem condition formulation
conditions = {
'gamma1': Condition(
location=Span({'x1': x_range, 'x2': 1, 'mu': mu_range, 'alpha': a_range}),
function=[state_dirichlet, adj_dirichlet]),
'gamma2': Condition(
location=Span({'x1': x_range, 'x2': -1, 'mu': mu_range, 'alpha': a_range}),
function=[state_dirichlet, adj_dirichlet]),
'gamma3': Condition(
location=Span({'x1': 1, 'x2': y_range, 'mu': mu_range, 'alpha': a_range}),
function=[state_dirichlet, adj_dirichlet]),
'gamma4': Condition(
location=Span({'x1': -1, 'x2': y_range, 'mu': mu_range, 'alpha': a_range}),
function=[state_dirichlet, adj_dirichlet]),
'D': Condition(
location=Span({'x1': x_range, 'x2': y_range,
'mu': mu_range, 'alpha': a_range}),
function=[term1, term2]),
}

View File

@@ -1,8 +1,5 @@
import torch
""" Parametric Poisson problem. """
from pina.problem import SpatialProblem, ParametricProblem
from pina.operators import laplacian
from pina import Span, Condition
# ===================================================== #
# #
@@ -16,12 +13,20 @@ from pina import Span, Condition
# #
# ===================================================== #
from pina.geometry import CartesianDomain
from pina.problem import SpatialProblem, ParametricProblem
from pina.operators import laplacian
from pina.equation import FixedValue, Equation
from pina import Condition
import torch
class ParametricPoisson(SpatialProblem, ParametricProblem):
# assign output/ spatial and parameter variables
output_variables = ['u']
spatial_domain = Span({'x': [-1, 1], 'y': [-1, 1]})
parameter_domain = Span({'mu1': [-1, 1], 'mu2': [-1, 1]})
spatial_domain = CartesianDomain({'x': [-1, 1], 'y': [-1, 1]})
parameter_domain = CartesianDomain({'mu1': [-1, 1], 'mu2': [-1, 1]})
# define the laplace equation
def laplace_equation(input_, output_):
@@ -30,26 +35,21 @@ class ParametricPoisson(SpatialProblem, ParametricProblem):
- 2*(input_.extract(['y']) - input_.extract(['mu2']))**2)
return laplacian(output_.extract(['u']), input_) - force_term
# define nill dirichlet boundary conditions
def nil_dirichlet(input_, output_):
value = 0.0
return output_.extract(['u']) - value
# problem condition statement
conditions = {
'gamma1': Condition(
location=Span({'x': [-1, 1], 'y': 1, 'mu1': [-1, 1], 'mu2': [-1, 1]}),
function=nil_dirichlet),
location=CartesianDomain({'x': [-1, 1], 'y': 1, 'mu1': [-1, 1], 'mu2': [-1, 1]}),
equation=FixedValue(0.)),
'gamma2': Condition(
location=Span({'x': [-1, 1], 'y': -1, 'mu1': [-1, 1], 'mu2': [-1, 1]}),
function=nil_dirichlet),
location=CartesianDomain({'x': [-1, 1], 'y': -1, 'mu1': [-1, 1], 'mu2': [-1, 1]}),
equation=FixedValue(0.)),
'gamma3': Condition(
location=Span({'x': 1, 'y': [-1, 1], 'mu1': [-1, 1], 'mu2': [-1, 1]}),
function=nil_dirichlet),
location=CartesianDomain({'x': 1, 'y': [-1, 1], 'mu1': [-1, 1], 'mu2': [-1, 1]}),
equation=FixedValue(0.)),
'gamma4': Condition(
location=Span({'x': -1, 'y': [-1, 1], 'mu1': [-1, 1], 'mu2': [-1, 1]}),
function=nil_dirichlet),
location=CartesianDomain({'x': -1, 'y': [-1, 1], 'mu1': [-1, 1], 'mu2': [-1, 1]}),
equation=FixedValue(0.)),
'D': Condition(
location=Span({'x': [-1, 1], 'y': [-1, 1], 'mu1': [-1, 1], 'mu2': [-1, 1]}),
function=laplace_equation),
}
location=CartesianDomain({'x': [-1, 1], 'y': [-1, 1], 'mu1': [-1, 1], 'mu2': [-1, 1]}),
equation=Equation(laplace_equation)),
}

View File

@@ -1,10 +1,5 @@
""" Poisson equation example. """
import numpy as np
import torch
""" Poisson problem. """
from pina.problem import SpatialProblem
from pina.operators import laplacian
from pina import Condition, Span
# ===================================================== #
# #
@@ -17,39 +12,46 @@ from pina import Condition, Span
# ===================================================== #
import torch
from pina.geometry import CartesianDomain
from pina import Condition
from pina.problem import SpatialProblem
from pina.operators import laplacian
from pina.equation import FixedValue, Equation
class Poisson(SpatialProblem):
# assign output/ spatial variables
output_variables = ['u']
spatial_domain = Span({'x': [0, 1], 'y': [0, 1]})
spatial_domain = CartesianDomain({'x': [0, 1], 'y': [0, 1]})
# define the laplace equation
def laplace_equation(input_, output_):
force_term = (torch.sin(input_.extract(['x'])*torch.pi) *
torch.sin(input_.extract(['y'])*torch.pi))
delta_u = laplacian(output_.extract(['u']), input_)
return delta_u - force_term
torch.sin(input_.extract(['y'])*torch.pi))
nabla_u = laplacian(output_.extract(['u']), input_)
return nabla_u - force_term
# define nill dirichlet boundary conditions
def nil_dirichlet(input_, output_):
value = 0.0
return output_.extract(['u']) - value
# problem condition statement
conditions = {
'gamma1': Condition(location=Span({'x': [0, 1], 'y': 1}), function=nil_dirichlet),
'gamma2': Condition(location=Span({'x': [0, 1], 'y': 0}), function=nil_dirichlet),
'gamma3': Condition(location=Span({'x': 1, 'y': [0, 1]}),function=nil_dirichlet),
'gamma4': Condition(location=Span({'x': 0, 'y': [0, 1]}), function=nil_dirichlet),
'D': Condition(location=Span({'x': [0, 1], 'y': [0, 1]}), function=laplace_equation),
'gamma1': Condition(
location=CartesianDomain({'x': [0, 1], 'y': 1}),
equation=FixedValue(0.0)),
'gamma2': Condition(
location=CartesianDomain({'x': [0, 1], 'y': 0}),
equation=FixedValue(0.0)),
'gamma3': Condition(
location=CartesianDomain({'x': 1, 'y': [0, 1]}),
equation=FixedValue(0.0)),
'gamma4': Condition(
location=CartesianDomain({'x': 0, 'y': [0, 1]}),
equation=FixedValue(0.0)),
'D': Condition(
location=CartesianDomain({'x': [0, 1], 'y': [0, 1]}),
equation=Equation(laplace_equation)),
}
# real poisson solution
def poisson_sol(self, pts):
return -(
torch.sin(pts.extract(['x'])*torch.pi) *
torch.sin(pts.extract(['y'])*torch.pi)
)/(2*torch.pi**2)
# return -(np.sin(x*np.pi)*np.sin(y*np.pi))/(2*np.pi**2)
truth_solution = poisson_sol

View File

@@ -1,9 +1,11 @@
import numpy as np
import torch
""" Navier Stokes Problem """
import torch
from pina.problem import SpatialProblem
from pina.operators import laplacian, grad, div
from pina import Condition, Span, LabelTensor
from pina import Condition, LabelTensor
from pina.geometry import CartesianDomain
from pina.equation import SystemEquation, Equation
# ===================================================== #
# #
@@ -21,7 +23,7 @@ class Stokes(SpatialProblem):
# assign output/ spatial variables
output_variables = ['ux', 'uy', 'p']
spatial_domain = Span({'x': [-2, 2], 'y': [-1, 1]})
spatial_domain = CartesianDomain({'x': [-2, 2], 'y': [-1, 1]})
# define the momentum equation
def momentum(input_, output_):
@@ -49,17 +51,9 @@ class Stokes(SpatialProblem):
# problem condition statement
conditions = {
'gamma_top': Condition(location=Span({'x': [-2, 2], 'y': 1}), function=wall),
'gamma_bot': Condition(location=Span({'x': [-2, 2], 'y': -1}), function=wall),
'gamma_out': Condition(location=Span({'x': 2, 'y': [-1, 1]}), function=outlet),
'gamma_in': Condition(location=Span({'x': -2, 'y': [-1, 1]}), function=inlet),
'D1': Condition(location=Span({'x': [-2, 2], 'y': [-1, 1]}), function=momentum),
'D2': Condition(location=Span({'x': [-2, 2], 'y': [-1, 1]}), function=continuity),
'gamma_top': Condition(location=CartesianDomain({'x': [-2, 2], 'y': 1}), equation=Equation(wall)),
'gamma_bot': Condition(location=CartesianDomain({'x': [-2, 2], 'y': -1}), equation=Equation(wall)),
'gamma_out': Condition(location=CartesianDomain({'x': 2, 'y': [-1, 1]}), equation=Equation(outlet)),
'gamma_in': Condition(location=CartesianDomain({'x': -2, 'y': [-1, 1]}), equation=Equation(inlet)),
'D': Condition(location=CartesianDomain({'x': [-2, 2], 'y': [-1, 1]}), equation=SystemEquation([momentum, continuity]))
}
# conditions = {
# 'gamma_top': Condition(location=Span({'x': [-2, 2], 'y': 1}), function=wall),
# 'gamma_bot': Condition(location=Span({'x': [-2, 2], 'y': -1}), function=wall),
# 'gamma_out': Condition(location=Span({'x': 2, 'y': [-1, 1]}), function=outlet),
# 'gamma_in': Condition(location=Span({'x': -2, 'y': [-1, 1]}), function=inlet),
# 'D': Condition(location=Span({'x': [-2, 2], 'y': [-1, 1]}), function=[momentum, continuity]),
# }

57
examples/problems/wave.py Normal file
View File

@@ -0,0 +1,57 @@
""" Wave equation Problem """
import torch
from pina.geometry import CartesianDomain
from pina import Condition
from pina.problem import SpatialProblem, TimeDependentProblem
from pina.operators import laplacian, grad
from pina.equation import FixedValue, Equation
# ===================================================== #
# #
# This script implements the two dimensional #
# Wave equation. The Wave class is defined inheriting #
# from SpatialProblem and TimeDependentProblem. Let #
# u --> field variable #
# x,y --> spatial variables #
# t --> temporal variables #
# the velocity coefficient is set to one. #
# #
# ===================================================== #
class Wave(TimeDependentProblem, SpatialProblem):
output_variables = ['u']
spatial_domain = CartesianDomain({'x': [0, 1], 'y': [0, 1]})
temporal_domain = CartesianDomain({'t': [0, 1]})
def wave_equation(input_, output_):
u_t = grad(output_, input_, components=['u'], d=['t'])
u_tt = grad(u_t, input_, components=['dudt'], d=['t'])
nabla_u = laplacian(output_, input_, components=['u'], d=['x', 'y'])
return nabla_u - u_tt
def initial_condition(input_, output_):
u_expected = (torch.sin(torch.pi*input_.extract(['x'])) *
torch.sin(torch.pi*input_.extract(['y'])))
return output_.extract(['u']) - u_expected
conditions = {
'gamma1': Condition(location=CartesianDomain({'x': [0, 1], 'y': 1, 't': [0, 1]}), equation=FixedValue(0.)),
'gamma2': Condition(location=CartesianDomain({'x': [0, 1], 'y': 0, 't': [0, 1]}), equation=FixedValue(0.)),
'gamma3': Condition(location=CartesianDomain({'x': 1, 'y': [0, 1], 't': [0, 1]}), equation=FixedValue(0.)),
'gamma4': Condition(location=CartesianDomain({'x': 0, 'y': [0, 1], 't': [0, 1]}), equation=FixedValue(0.)),
't0': Condition(location=CartesianDomain({'x': [0, 1], 'y': [0, 1], 't': 0}), equation=Equation(initial_condition)),
'D': Condition(location=CartesianDomain({'x': [0, 1], 'y': [0, 1], 't': [0, 1]}), equation=Equation(wave_equation)),
}
def wave_sol(self, pts):
sqrt_2 = torch.sqrt(torch.tensor(2.))
return (torch.sin(torch.pi*pts.extract(['x'])) *
torch.sin(torch.pi*pts.extract(['y'])) *
torch.cos(sqrt_2*torch.pi*pts.extract(['t'])))
truth_solution = wave_sol