Skip to content

Merging carrier and signal simulation

finesse importer requested to merge merging_carrier_signal_sim into master

A large amount of changes here, hopefully for the better:

BaseSimulation is gone. CarrierSignalMatrixSimulation replaces it effectively. This new class embodies the simulation methodology of Finesse, solving two sparse matrices, can be plane-wave or modal.

CarrierSignalMatrixSimulation has two matrix solvers, one for the carrier and one for the signal. sim.carrier and sim.signal. These hold all the information regards node indicies, views of the RHS output, solving, filling, workspaces, etc.

Detector workspaces are now stored in the single CarrierSignalMatrixSimulation object as it should be, rather than in the model.

CarrierSignalMatrixSimulation contains common workspaces and beam tracing between the two matrix solvers. No need for all the annoying duplicated code and weird work arounds.

Matrix filling methods are now split, you specify one for carrier and one for signal. Looks like this now:

ws = MirrorWorkspace(self, sim, refill)
ws.carrier.set_fill_function(mirror_carrier_fill)
ws.signal.set_fill_function(mirror_signal_fill)

This change means nearly every file needed updating slightly.

Getting some output now looks like, weird DC in the name gone:

ws.sim.carrier.get_out(self.p1.i, f1.index, k)

ws.carrier is a ConnectorMatrixSimulationInfo which contains details on the matrix specific connections indices for accessing fill functions, and points to fill functions. ws.sim.carrier is a reference to the MatrixSystemSolver for actually doing filling, solving. KLU class inherits from this solver class to do its job. Dense matrix solver and Lee's code unfortunately do not work

sim.frequencies has been renamed to sim.optical_frequencies which is a FrequencyContainer.

Optical and signal connections objects now have to be both stored at once. Given all the purely optical filling is identical between carrier and signal, fill methods should be abstracted enough to be used between them:

cdef class MirrorOpticalConnections:
    cdef public:
        int P1i_P1o_idx
        int P2i_P2o_idx
        int P1i_P2o_idx
        int P2i_P1o_idx

    cdef readonly:
        SubCCSView1DArray P1i_P1o
        SubCCSView1DArray P2i_P2o
        SubCCSView1DArray P1i_P2o
        SubCCSView1DArray P2i_P1o
    cdef:
        mirror_optical_connections opt_conn_ptrs

cdef class MirrorSignalConnections(MirrorOpticalConnections):
    cdef public:
        int P1i_Fz_idx, P2i_Fz_idx, P1o_Fz_idx, P2o_Fz_idx
        int Z_P1o_idx, Z_P2o_idx

    cdef readonly:
        SubCCSView2DArray P1i_Fz
        SubCCSView2DArray P1o_Fz
        SubCCSView2DArray P2i_Fz
        SubCCSView2DArray P2o_Fz
        SubCCSView2DArray Z_P1o
        SubCCSView2DArray Z_P2o
    cdef:
        mirror_signal_connections sig_conn_ptrs

These new abstract fill methods can look something like this:

cdef inline void mirror_fill_optical_2_optical(
        mirror_optical_connections *conn,
        MirrorWorkspace ws,
        frequency_info_t *freq,
        double r,
        complex_t it,
        double phi
    ):
    cdef double phase_shift = 2.0 * phi * (1 + freq.f / ws.sim.model_data.f0)
    cdef complex_t tuning = cexp(1.0j * phase_shift)
    cdef complex_t ctuning = conj(tuning)
    # Reflections
    (<SubCCSView>conn.P1i_P1o[freq.index]).fill_za_zm_2(
        r * tuning, ws.K11.ptr, ws.K11.stride1, ws.K11.stride2
    )
    (<SubCCSView>conn.P2i_P2o[freq.index]).fill_za_zm_2(
        r * ctuning, ws.K22.ptr, ws.K22.stride1, ws.K22.stride2
    )
    # Transmission
    (<SubCCSView>conn.P1i_P2o[freq.index]).fill_za_zm_2(
        it, ws.K12.ptr, ws.K12.stride1, ws.K12.stride2
    )
    (<SubCCSView>conn.P2i_P1o[freq.index]).fill_za_zm_2(
        it, ws.K21.ptr, ws.K21.stride1, ws.K21.stride2
    )
Edited by finesse importer

Merge request reports