There is a maintenance of MPCDF Gitlab on Thursday, April 22st 2020, 9:00 am CEST - Expect some service interruptions during this time

correlated_fields.py 3.76 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.
Philipp Arras's avatar
Philipp Arras committed
17

18 19
from functools import reduce

Philipp Arras's avatar
Philipp Arras committed
20
from ..domain_tuple import DomainTuple
21
from ..operators.contraction_operator import ContractionOperator
Philipp Arras's avatar
Philipp Arras committed
22
from ..operators.distributors import PowerDistributor
Martin Reinecke's avatar
Martin Reinecke committed
23
from ..operators.harmonic_operators import HarmonicTransformOperator
Martin Reinecke's avatar
Martin Reinecke committed
24
from ..operators.simple_linear_operators import ducktape
Martin Reinecke's avatar
Martin Reinecke committed
25

Martin Reinecke's avatar
Martin Reinecke committed
26

27 28 29 30 31 32 33 34 35 36
def CorrelatedField(target, amplitude_operator, name='xi'):
    '''Constructs operator which turns white Gaussian excitation fields into a
    correlated field.

    This function returns an operator which implements:

        ht @ (vol * A * xi),

    where `ht` is a harmonic transform operator, `A` is the sqare root of the
    prior covariance an `xi` is the excitation field.
37 38 39

    Parameters
    ----------
40 41 42
    target : Domain, DomainTuple or tuple of Domain
        Target of the operator. Is not allowed to be a DomainTuple with more
        than one space.
Philipp Arras's avatar
Philipp Arras committed
43
    amplitude_operator: Operator
44
    name : string
45 46 47 48 49
        :class:`MultiField` key for xi-field.

    Returns
    -------
    Correlated field : Operator
50
    '''
51 52 53 54 55
    tgt = DomainTuple.make(target)
    if len(tgt) > 1:
        raise ValueError
    h_space = tgt[0].get_default_codomain()
    ht = HarmonicTransformOperator(h_space, tgt[0])
Philipp Arras's avatar
Philipp Arras committed
56
    p_space = amplitude_operator.target[0]
Martin Reinecke's avatar
Martin Reinecke committed
57
    power_distributor = PowerDistributor(h_space, p_space)
Philipp Arras's avatar
Philipp Arras committed
58
    A = power_distributor(amplitude_operator)
59 60
    vol = h_space.scalar_dvol**-0.5
    return ht(vol*A*ducktape(h_space, None, name))
61 62


63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83
def MfCorrelatedField(target, amplitudes, name='xi'):
    '''Constructs operator which turns white Gaussian excitation fields into a
    correlated field defined on a DomainTuple with two entries and two separate
    correlation structures.

    This operator may be used as model for multi-frequency reconstructions
    with a correlation structure in both spatial and energy direction.

    Parameters
    ----------
    target : Domain, DomainTuple or tuple of Domain
        Target of the operator. Is not allowed to be a DomainTuple with more
        than one space.
    amplitudes: iterable of Operator
        List of two amplitude operators.
    name : string
        :class:`MultiField` key for xi-field.

    Returns
    -------
    Correlated field : Operator
84
    '''
85 86 87 88 89
    tgt = DomainTuple.make(target)
    if len(tgt) != 2:
        raise ValueError
    if len(amplitudes) != 2:
        raise ValueError
90

91 92 93 94
    hsp = DomainTuple.make([tt.get_default_codomain() for tt in tgt])
    ht1 = HarmonicTransformOperator(hsp, target=tgt[0], space=0)
    ht2 = HarmonicTransformOperator(ht1.target, space=1)
    ht = ht2 @ ht1
95

96 97 98 99
    psp = [aa.target[0] for aa in amplitudes]
    pd0 = PowerDistributor(hsp, psp[0], 0)
    pd1 = PowerDistributor(pd0.domain, psp[1], 1)
    pd = pd0 @ pd1
100

101 102 103
    dd0 = ContractionOperator(pd.domain, 1).adjoint
    dd1 = ContractionOperator(pd.domain, 0).adjoint
    d = [dd0, dd1]
104

105 106 107 108 109
    a = [dd @ amplitudes[ii] for ii, dd in enumerate(d)]
    a = reduce(lambda x, y: x*y, a)
    A = pd @ a
    vol = reduce(lambda x, y: x*y, [sp.scalar_dvol**-0.5 for sp in hsp])
    return ht(vol*A*ducktape(hsp, None, name))