#cython: boundscheck=False, wraparound=False, initializedcheck=False
from finesse.cymath cimport complex_t
from finesse.simulations.simulation cimport BaseSimulation
from finesse.cymath.cmatrix cimport SubCCSView1DArray
from finesse.symbols import Symbol
from finesse.frequency cimport frequency_info_t
from finesse.cymath.cmatrix cimport SubCCSView
from finesse.components.workspace cimport FillFuncWrapper
from cpython.ref cimport PyObject
import logging
ctypedef (double*, ) ptr_tuple_1
ctypedef (double*, double*) ptr_tuple_2
LOGGER = logging.getLogger(__name__)
cdef class LensValues(BaseCValues):
def __init__(LensValues self):
cdef ptr_tuple_1 ptr = (&self.f, )
cdef tuple params = ("f", )
self.setup(params, sizeof(ptr), <double**>&ptr)
cdef class AstigmaticLensValues(BaseCValues):
def __init__(AstigmaticLensValues self):
cdef ptr_tuple_2 ptr = (&self.fx, &self.fy)
cdef tuple params = ("fx", "fy")
self.setup(params, sizeof(ptr), <double**>&ptr)
[docs]cdef class LensConnections:
def __cinit__(self, BaseSimulation sim):
self.P1i_P2o = SubCCSView1DArray(sim.carrier.optical_frequencies.size)
self.P2i_P1o = SubCCSView1DArray(sim.carrier.optical_frequencies.size)
self.conn_ptrs.P1i_P2o = <PyObject**>self.P1i_P2o.views
self.conn_ptrs.P2i_P1o = <PyObject**>self.P2i_P1o.views
cdef class BaseLensWorkspace(KnmConnectorWorkspace):
def __init__(self, owner, BaseSimulation sim, BaseCValues values):
super().__init__(
owner,
sim,
LensConnections(sim),
None,
values,
)
self.lc = self.carrier.connections
self.P1i_id = sim.trace_node_index[owner.p1.i]
self.P1o_id = sim.trace_node_index[owner.p1.o]
self.P2i_id = sim.trace_node_index[owner.p2.i]
self.P2o_id = sim.trace_node_index[owner.p2.o]
self.sym_abcd_Cx = NULL
self.sym_abcd_Cy = NULL
def __dealloc__(self):
cy_expr_free(self.sym_abcd_Cx)
cy_expr_free(self.sym_abcd_Cy)
def compile_abcd_cy_exprs(self):
cdef:
dict abcd_handles = self.owner._abcd_matrices
tuple keyx = (self.owner.p1.i, self.owner.p2.o, "x")
tuple keyy = (self.owner.p1.i, self.owner.p2.o, "y")
cdef object[:, ::1] Mx_sym = abcd_handles[keyx][0]
cdef object[:, ::1] My_sym = abcd_handles[keyy][0]
# NOTE (sjr) Only element C of a Lens ABCD matrix can possibly change
if isinstance(Mx_sym[1][0], Symbol):
ch_sym = Mx_sym[1][0].expand_symbols().eval(keep_changing_symbols=True)
if isinstance(ch_sym, Symbol):
self.sym_abcd_Cx = cy_expr_new()
cy_expr_init(self.sym_abcd_Cx, ch_sym)
if isinstance(My_sym[1][0], Symbol):
ch_sym = My_sym[1][0].expand_symbols().eval(keep_changing_symbols=True)
if isinstance(ch_sym, Symbol):
self.sym_abcd_Cy = cy_expr_new()
cy_expr_init(self.sym_abcd_Cy, ch_sym)
cpdef update_parameter_values(self) :
ConnectorWorkspace.update_parameter_values(self)
if self.sym_abcd_Cx != NULL:
self.abcd_x[1][0] = cy_expr_eval(self.sym_abcd_Cx)
if self.sym_abcd_Cy != NULL:
self.abcd_y[1][0] = cy_expr_eval(self.sym_abcd_Cy)
cdef class LensWorkspace(BaseLensWorkspace):
def __init__(self, owner, BaseSimulation sim):
self.lv = LensValues()
super().__init__(owner, sim, self.lv)
cdef class AstigmaticLensWorkspace(BaseLensWorkspace):
def __init__(self, owner, BaseSimulation sim):
self.lv = AstigmaticLensValues()
super().__init__(owner, sim, self.lv)
# TODO (sjr) make c_lens_fill function?
lens_fill_qnoise = FillFuncWrapper.make_from_ptr(c_lens_fill_qnoise)
cdef object c_lens_fill_qnoise(ConnectorWorkspace cws) :
r"""
Fills the quantum noise input matrix elements corresponding to this `lens`.
"""
cdef:
BaseLensWorkspace ws = <BaseLensWorkspace> cws
PyObject ***noises = ws.output_noise.ptrs
frequency_info_t *freq
Py_ssize_t i, j
complex_t factor
for i in range(ws.sim.signal.optical_frequencies.size):
freq = &(ws.sim.signal.optical_frequencies.frequency_info[i])
factor = 0.5 * (1 + freq.f_car[0] / ws.sim.model_settings.f0)
if ws.sim.is_modal:
ws.total_losses[:] = 0
for j in range(ws.sim.signal.nhoms):
ws.total_losses[j] += ws.oconn_info[0].loss[j]
(<SubCCSView>noises[0][freq.index]).fill_za_dv(factor, ws.total_losses)
ws.total_losses[:] = 0
for j in range(ws.sim.signal.nhoms):
ws.total_losses[j] += ws.oconn_info[1].loss[j]
(<SubCCSView>noises[1][freq.index]).fill_za_dv(factor, ws.total_losses)