correlated_fields_simple.py 4.44 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 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/>.
#
# Copyright(C) 2013-2020 Max-Planck-Society
Philipp Arras's avatar
Philipp Arras committed
15
# Author: Philipp Arras
16
17
18
19
20
21
22
23
24
25
#
# NIFTy is being developed at the Max-Planck-Institut fuer Astrophysik.

import numpy as np

from ..domains.power_space import PowerSpace
from ..operators.adder import Adder
from ..operators.contraction_operator import ContractionOperator
from ..operators.distributors import PowerDistributor
from ..operators.harmonic_operators import HarmonicTransformOperator
Philipp Arras's avatar
Philipp Arras committed
26
from ..operators.normal_operators import LognormalTransform, NormalTransform
Philipp Arras's avatar
Philipp Arras committed
27
from .correlated_fields import _TwoLogIntegrations
28
29
from ..operators.operator import Operator
from ..operators.simple_linear_operators import ducktape
Philipp Arras's avatar
Philipp Arras committed
30
31
from ..operators.value_inserter import ValueInserter
from ..sugar import full, makeField, makeOp
Philipp Arras's avatar
Philipp Arras committed
32
from .correlated_fields import (_log_vol, _Normalization,
Philipp Arras's avatar
Philipp Arras committed
33
34
35
                                _relative_log_k_lengths, _SlopeRemover)


Philipp Arras's avatar
Philipp Arras committed
36
class SimpleCorrelatedField(Operator):
Philipp Arras's avatar
Philipp Arras committed
37
38
39
40
    def __init__(self, target, offset_mean, offset_std_mean, offset_std_std,
                 fluctuations_mean, fluctuations_stddev, flexibility_mean,
                 flexibility_stddev, asperity_mean, asperity_stddev,
                 loglogavgslope_mean, loglogavgslope_stddev, prefix='',
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
                 harmonic_partner=None):
        if harmonic_partner is None:
            harmonic_partner = target.get_default_codomain()
        else:
            target.check_codomain(harmonic_partner)
            harmonic_partner.check_codomain(target)
        fluct = LognormalTransform(fluctuations_mean, fluctuations_stddev,
                                   prefix + 'fluctuations', 0)
        flex = LognormalTransform(flexibility_mean, flexibility_stddev,
                                  prefix + 'flexibility', 0)
        asp = LognormalTransform(asperity_mean, asperity_stddev,
                                 prefix + 'asperity', 0)
        avgsl = NormalTransform(loglogavgslope_mean, loglogavgslope_stddev,
                                prefix + 'loglogavgslope', 0)
        zm = LognormalTransform(offset_std_mean, offset_std_std,
                                prefix + 'zeromode', 0)
Philipp Arras's avatar
Philipp Arras committed
57

Philipp Arras's avatar
Philipp Arras committed
58
59
        pspace = PowerSpace(harmonic_partner)
        twolog = _TwoLogIntegrations(pspace)
Philipp Arras's avatar
Philipp Arras committed
60
61
        dom = twolog.domain[0]
        vflex = np.zeros(dom.shape)
Philipp Arras's avatar
Philipp Arras committed
62
63
        vasp = np.zeros(dom.shape)
        shift = np.ones(dom.shape)
Philipp Arras's avatar
Philipp Arras committed
64
        vflex[0] = vflex[1] = np.sqrt(_log_vol(pspace))
Philipp Arras's avatar
Philipp Arras committed
65
        vasp[0] = 1
Philipp Arras's avatar
Philipp Arras committed
66
        shift[0] = _log_vol(pspace)**2/12.
Philipp Arras's avatar
Philipp Arras committed
67
68
        vflex = makeOp(makeField(dom, vflex))
        vasp = makeOp(makeField(dom, vasp))
Philipp Arras's avatar
Philipp Arras committed
69
        shift = makeField(dom, shift)
Philipp Arras's avatar
Philipp Arras committed
70
        vslope = makeOp(makeField(pspace, _relative_log_k_lengths(pspace)))
Philipp Arras's avatar
Philipp Arras committed
71
72

        expander = ContractionOperator(twolog.domain, 0).adjoint
Philipp Arras's avatar
Philipp Arras committed
73
        ps_expander = ContractionOperator(pspace, 0).adjoint
Philipp Arras's avatar
Philipp Arras committed
74
75
76
77
        slope = vslope @ ps_expander @ avgsl
        sig_flex = vflex @ expander @ flex
        sig_asp = vasp @ expander @ asp
        xi = ducktape(dom, None, prefix + 'spectrum')
Philipp Arras's avatar
Philipp Arras committed
78
        smooth = xi*sig_flex*(Adder(shift) @ sig_asp).ptw("sqrt")
Philipp Arras's avatar
Philipp Arras committed
79
        smooth = _SlopeRemover(pspace, 0) @ twolog @ smooth
Philipp Arras's avatar
Philipp Arras committed
80
        a = _Normalization(pspace, 0) @ (slope + smooth)
Philipp Arras's avatar
Philipp Arras committed
81

Philipp Arras's avatar
Philipp Arras committed
82
        maskzm = np.ones(pspace.shape)
Philipp Arras's avatar
Philipp Arras committed
83
        maskzm[0] = 0
Philipp Arras's avatar
Philipp Arras committed
84
85
        maskzm = makeOp(makeField(pspace, maskzm))
        insert = ValueInserter(pspace, (0,))
Philipp Arras's avatar
Philipp Arras committed
86
        a = (maskzm @ ((ps_expander @ fluct)*a)) + insert(zm)
Philipp Arras's avatar
Philipp Arras committed
87
        self._a = a.scale(target.total_volume)
Philipp Arras's avatar
Philipp Arras committed
88

89
        ht = HarmonicTransformOperator(harmonic_partner, target)
Philipp Arras's avatar
Philipp Arras committed
90
        pd = PowerDistributor(harmonic_partner, pspace)
Philipp Arras's avatar
Philipp Arras committed
91
        xi = ducktape(harmonic_partner, None, prefix + 'xi')
Philipp Arras's avatar
Philipp Arras committed
92
        op = ht(pd(self._a)*xi)
93
        if offset_mean is not None:
Philipp Arras's avatar
Philipp Arras committed
94
95
96
97
            op = Adder(full(op.target, float(offset_mean))) @ op
        self.apply = op.apply
        self._domain = op.domain
        self._target = op.target
98
99
100
101

    @property
    def amplitude(self):
        return self._a