operator.py 3.09 KB
Newer Older
Martin Reinecke's avatar
Martin Reinecke committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
from __future__ import absolute_import, division, print_function

import abc

import numpy as np

from .compat import *
from .utilities import NiftyMetaBase
#from ..domain_tuple import DomainTuple
#from ..multi.multi_domain import MultiDomain
from .field import Field
from .multi.multi_field import MultiField


class Linearization(object):
    def __init__(self, val, jac):
        self._val = val
        self._jac = jac

    @property
    def domain(self):
        return self._jac.domain

    @property
    def target(self):
        return self._jac.target

    @property
    def val(self):
        return self._val

    @property
    def jac(self):
        return self._jac

    def __neg__(self):
        return Linearization(-self._val, self._jac*(-1))

    def __add__(self, other):
        if isinstance(other, Linearization):
Martin Reinecke's avatar
more    
Martin Reinecke committed
41
42
43
44
            from .operators.relaxed_sum_operator import RelaxedSumOperator
            return Linearization(
                MultiField.combine((self._val, other._val)),
                RelaxedSumOperator((self._jac, other._jac)))
Martin Reinecke's avatar
Martin Reinecke committed
45
46
47
48
49
50
51
52
53
54
55
56
57
        if isinstance(other, (int, float, complex, Field, MultiField)):
            return Linearization(self._val+other, self._jac)

    def __radd__(self, other):
        return self.__add__(other)

    def __sub__(self, other):
        return self.__add__(-other)

    def __rsub__(self, other):
        return (-self).__add__(other)

    def __mul__(self, other):
Martin Reinecke's avatar
more    
Martin Reinecke committed
58
        from .sugar import makeOp
Martin Reinecke's avatar
Martin Reinecke committed
59
        if isinstance(other, Linearization):
Martin Reinecke's avatar
more    
Martin Reinecke committed
60
61
            d1 = makeOp(self._val)
            d2 = makeOp(other._val)
Martin Reinecke's avatar
Martin Reinecke committed
62
63
64
65
66
67
68
            return Linearization(self._val*other._val,
                                 self._jac*d2 + d1*other._jac)
        if isinstance(other, (int, float, complex)):
            #if other == 0:
            #    return ...
            return Linearization(self._val*other, self._jac*other)
        if isinstance(other, (Field, MultiField)):
Martin Reinecke's avatar
more    
Martin Reinecke committed
69
            d2 = makeOp(other)
Martin Reinecke's avatar
Martin Reinecke committed
70
71
72
73
            return Linearization(self._val*other, self._jac*d2)
        raise TypeError

    def __rmul__(self, other):
Martin Reinecke's avatar
more    
Martin Reinecke committed
74
        from .sugar import makeOp
Martin Reinecke's avatar
Martin Reinecke committed
75
76
77
        if isinstance(other, (int, float, complex)):
            return Linearization(self._val*other, self._jac*other)
        if isinstance(other, (Field, MultiField)):
Martin Reinecke's avatar
more    
Martin Reinecke committed
78
            d1 = makeOp(other)
Martin Reinecke's avatar
Martin Reinecke committed
79
80
81
82
            return Linearization(self._val*other, d1*self._jac)

    @staticmethod
    def make_var(field):
Martin Reinecke's avatar
Martin Reinecke committed
83
        from .operators.scaling_operator import ScalingOperator
Martin Reinecke's avatar
Martin Reinecke committed
84
85
86
        return Linearization(field, ScalingOperator(1., field.domain))
    @staticmethod
    def make_const(field):
Martin Reinecke's avatar
more    
Martin Reinecke committed
87
88
        from .operators.null_operator import NullOperator
        return Linearization(field, NullOperator({}, field.domain))
Martin Reinecke's avatar
Martin Reinecke committed
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108

class Operator(NiftyMetaBase()):
    """Transforms values living on one domain into values living on another
    domain, and can also provide the Jacobian.
    """

    def __call__(self, x):
        """Returns transformed x

        Parameters
        ----------
        x : Linearization
            input

        Returns
        -------
        Linearization
            output
        """
        raise NotImplementedError