Skip to content
Snippets Groups Projects
Commit 25dcfa78 authored by Jameson Graef Rollins's avatar Jameson Graef Rollins
Browse files

newtonian noise simplifications

Simplify newtonian noise calculations to return displacement noise for
simplified configuration: either single test mass or single arm.
parent 080b9fb9
No related branches found
No related tags found
No related merge requests found
...@@ -3,6 +3,7 @@ import numpy as np ...@@ -3,6 +3,7 @@ import numpy as np
from .. import nb from .. import nb
from .. import noise from .. import noise
class QuantumVacuum(nb.Noise): class QuantumVacuum(nb.Noise):
"""Quantum Vacuum """Quantum Vacuum
...@@ -50,7 +51,8 @@ class Newtonian(nb.Noise): ...@@ -50,7 +51,8 @@ class Newtonian(nb.Noise):
) )
def calc(self): def calc(self):
return noise.newtonian.gravg(self.freq, self.ifo) n = noise.newtonian.gravg(self.freq, self.ifo.Seismic)
return n * 4 * self.ifo.gwinc.dhdl_sqr
class NewtonianRayleigh(nb.Noise): class NewtonianRayleigh(nb.Noise):
...@@ -63,7 +65,8 @@ class NewtonianRayleigh(nb.Noise): ...@@ -63,7 +65,8 @@ class NewtonianRayleigh(nb.Noise):
) )
def calc(self): def calc(self):
return noise.newtonian.gravg_rayleigh(self.freq, self.ifo) n = noise.newtonian.gravg_rayleigh(self.freq, self.ifo.Seismic)
return n * 2 * self.ifo.gwinc.dhdl_sqr
class NewtonianBody(nb.Noise): class NewtonianBody(nb.Noise):
...@@ -76,8 +79,9 @@ class NewtonianBody(nb.Noise): ...@@ -76,8 +79,9 @@ class NewtonianBody(nb.Noise):
) )
def calc(self): def calc(self):
return (noise.newtonian.gravg_pwave(self.freq, self.ifo) np = noise.newtonian.gravg_pwave(self.freq, self.ifo.Seismic)
+ noise.newtonian.gravg_swave(self.freq, self.ifo)) ns = noise.newtonian.gravg_swave(self.freq, self.ifo.Seismic)
return (np + ns) * 4 * self.ifo.gwinc.dhdl_sqr
class NewtonianInfrasound(nb.Noise): class NewtonianInfrasound(nb.Noise):
...@@ -90,7 +94,8 @@ class NewtonianInfrasound(nb.Noise): ...@@ -90,7 +94,8 @@ class NewtonianInfrasound(nb.Noise):
) )
def calc(self): def calc(self):
return noise.newtonian.atmois(self.freq, self.ifo) n = noise.newtonian.atmois(self.freq, self.ifo.Atmospheric, self.ifo.Seismic)
return n * 2 * self.ifo.gwinc.dhdl_sqr
class SuspensionThermal(nb.Noise): class SuspensionThermal(nb.Noise):
......
from __future__ import division '''Functions to calculate Newtonian noise
'''
from __future__ import division
import numpy as np import numpy as np
from numpy import pi, sqrt, exp, log10
import scipy.integrate as scint import scipy.integrate as scint
from numpy import pi, sqrt, exp
from .seismic import seismic_ground_NLNM from .seismic import seismic_ground_NLNM
from .. import const from .. import const
def gravg(f, ifo): def gravg(f, seismic):
"""Return estimate of newtonian noise contribribution to |h(f)|^2 """Gravity gradient noise for single test mass
:f: frequency array in Hz
:seismic: gwinc Seismic struct
N = GRAVG(F, IFO) returns the gravity gradient (Newtonian) noise :returns: displacement noise power spectrum at :f:, in meters
contribution in strain^2/Hz for four mirrors.
References: References:
...@@ -21,7 +25,7 @@ def gravg(f, ifo): ...@@ -21,7 +25,7 @@ def gravg(f, ifo):
Driggers and Harms 2011, ``Results of Phase 1 Newtonian Noise Driggers and Harms 2011, ``Results of Phase 1 Newtonian Noise
Measurements at the LIGO Sites,'' February-March 2011. T1100237. Measurements at the LIGO Sites,'' February-March 2011. T1100237.
https://dcc.ligo.org/cgi-bin/private/DocDB/ShowDocument?docid=60064 https://dcc.ligo.org/LIGO-T1100237
Written by Enrico Camagna (?) Written by Enrico Camagna (?)
...@@ -31,20 +35,18 @@ def gravg(f, ifo): ...@@ -31,20 +35,18 @@ def gravg(f, ifo):
""" """
fk = ifo.Seismic.KneeFrequency fk = seismic.KneeFrequency
a = ifo.Seismic.LowFrequencyLevel a = seismic.LowFrequencyLevel
L = ifo.Infrastructure.Length gamma = seismic.Gamma
gamma = ifo.Seismic.Gamma rho = seismic.Rho
ggcst = const.G
rho = ifo.Seismic.Rho
# factor to account for correlation between masses # factor to account for correlation between masses
# and the height of the mirror above the ground # and the height of the mirror above the ground
beta = ifo.Seismic.Beta beta = seismic.Beta
h = ifo.Seismic.TestMassHeight h = seismic.TestMassHeight
c_rayleigh = ifo.Seismic.RayleighWaveSpeed c_rayleigh = seismic.RayleighWaveSpeed
if 'Omicron' in ifo.Seismic: if 'Omicron' in seismic:
omicron = ifo.Seismic.Omicron omicron = seismic.Omicron
else: else:
omicron = 1 omicron = 1
...@@ -53,14 +55,14 @@ def gravg(f, ifo): ...@@ -53,14 +55,14 @@ def gravg(f, ifo):
# modelization of seismic noise (vertical) # modelization of seismic noise (vertical)
ground = a*coeff + a*(1-coeff)*(fk/f)**2 ground = a*coeff + a*(1-coeff)*(fk/f)**2
if 'Site' in ifo.Seismic and ifo.Seismic.Site == 'LLO': if 'Site' in seismic and seismic.Site == 'LLO':
ground = a*coeff*(fk/f) + a*(1-coeff)*(fk/f)**2 ground = a*coeff*(fk/f) + a*(1-coeff)*(fk/f)**2
# effective GG spring frequency, with G gravitational # effective GG spring frequency, with G gravitational
fgg = sqrt(ggcst * rho) / (2*pi) fgg = sqrt(const.G * rho) / (2*pi)
# fixed numerical factors, 5/9/06, PF # fixed numerical factors, 5/9/06, PF
n = (beta*4*pi/L*(fgg**2/f**2)*ground)**2 n = (beta*2*pi*(fgg**2/f**2)*ground)**2
# The following two terms are corrections due to Jan Harms # The following two terms are corrections due to Jan Harms
# https://git.ligo.org/rana-adhikari/CryogenicLIGO/issues/45 # https://git.ligo.org/rana-adhikari/CryogenicLIGO/issues/45
...@@ -72,25 +74,29 @@ def gravg(f, ifo): ...@@ -72,25 +74,29 @@ def gravg(f, ifo):
# Feedforward cancellation # Feedforward cancellation
n /= (omicron**2) n /= (omicron**2)
return n * ifo.gwinc.sinc_sqr return n
def gravg_rayleigh(f, seismic):
"""Gravity gradient noise for single arm cavity from seismic Rayleigh waves
:f: frequency array in Hz
:seismic: gwinc Seismic structure
:returns: displacement noise power spectrum at :f:, in meters
def gravg_rayleigh(f, ifo):
"""Gravity gradient noise for seismic Rayleigh waves
Following Harms LRR: https://doi.org/10.1007/lrr-2015-3 Following Harms LRR: https://doi.org/10.1007/lrr-2015-3
""" """
fk = ifo.Seismic.KneeFrequency fk = seismic.KneeFrequency
a = ifo.Seismic.LowFrequencyLevel a = seismic.LowFrequencyLevel
L = ifo.Infrastructure.Length gamma = seismic.Gamma
gamma = ifo.Seismic.Gamma rho = seismic.Rho
ggcst = const.G h = seismic.TestMassHeight
rho = ifo.Seismic.Rho c_rayleigh = seismic.RayleighWaveSpeed
h = ifo.Seismic.TestMassHeight
c_rayleigh = ifo.Seismic.RayleighWaveSpeed if 'Omicron' in seismic:
omicron = seismic.Omicron
if 'Omicron' in ifo.Seismic:
omicron = ifo.Seismic.Omicron
else: else:
omicron = 1 omicron = 1
...@@ -99,41 +105,47 @@ def gravg_rayleigh(f, ifo): ...@@ -99,41 +105,47 @@ def gravg_rayleigh(f, ifo):
# modelization of seismic noise (vertical) # modelization of seismic noise (vertical)
ground = a*coeff + a*(1-coeff)*(fk/f)**2 ground = a*coeff + a*(1-coeff)*(fk/f)**2
if 'Site' in ifo.Seismic and ifo.Seismic.Site == 'LLO': if 'Site' in seismic and seismic.Site == 'LLO':
ground = a*coeff*(fk/f) + a*(1-coeff)*(fk/f)**2 ground = a*coeff*(fk/f) + a*(1-coeff)*(fk/f)**2
# Harms LRR eqs. 35, 96, and 98 # Harms LRR eqs. 35, 96, and 98
w = 2 * pi * f w = 2 * pi * f
k = w / c_rayleigh k = w / c_rayleigh
kP = w / ifo.Seismic.pWaveSpeed kP = w / seismic.pWaveSpeed
kS = w / ifo.Seismic.sWaveSpeed kS = w / seismic.sWaveSpeed
qzP = sqrt(k**2 - kP**2) qzP = sqrt(k**2 - kP**2)
qzS = sqrt(k**2 - kS**2) qzS = sqrt(k**2 - kS**2)
zeta = sqrt(qzP / qzS) zeta = sqrt(qzP / qzS)
gnu = k * (1 - zeta) / (qzP - k * zeta) gnu = k * (1 - zeta) / (qzP - k * zeta)
n = 2 * (2 * pi * ggcst * rho * exp(-h * k) * gnu)**2 * ground**2 / w**4 n = (2 * pi * const.G * rho * exp(-h * k) * gnu)**2 * ground**2 / w**4
n /= omicron**2 n /= omicron**2
return n * ifo.gwinc.dhdl_sqr return n
def gravg_pwave(f, seismic):
"""Gravity gradient noise for single test mass from seismic p-waves
:f: frequency array in Hz
:seismic: gwinc Seismic structure
:returns: displacement noise power spectrum at :f:, in meters
def gravg_pwave(f, ifo):
"""Gravity gradient noise for seismic p-waves
Following Harms LRR: https://doi.org/10.1007/lrr-2015-3 Following Harms LRR: https://doi.org/10.1007/lrr-2015-3
""" """
ggcst = const.G cP = seismic.pWaveSpeed
cP = ifo.Seismic.pWaveSpeed levelP = seismic.pWaveLevel
levelP = ifo.Seismic.pWaveLevel tmheight = seismic.TestMassHeight
rho_ground = seismic.Rho
kP = (2 * pi * f) / cP kP = (2 * pi * f) / cP
rho_ground = ifo.Seismic.Rho
psd_ground_pwave = (levelP * seismic_ground_NLNM(f))**2 psd_ground_pwave = (levelP * seismic_ground_NLNM(f))**2
tmheight = ifo.Seismic.TestMassHeight
xP = np.abs(kP * tmheight) xP = np.abs(kP * tmheight)
if tmheight >= 0: if tmheight >= 0:
...@@ -148,74 +160,81 @@ def gravg_pwave(f, ifo): ...@@ -148,74 +160,81 @@ def gravg_pwave(f, ifo):
height_supp_power = (3 / 4) * np.array([scint.quad(lambda th, x: np.sin(th)**3 height_supp_power = (3 / 4) * np.array([scint.quad(lambda th, x: np.sin(th)**3
* (2 - np.exp(-x * np.sin(th)))**2, 0, pi, args=(x,))[0] * (2 - np.exp(-x * np.sin(th)))**2, 0, pi, args=(x,))[0]
for x in xP]) for x in xP])
psd_gravg_pwave = ((2 * pi * ggcst * rho_ground)**2 psd_gravg_pwave = ((2 * pi * const.G * rho_ground)**2
* psd_ground_pwave * height_supp_power) * psd_ground_pwave * height_supp_power)
psd_gravg_pwave *= 4 / (2 * pi * f)**4 psd_gravg_pwave /= (2 * pi * f)**4
return psd_gravg_pwave * ifo.gwinc.dhdl_sqr return psd_gravg_pwave
def gravg_swave(f, seismic):
"""Gravity gradient noise for single test mass from seismic s-waves
:f: frequency array in Hz
:seismic: gwinc Seismic structure
:returns: displacement noise power spectrum at :f:, in meters
def gravg_swave(f, ifo):
"""Gravity gradient noise for seismic s-waves
Following Harms LRR: https://doi.org/10.1007/lrr-2015-3 Following Harms LRR: https://doi.org/10.1007/lrr-2015-3
""" """
ggcst = const.G cS = seismic.sWaveSpeed
cS = ifo.Seismic.sWaveSpeed levelS = seismic.sWaveLevel
levelS = ifo.Seismic.sWaveLevel tmheight = seismic.TestMassHeight
rho_ground = seismic.Rho
kS = (2 * pi * f) / cS kS = (2 * pi * f) / cS
rho_ground = ifo.Seismic.Rho
psd_ground_swave = (levelS * seismic_ground_NLNM(f))**2 psd_ground_swave = (levelS * seismic_ground_NLNM(f))**2
tmheight = ifo.Seismic.TestMassHeight
xS = np.abs(kS * tmheight) xS = np.abs(kS * tmheight)
# For both surface and underground facilities # For both surface and underground facilities
height_supp_power = (3 / 2) * np.array([scint.quad(lambda th, x: np.sin(th)**3 height_supp_power = (3 / 2) * np.array([scint.quad(lambda th, x: np.sin(th)**3
* np.exp(-2 * x * np.sin(th)), 0, pi / 2, args=(x,))[0] * np.exp(-2 * x * np.sin(th)), 0, pi / 2, args=(x,))[0]
for x in xS]) for x in xS])
psd_gravg_swave = ((2 * pi * ggcst * rho_ground)**2 psd_gravg_swave = ((2 * pi * const.G * rho_ground)**2
* psd_ground_swave * height_supp_power) * psd_ground_swave * height_supp_power)
psd_gravg_swave *= 4 / (2 * pi * f)**4 psd_gravg_swave /= (2 * pi * f)**4
return psd_gravg_swave * ifo.gwinc.dhdl_sqr return psd_gravg_swave
def atmois(f, ifo): def atmois(f, atmos, seismic):
""" """Atmospheric infrasound newtonian noise for single arm cavity
Atmospheric infrasound calculation following Harms LRR.
""" :f: frequency array in Hz
p_air = ifo.Atmospheric.AirPressure :atmos: gwinc Atmospheric structure
rho_air = ifo.Atmospheric.AirDensity :seismic: gwinc Seismic structure
ai_air = ifo.Atmospheric.AdiabaticIndex
c_sound = ifo.Atmospheric.SoundSpeed
L = ifo.Infrastructure.Length :returns: displacement noise power spectrum at :f:, in meters
ggcst = const.G
h = ifo.Seismic.TestMassHeight """
p_air = atmos.AirPressure
rho_air = atmos.AirDensity
ai_air = atmos.AdiabaticIndex
c_sound = atmos.SoundSpeed
h = seismic.TestMassHeight
w = 2 * pi * f w = 2 * pi * f
k = w / c_sound k = w / c_sound
# Pressure spectrum # Pressure spectrum
try: try:
a_if = ifo.Atmospheric.InfrasoundLevel1Hz a_if = atmos.InfrasoundLevel1Hz
e_if = ifo.Atmospheric.InfrasoundExponent e_if = atmos.InfrasoundExponent
psd_if = (a_if * f**e_if)**2 psd_if = (a_if * f**e_if)**2
except AttributeError: except AttributeError:
psd_if = atmoBowman(f)**2 psd_if = atmoBowman(f)**2
# Harms LRR (2015), eq. 172 # Harms LRR (2015), eq. 172
# https://doi.org/10.1007/lrr-2015-3 # https://doi.org/10.1007/lrr-2015-3
# With an extra factor 2 for two arms
# And with the Bessel terms ignored... for 4 km this amounts to a 10% # And with the Bessel terms ignored... for 4 km this amounts to a 10%
# correction at 10 Hz and a 30% correction at 1 Hz # correction at 10 Hz and a 30% correction at 1 Hz
coupling_if = 4./3 * (4 * pi / (k * w**2) * ggcst * rho_air / (ai_air * p_air))**2 coupling_if = 2/3 * (4 * pi / (k * w**2) * const.G * rho_air / (ai_air * p_air))**2
n_if = coupling_if * psd_if n_if = coupling_if * psd_if
return n_if * ifo.gwinc.dhdl_sqr return n_if
def atmoBowman(f): def atmoBowman(f):
...@@ -223,12 +242,15 @@ def atmoBowman(f): ...@@ -223,12 +242,15 @@ def atmoBowman(f):
""" """
freq = np.array([ freq = np.array([
0.01, 0.0155, 0.0239, 0.0367, 0.0567, 0.01, 0.0155, 0.0239, 0.0367, 0.0567,
0.0874, 0.1345, 0.2075, 0.32, 0.5, 0.0874, 0.1345, 0.2075, 0.32, 0.5,
0.76, 1.17, 1.8, 2.79, 4.3, 0.76, 1.17, 1.8, 2.79, 4.3,
6.64, 10, 100]) 6.64, 10, 100,
pressure_asd = np.sqrt([22.8, 4, 0.7, 0.14, 0.027, 0.004, ])
0.0029, 0.0039, 7e-4, 1.44e-4, 0.37e-4, pressure_asd = sqrt([
0.12e-4, 0.56e-5, 0.35e-5, 0.26e-5, 0.24e-5, 22.8, 4, 0.7, 0.14, 0.027, 0.004,
2e-6, 2e-6]) 0.0029, 0.0039, 7e-4, 1.44e-4, 0.37e-4,
return 10**(np.interp(np.log10(f), np.log10(freq), np.log10(pressure_asd))) 0.12e-4, 0.56e-5, 0.35e-5, 0.26e-5, 0.24e-5,
2e-6, 2e-6,
])
return 10**(np.interp(log10(f), log10(freq), log10(pressure_asd)))
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment