From 519024feb8af950f6874d87b981609f9826b9b55 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Bayle <j2b.bayle@gmail.com> Date: Thu, 16 Jun 2022 09:53:44 +0200 Subject: [PATCH] First attempt to simulate hexagon --- lisainstrument/__init__.py | 1 + lisainstrument/hexagon.py | 106 +++++++++++++++++++++++++++++++++++++ tests/test_hexagon.py | 12 +++++ 3 files changed, 119 insertions(+) create mode 100644 lisainstrument/hexagon.py create mode 100755 tests/test_hexagon.py diff --git a/lisainstrument/__init__.py b/lisainstrument/__init__.py index 1781ab0..85367f1 100644 --- a/lisainstrument/__init__.py +++ b/lisainstrument/__init__.py @@ -7,3 +7,4 @@ from .meta import __author__ from .meta import __email__ from .instrument import Instrument +from .hexagon import Hexagon diff --git a/lisainstrument/hexagon.py b/lisainstrument/hexagon.py new file mode 100644 index 0000000..4c8c03a --- /dev/null +++ b/lisainstrument/hexagon.py @@ -0,0 +1,106 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +Simulation of the Hexagon experiment [1]. + +Reference: + + [1] Yamamoto, K., Vorndamme, C., Hartwig, O., Staab, M., Schwarze, T. S., & Heinzel, G. (2021). + Experimental verification of intersatellite clock synchronization at LISA performance levels. + https://doi.org/10.1103/PhysRevD.105.042009 + +Authors: + ... + Jean-Baptiste Bayle <j2b.bayle@gmail.com> +""" + +import numpy as np + +from . import noises + + +class Hexagon(): + """Represent the Hexagon instrument. + + Args: + size (int): numer of samples in the simulation + dt (float): sampling period [s] + primary_laser_asd (float): ASD of primary laser 1 [Hz/sqrt(Hz)] + locked_laser_asd (float): ASD added to locked lasers 2 & 3 [Hz/sqrt(Hz)] + """ + + INDICES = [1, 2, 3] + BEATNOTES = [12, 23, 31] + + def __init__(self, + size=100, dt=1 / (80e6/2**17/10/6/3), + primary_laser_asd=100, + locked_laser_asd=60, + offset_freqs='default', + central_freq=2.816E14): + + self.size = int(size) + self.dt = float(dt) + self.fs = 1.0 / self.dt + self.duration = self.size * self.dt + self.time = np.linspace(0, self.duration-self.dt, self.size) + + self.primary_laser_asd = primary_laser_asd + self.locked_laser_asd = locked_laser_asd + + self.central_freq = float(central_freq) + if offset_freqs == 'default': + self.offset_freqs = {1: 0.0, 2: 15E6, 3: 7E6} + else: + self.offset_freqs = offset_freqs + + # initialize single-laser-related attributes + self.laser_noises = None + self.carrier_flucuations = None + self.carrier_offsets = None + # initialize beatnote-related attributes + self.carrier_beatnote = None + self.carrier_beatnote_offsets = None + self.carrier_beatnote_fluctuations = None + # initialize signal-combination attributes + self.three_signal_combination = None + + + def simulate(self): + """Run a simulation, and generate all intermediary signals. + + Args: + """ + + self.laser_noises = np.empty((self.size, 3)) # (size, laser) [Hz] + + # Laser 1 is free-running + self.laser_noises[:, 0] = noises.laser(self.fs, self.size, self.primary_laser_asd) + # Laser 2 replicated laser 1 with added locking noise + self.laser_noises[:, 1] = self.laser_noises[:, 0] \ + + noises.white(self.fs, self.size, self.locked_laser_asd) + # Laser 3 replicated laser 1 with added locking noise + self.laser_noises[:, 2] = self.laser_noises[:, 0] \ + + noises.white(self.fs, self.size, self.locked_laser_asd) + + # Carrier beams + self.carrier_flucuations = self.laser_noises # (size, laser) [Hz] + self.carrier_offsets = np.array( + [[self.offset_freqs[index] for index in self.INDICES]] + ) # (size, laser) [Hz] + + # Compute beatnotes + # Convention is from paper: beatnote ij is beam j - beam i + self.carrier_beatnote_offsets = np.stack([ + self.carrier_offsets[:, int(str(ij)[1]) - 1] - self.carrier_offsets[:, int(str(ij)[0]) - 1] + for ij in self.BEATNOTES + ], axis=-1) # (size, beatnote) [Hz] + self.carrier_beatnote_fluctuations = np.stack([ + self.carrier_flucuations[:, int(str(ij)[1]) - 1] - self.carrier_flucuations[:, int(str(ij)[0]) - 1] + for ij in self.BEATNOTES + ], axis=-1) # (size, beatnote) [Hz] + self.carrier_beatnote = self.carrier_beatnote_offsets + self.carrier_beatnote_fluctuations + + # Three-signal combination + self.three_signal_combination = self.carrier_beatnote[:,0] \ + + self.carrier_beatnote[:,1] + self.carrier_beatnote[:,2] \ No newline at end of file diff --git a/tests/test_hexagon.py b/tests/test_hexagon.py new file mode 100755 index 0000000..e38ce3e --- /dev/null +++ b/tests/test_hexagon.py @@ -0,0 +1,12 @@ +#! /usr/bin/env python3 +# -*- coding: utf-8 -*- +# pylint: disable=missing-module-docstring + +import pytest +from lisainstrument import Hexagon + + +def test_run(): + """Test that simulations can run.""" + hex = Hexagon() + hex.simulate() -- GitLab