symmetrizing_operator.py 2.17 KB
Newer Older
Martin Reinecke's avatar
Martin Reinecke committed
1
2
3
4
5
6
7
8
9
10
11
12
13
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
#
14
# Copyright(C) 2013-2019 Max-Planck-Society
Martin Reinecke's avatar
Martin Reinecke committed
15
#
16
# NIFTy is being developed at the Max-Planck-Institut fuer Astrophysik.
Martin Reinecke's avatar
Martin Reinecke committed
17

Philipp Arras's avatar
Philipp Arras committed
18
from .. import dobj, utilities
19
from ..domain_tuple import DomainTuple
20
from ..domains.log_rg_space import LogRGSpace
21
22
23
24
25
from ..field import Field
from .endomorphic_operator import EndomorphicOperator


class SymmetrizingOperator(EndomorphicOperator):
26
    """Subtracts the field axes-wise in reverse order from itself. The slice of
Philipp Arras's avatar
Docs  
Philipp Arras committed
27
28
29
30
31
32
33
34
35
    all elements with at least one index being zero is not touched.

    Parameters
    ----------
    domain : Domain, DomainTuple or tuple of Domain
        Domain of the operator. `domain[space]` needs to be a non-harmonic
        :class:`LogRGSpace`.
    space : int
        Index of space in domain on which the operator shall act. Default is 0.
36
    """
Martin Reinecke's avatar
Martin Reinecke committed
37
    def __init__(self, domain, space=0):
38
        self._domain = DomainTuple.make(domain)
Martin Reinecke's avatar
Martin Reinecke committed
39
        self._capability = self.TIMES | self.ADJOINT_TIMES
40
        self._space = utilities.infer_space(self._domain, space)
Martin Reinecke's avatar
Martin Reinecke committed
41
42
        dom = self._domain[self._space]
        if not (isinstance(dom, LogRGSpace) and not dom.harmonic):
43
            raise TypeError("nonharmonic LogRGSpace needed")
44
45
46

    def apply(self, x, mode):
        self._check_input(x, mode)
Martin Reinecke's avatar
Martin Reinecke committed
47
        v = x.val.copy()
Martin Reinecke's avatar
Martin Reinecke committed
48
        for i in self._domain.axes[self._space]:
49
            lead = (slice(None),)*i
Martin Reinecke's avatar
Martin Reinecke committed
50
51
            v, loc = dobj.ensure_not_distributed(v, (i,))
            loc[lead+(slice(1, None),)] -= loc[lead+(slice(None, 0, -1),)]
52
            loc /= 2
Martin Reinecke's avatar
Martin Reinecke committed
53
        return Field(self.target, dobj.ensure_default_distributed(v))