gwinc.py 8.33 KB
Newer Older
1
from __future__ import division
Christopher Wipf's avatar
Christopher Wipf committed
2
import numpy as np
3
from numpy import pi, sqrt
4
from collections import OrderedDict
5
import logging
6

7
from .precomp import precompIFO
8
from . import noise
9
from .plot import plot_noise
10 11 12 13 14


def noise_calc(ifo, f):
    """Calculate all IFO noises and return as dict

Jameson Graef Rollins's avatar
Jameson Graef Rollins committed
15 16
    Assumes ifo has already been run through precompIFO().

17
    """
18
    ##############################
Jameson Graef Rollins's avatar
Jameson Graef Rollins committed
19
    # suspension transfer function
20
    #
Jameson Graef Rollins's avatar
Jameson Graef Rollins committed
21
    # used in seismic and susptherm calculations
22 23
    ##############################

24
    noises = OrderedDict()
25 26

    noises['Quantum Vacuum'] = noise.quantum.shotrad(f, ifo)
27
    noises['Suspension Thermal']  = noise.suspensionthermal.susptherm(f, ifo)
28
    noises['Coating Brownian']  = noise.coatingthermal.coatbrownian(f, ifo)
29
    noises['Coating Thermo-Optic'] = noise.coatingthermal.thermooptic(f, ifo)
30
    noises['Substrate Thermo-Elastic']  = noise.substratethermal.subtherm(f, ifo)
31
    noises['Substrate Brownian']  = noise.substratethermal.subbrownian(f, ifo)
32
    noises['Seismic'] = noise.seismic.seismic(f, ifo)[0]
33 34
    noises['Newtonian Gravity']  = noise.newtonian.gravg(f, ifo)
    noises['Excess Gas']  = noise.residualgas.gas(f, ifo)
35 36

    # calc semiconductor noise sources
37
    if 'isSemiConductor' in ifo.Materials.Substrate and ifo.Materials.Substrate.isSemiConductor:
38 39 40 41 42 43 44
        noises['ITM Thermo-Refractive'] = noise.substratethermal.thermorefractiveITM(f, ifo)
        noises['ITM Carrier Density'] = noise.substratethermal.carrierdensity(f, ifo)

    # adjust noise curves for multiple bounces - for resonant delay lines
    # Brownian noise scales as Neff (correlation-corrected spot number)
    # Displacement noises scale as N^2
    # Thermo-optic noise scales as N (incoherent between spots)
45
    if 'NFolded' in ifo.Infrastructure:
46
        logging.info('FOLDED')
47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
        if ifo.Infrastructure.travellingWave:
            N = ifo.Infrastructure.NFolded
            sep_w = ifo.Infrastructure.DelayLineSpotSeparation
            Neff = getBrownianCorrelationFactor(N,sep_w) # not yet ported to python
            noises['Suspension Thermal'] *= N**2
            noises['Substrate Brownian'] *= Neff
            noises['Coating Brownian'] *= Neff
            noises['Substrate Thermo-Elastic'] *= N**2
            noises['Newtonian Gravity'] *= N**2
            noises['Seismic'] *= N**2
            noises['Coating Thermo-Optic'] *= N
        else:
            N = ifo.Infrastructure.NFolded
            sep_w = ifo.Infrastructure.DelayLineSpotSeparation
            Neff = getBrownianCorrelationFactorStandingWave(N,sep_w) # not yet ported to python
            Ndispl = (2*N-1)
            N_TO = 4*N-3 # use naive counting, needs improvement
            noises['Suspension Thermal'] *= Ndispl**2
            noises['Substrate Brownian'] *= Neff
            noises['Coating Brownian'] *= Neff
            noises['Substrate Thermo-Elastic'] *= Ndispl**2
            noises['Newtonian Gravity'] *= Ndispl**2
            noises['Seismic'] *= Ndispl**2
            noises['Coating Thermo-Optic'] *= N_TO
        #noises['Mirror Thermal'] = noises['Substrate Brownian'] + noises['Coating Brownian'] + \
72
        #                           noises['Substrate Thermo-Elastic'] + noises['Coating Thermo-Optic'] # total mirror thermal
73 74 75 76 77 78

    noises['Total'] = sum(noises[curve] for curve in noises)
    noises['Freq'] = f

    return noises

Christopher Wipf's avatar
Christopher Wipf committed
79

80
def gwinc(freq, ifoin, source=None, plot=False, PRfixed=True):
81 82 83 84 85 86 87 88 89 90
    """Calculate strain noise budget for a specified interferometer model.

    Argument `freq` is the frequency array for which the noises will
    be calculated, and `ifoin` is the IFO model (see the `load_ifo()`
    function).

    If `source` structure provided, so evaluates the sensitivity of
    the detector to several potential gravitational wave
    sources.

91
    If `plot` is True a plot of the budget will be created.
92 93 94 95

    Returns tuple of (score, noises, ifo)

    """
Christopher Wipf's avatar
Christopher Wipf committed
96
    # add some precomputed info to the ifo struct
97 98
    #this implicitly deepcopies and the return value is the copy
    ifo = precompIFO(freq, ifoin, PRfixed)
Christopher Wipf's avatar
Christopher Wipf committed
99 100

    pbs      = ifo.gwinc.pbs
101
    parm     = ifo.gwinc.parm
Christopher Wipf's avatar
Christopher Wipf committed
102 103 104 105 106 107
    finesse  = ifo.gwinc.finesse
    prfactor = ifo.gwinc.prfactor
    if ifo.Laser.Power * prfactor != pbs:
        pass
        #warning(['Thermal lensing limits input power to ' num2str(pbs/prfactor, 3) ' W']);

108
    noises = noise_calc(ifo, freq)
Christopher Wipf's avatar
Christopher Wipf committed
109

110 111
    #TODO decide if all this below this should remain, since it is already inside of __main__

112 113
    # report astrophysical scores if so desired
    score = None
Christopher Wipf's avatar
Christopher Wipf committed
114
    if source:
115 116
        score = int73(freq, noises['Total'], ifo, source)
        score.Omega = intStoch(freq, noises['Total'], 0, ifo, source)
Christopher Wipf's avatar
Christopher Wipf committed
117

118 119 120
    # --------------------------------------------------------
    # output graphics

121
    if plot:
122
        # Report input parameters
Christopher Wipf's avatar
Christopher Wipf committed
123 124
        if ifo.Optics.Type == 'DualCarrier_new':     #include the case for Dual carrier
            finesseA = 2*pi/ifo.Optics.ITM.TransmittanceD1
125
            finesseB = 2*pi/ifo.Optics.ITM.TransmittanceD2
Christopher Wipf's avatar
Christopher Wipf committed
126 127
            pbsA = ifo.Laser.PBSD1
            pbsB = ifo.Laser.PBSD2
128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143
            logging.info('Finesse for carrier A:  %7.2f' % finesseA)
            logging.info('Finesse for carrier B:  %7.2f' % finesseB)
            logging.info('Power Recycling Factor: %7.2f' % ifo.PRCgain)
            logging.info('Arm power for carrier A:%7.2f kW' % (finesseA*2/pi*pbsA/2/1000))
            logging.info('Arm power for carrier B:%7.2f kW' % (finesseB*2/pi*pbsB/2/1000))
            logging.info('Power on beam splitter for carrier A: %7.2f W' % pbsA)
            logging.info('Power on beam splitter for carrier B: %7.2f W' % pbsB)
            logging.info('Laser Power for Carrier A:     %7.2f Watt' % ifo.LP1)
            logging.info('Laser Power for Carrier B:     %7.2f Watt' % ifo.LP2)
            logging.info('SRM Detuning for Carrier A:    %7.2f degree' % (ifo.Optics.SRM.TunephaseD1*180/pi))
            logging.info('SRM Detuning for Carrier B:    %7.2f degree' % (ifo.Optics.SRM.TunephaseD2*180/pi))
            logging.info('SRM transmission for Carrier A:%9.4f' % ifo.Optics.SRM.TransmittanceD1)
            logging.info('SRM transmission for Carrier B:%9.4f' % ifo.Optics.SRM.TransmittanceD2)
            logging.info('ITM transmission for Carrier A:%9.4f' % ifo.Optics.ITM.TransmittanceD1)
            logging.info('ITM transmission for Carrier B:%9.4f' % ifo.Optics.ITM.TransmittanceD2)
            logging.info('PRM transmission for both:     %9.4f' % ifo.Optics.PRM.Transmittance)
Christopher Wipf's avatar
Christopher Wipf committed
144
        else:
145 146 147 148 149 150 151 152 153
            logging.info('Laser Power:            %7.2f Watt' % ifo.Laser.Power)
            logging.info('SRM Detuning:           %7.2f degree' % (ifo.Optics.SRM.Tunephase*180/pi))
            logging.info('SRM transmission:       %9.4f' % ifo.Optics.SRM.Transmittance)
            logging.info('ITM transmission:       %9.4f' % ifo.Optics.ITM.Transmittance)
            logging.info('PRM transmission:       %9.4f' % ifo.Optics.PRM.Transmittance)
            logging.info('Finesse:                %7.2f' % finesse)
            logging.info('Power Recycling Gain:   %7.2f' % prfactor)
            logging.info('Arm Power:              %7.2f kW' % (parm/1000))
            logging.info('Power on BS:            %7.2f W' % pbs)
Christopher Wipf's avatar
Christopher Wipf committed
154

155 156 157 158 159
        # coating and substrate thermal load on the ITM
        PowAbsITM = (pbs/2) * \
                    np.hstack([(finesse*2/pi) * ifo.Optics.ITM.CoatingAbsorption,
                               (2 * ifo.Materials.MassThickness) * ifo.Optics.ITM.SubstrateAbsorption])

160
        # Stefan's Mysterious TCS Section ~~~~ `~~ ` ` 324@#%@#$ !
Christopher Wipf's avatar
Christopher Wipf committed
161 162 163 164
        M = np.array([[ifo.TCS.s_cc, ifo.TCS.s_cs], [ifo.TCS.s_cs, ifo.TCS.s_ss]])
        S_uncorr = PowAbsITM.T*M*PowAbsITM
        TCSeff = 1-sqrt(ifo.TCS.SRCloss/S_uncorr)

165 166 167
        logging.info('Thermal load on ITM:    %8.3f W' % sum(PowAbsITM))
        logging.info('Thermal load on BS:     %8.3f W' %
                     (ifo.Materials.MassThickness*ifo.Optics.SubstrateAbsorption*pbs))
Christopher Wipf's avatar
Christopher Wipf committed
168
        if (ifo.Laser.Power*prfactor != pbs):
169
            logging.info('Lensing limited input power: %7.2f W' % (pbs/prfactor))
Christopher Wipf's avatar
Christopher Wipf committed
170 171

        if source:
172 173 174
            logging.info('BNS Inspiral Range:     ' + str(score.effr0ns) + ' Mpc/ z = ' + str(score.zHorizonNS))
            logging.info('BBH Inspiral Range:     ' + str(score.effr0bh) + ' Mpc/ z = ' + str(score.zHorizonBH))
            logging.info('Stochastic Omega: %4.1g Universes' % score.Omega)
Christopher Wipf's avatar
Christopher Wipf committed
175

176
        plot_noise(ifo, noises)
177
    return score, noises, ifo