Documentation for v0.1 version (#199)

* Adding Equations, solving typos
* improve _code.rst
* the team rst and restuctore index.rst
* fixing errors

---------

Co-authored-by: Dario Coscia <dariocoscia@dhcp-015.eduroam.sissa.it>
This commit is contained in:
Dario Coscia
2023-11-08 14:39:00 +01:00
committed by Nicola Demo
parent 3f9305d475
commit 8b7b61b3bd
144 changed files with 2741 additions and 1766 deletions

View File

@@ -27,7 +27,7 @@ class AbstractProblem(metaclass=ABCMeta):
# put in self.input_pts all the points that we don't need to sample
self._span_condition_points()
@property
def input_variables(self):
"""
@@ -55,10 +55,11 @@ class AbstractProblem(metaclass=ABCMeta):
def domain(self):
"""
The domain(s) where the conditions of the AbstractProblem are valid.
If more than one domain type is passed, a list of Location is
retured.
:return: the domain(s) of self
:rtype: list (if more than one domain are defined),
`Span` domain (of only one domain is defined)
:return: the domain(s) of ``self``
:rtype: list[Location]
"""
domains = [
getattr(self, f'{t}_domain')
@@ -109,7 +110,11 @@ class AbstractProblem(metaclass=ABCMeta):
self.input_pts[condition_name] = samples
self._have_sampled_points[condition_name] = True
def discretise_domain(self, n, mode = 'random', variables = 'all', locations = 'all'):
def discretise_domain(self,
n,
mode='random',
variables='all',
locations='all'):
"""
Generate a set of points to span the `Location` of all the conditions of
the problem.
@@ -122,9 +127,9 @@ class AbstractProblem(metaclass=ABCMeta):
latin hypercube sampling, ``latin`` or ``lh``;
chebyshev sampling, ``chebyshev``; grid sampling ``grid``.
:param variables: problem's variables to be sampled, defaults to 'all'.
:type variables: str or list[str], optional
:type variables: str | list[str]
:param locations: problem's locations from where to sample, defaults to 'all'.
:type locations: str, optional
:type locations: str
:Example:
>>> pinn.discretise_domain(n=10, mode='grid')
@@ -146,24 +151,24 @@ class AbstractProblem(metaclass=ABCMeta):
check_consistency(mode, str)
if mode not in ['random', 'grid', 'lh', 'chebyshev', 'latin']:
raise TypeError(f'mode {mode} not valid.')
# check consistency variables
if variables == 'all':
variables = self.input_variables
else:
check_consistency(variables, str)
if sorted(variables) != sorted(self.input_variables):
if sorted(variables) != sorted(self.input_variables):
TypeError(f'Wrong variables for sampling. Variables ',
f'should be in {self.input_variables}.')
# check consistency location
if locations == 'all':
locations = [condition for condition in self.conditions]
else:
check_consistency(locations, str)
if sorted(locations) != sorted(self.conditions):
if sorted(locations) != sorted(self.conditions):
TypeError(f'Wrong locations for sampling. Location ',
f'should be in {self.conditions}.')
@@ -174,7 +179,7 @@ class AbstractProblem(metaclass=ABCMeta):
# we try to check if we have already sampled
try:
already_sampled = [self.input_pts[location]]
# if we have not sampled, a key error is thrown
# if we have not sampled, a key error is thrown
except KeyError:
already_sampled = []
@@ -187,16 +192,15 @@ class AbstractProblem(metaclass=ABCMeta):
self._have_sampled_points[location] = False
# build samples
samples = [condition.location.sample(
n=n,
mode=mode,
variables=variables)
] + already_sampled
samples = [
condition.location.sample(n=n, mode=mode, variables=variables)
] + already_sampled
pts = merge_tensors(samples)
self.input_pts[location] = pts
# the condition is sampled if input_pts contains all labels
if sorted(self.input_pts[location].labels) == sorted(self.input_variables):
if sorted(self.input_pts[location].labels) == sorted(
self.input_variables):
self._have_sampled_points[location] = True
def add_points(self, new_points):
@@ -207,21 +211,22 @@ class AbstractProblem(metaclass=ABCMeta):
and values the torch.Tensor points.
"""
if sorted(new_points.keys()) != sorted(self.conditions):
if sorted(new_points.keys()) != sorted(self.conditions):
TypeError(f'Wrong locations for new points. Location ',
f'should be in {self.conditions}.')
for location in new_points.keys():
# extract old and new points
old_pts = self.input_pts[location]
new_pts = new_points[location]
# if they don't have the same variables error
if sorted(old_pts.labels) != sorted(new_pts.labels):
if sorted(old_pts.labels) != sorted(new_pts.labels):
TypeError(f'Not matching variables for old and new points '
f'in condition {location}.')
if old_pts.labels != new_pts.labels:
new_pts = torch.hstack([new_pts.extract([i]) for i in old_pts.labels])
new_pts = torch.hstack(
[new_pts.extract([i]) for i in old_pts.labels])
new_pts.labels = old_pts.labels
# merging
@@ -233,13 +238,14 @@ class AbstractProblem(metaclass=ABCMeta):
def have_sampled_points(self):
"""
Check if all points for
``'Location'`` are sampled.
"""
``Location`` are sampled.
"""
return all(self._have_sampled_points.values())
@property
def not_sampled_points(self):
"""Check which points are
"""
Check which points are
not sampled.
"""
# variables which are not sampled
@@ -251,4 +257,3 @@ class AbstractProblem(metaclass=ABCMeta):
if not is_sample:
not_sampled.append(condition_name)
return not_sampled

View File

@@ -16,14 +16,17 @@ class ParametricProblem(AbstractProblem):
:Example:
>>> from pina.problem import SpatialProblem, ParametricProblem
>>> from pina.operators import grad
>>> from pina import Condition, Span
>>> from pina.equations import Equation, FixedValue
>>> from pina import Condition
>>> from pina.geometry import CartesianDomain
>>> import torch
>>>
>>>
>>> class ParametricODE(SpatialProblem, ParametricProblem):
>>>
>>> output_variables = ['u']
>>> spatial_domain = Span({'x': [0, 1]})
>>> parameter_domain = Span({'alpha': [1, 10]})
>>> spatial_domain = CartesianDomain({'x': [0, 1]})
>>> parameter_domain = CartesianDomain({'alpha': [1, 10]})
>>>
>>> def ode_equation(input_, output_):
>>> u_x = grad(output_, input_, components=['u'], d=['x'])
@@ -31,14 +34,9 @@ class ParametricProblem(AbstractProblem):
>>> alpha = input_.extract(['alpha'])
>>> return alpha * u_x - u
>>>
>>> def initial_condition(input_, output_):
>>> value = 1.0
>>> u = output_.extract(['u'])
>>> return u - value
>>>
>>> conditions = {
>>> 'x0': Condition(Span({'x': 0, 'alpha':[1, 10]}), initial_condition),
>>> 'D': Condition(Span({'x': [0, 1], 'alpha':[1, 10]}), ode_equation)}
>>> 'x0': Condition(CartesianDomain({'x': 0, 'alpha':[1, 10]}), FixedValue(1.)),
>>> 'D': Condition(CartesianDomain({'x': [0, 1], 'alpha':[1, 10]}), Equation(ode_equation))}
"""
@abstractmethod

View File

@@ -14,24 +14,25 @@ class SpatialProblem(AbstractProblem):
:Example:
>>> from pina.problem import SpatialProblem
>>> from pina.operators import grad
>>> from pina import Condition, Span
>>> from pina.equations import Equation, FixedValue
>>> from pina import Condition
>>> from pina.geometry import CartesianDomain
>>> import torch
>>> class SimpleODE(SpatialProblem):
>>>
>>>
>>> class SpatialODE(SpatialProblem:
>>>
>>> output_variables = ['u']
>>> spatial_domain = Span({'x': [0, 1]})
>>> spatial_domain = CartesianDomain({'x': [0, 1]})
>>>
>>> def ode_equation(input_, output_):
>>> u_x = grad(output_, input_, components=['u'], d=['x'])
>>> u = output_.extract(['u'])
>>> return u_x - u
>>>
>>> def initial_condition(input_, output_):
>>> value = 1.0
>>> u = output_.extract(['u'])
>>> return u - value
>>>
>>> conditions = {
>>> 'x0': Condition(Span({'x': 0.}), initial_condition),
>>> 'D': Condition(Span({'x': [0, 1]}), ode_equation)}
>>> 'x0': Condition(CartesianDomain({'x': 0, 'alpha':[1, 10]}), FixedValue(1.)),
>>> 'D': Condition(CartesianDomain({'x': [0, 1], 'alpha':[1, 10]}), Equation(ode_equation))}
"""

View File

@@ -14,14 +14,17 @@ class TimeDependentProblem(AbstractProblem):
:Example:
>>> from pina.problem import SpatialProblem, TimeDependentProblem
>>> from pina.operators import grad, laplacian
>>> from pina import Condition, Span
>>> from pina.equations import Equation, FixedValue
>>> from pina import Condition
>>> from pina.geometry import CartesianDomain
>>> import torch
>>>
>>>
>>> class Wave(TimeDependentSpatialProblem):
>>>
>>> output_variables = ['u']
>>> spatial_domain = Span({'x': [0, 3]})
>>> temporal_domain = Span({'t': [0, 1]})
>>> spatial_domain = CartesianDomain({'x': [0, 3]})
>>> temporal_domain = CartesianDomain({'t': [0, 1]})
>>>
>>> def wave_equation(input_, output_):
>>> u_t = grad(output_, input_, components=['u'], d=['t'])
@@ -29,10 +32,6 @@ class TimeDependentProblem(AbstractProblem):
>>> delta_u = laplacian(output_, input_, components=['u'], d=['x'])
>>> return delta_u - u_tt
>>>
>>> def nil_dirichlet(input_, output_):
>>> value = 0.0
>>> return output_.extract(['u']) - value
>>>
>>> def initial_condition(input_, output_):
>>> u_expected = (-3*torch.sin(2*torch.pi*input_.extract(['x']))
>>> + 5*torch.sin(8/3*torch.pi*input_.extract(['x'])))
@@ -40,10 +39,10 @@ class TimeDependentProblem(AbstractProblem):
>>> return u - u_expected
>>>
>>> conditions = {
>>> 't0': Condition(Span({'x': [0, 3], 't':0}), initial_condition),
>>> 'gamma1': Condition(Span({'x':0, 't':[0, 1]}), nil_dirichlet),
>>> 'gamma2': Condition(Span({'x':3, 't':[0, 1]}), nil_dirichlet),
>>> 'D': Condition(Span({'x': [0, 3], 't':[0, 1]}), wave_equation)}
>>> 't0': Condition(CartesianDomain({'x': [0, 3], 't':0}), Equation(initial_condition)),
>>> 'gamma1': Condition(CartesianDomain({'x':0, 't':[0, 1]}), FixedValue(0.)),
>>> 'gamma2': Condition(CartesianDomain({'x':3, 't':[0, 1]}), FixedValue(0.)),
>>> 'D': Condition(CartesianDomain({'x': [0, 3], 't':[0, 1]}), Equation(wave_equation))}
"""