* solvers -> solver * adaptive_functions -> adaptive_function * callbacks -> callback * operators -> operator * pinns -> physics_informed_solver * layers -> block
85 lines
2.9 KiB
Python
85 lines
2.9 KiB
Python
"""Module for the ParametricProblem class"""
|
|
import torch
|
|
from abc import abstractmethod
|
|
from .abstract_problem import AbstractProblem
|
|
|
|
|
|
class InverseProblem(AbstractProblem):
|
|
"""
|
|
The class for the definition of inverse problems, i.e., problems
|
|
with unknown parameters that have to be learned during the training process
|
|
from given data.
|
|
|
|
Here's an example of a spatial inverse ODE problem, i.e., a spatial
|
|
ODE problem with an unknown parameter `alpha` as coefficient of the
|
|
derivative term.
|
|
|
|
:Example:
|
|
>>> from pina.problem import SpatialProblem, InverseProblem
|
|
>>> from pina.operator import grad
|
|
>>> from pina.equation import ParametricEquation, FixedValue
|
|
>>> from pina import Condition
|
|
>>> from pina.geometry import CartesianDomain
|
|
>>> import torch
|
|
>>>
|
|
>>> class InverseODE(SpatialProblem, InverseProblem):
|
|
>>>
|
|
>>> output_variables = ['u']
|
|
>>> spatial_domain = CartesianDomain({'x': [0, 1]})
|
|
>>> unknown_parameter_domain = CartesianDomain({'alpha': [1, 10]})
|
|
>>>
|
|
>>> def ode_equation(input_, output_, params_):
|
|
>>> u_x = grad(output_, input_, components=['u'], d=['x'])
|
|
>>> u = output_.extract(['u'])
|
|
>>> return params_.extract(['alpha']) * u_x - u
|
|
>>>
|
|
>>> def solution_data(input_, output_):
|
|
>>> x = input_.extract(['x'])
|
|
>>> solution = torch.exp(x)
|
|
>>> return output_ - solution
|
|
>>>
|
|
>>> conditions = {
|
|
>>> 'x0': Condition(CartesianDomain({'x': 0}), FixedValue(1.0)),
|
|
>>> 'D': Condition(CartesianDomain({'x': [0, 1]}), ParametricEquation(ode_equation)),
|
|
>>> 'data': Condition(CartesianDomain({'x': [0, 1]}), Equation(solution_data))
|
|
"""
|
|
|
|
def __init__(self):
|
|
super().__init__()
|
|
# storing unknown_parameters for optimization
|
|
self.unknown_parameters = {}
|
|
for i, var in enumerate(self.unknown_variables):
|
|
range_var = self.unknown_parameter_domain.range_[var]
|
|
tensor_var = (
|
|
torch.rand(1, requires_grad=True) * range_var[1]
|
|
+ range_var[0]
|
|
)
|
|
self.unknown_parameters[var] = torch.nn.Parameter(
|
|
tensor_var
|
|
)
|
|
|
|
@abstractmethod
|
|
def unknown_parameter_domain(self):
|
|
"""
|
|
The parameters' domain of the problem.
|
|
"""
|
|
pass
|
|
|
|
@property
|
|
def unknown_variables(self):
|
|
"""
|
|
The parameters of the problem.
|
|
"""
|
|
return self.unknown_parameter_domain.variables
|
|
|
|
@property
|
|
def unknown_parameters(self):
|
|
"""
|
|
The parameters of the problem.
|
|
"""
|
|
return self.__unknown_parameters
|
|
|
|
@unknown_parameters.setter
|
|
def unknown_parameters(self, value):
|
|
self.__unknown_parameters = value
|