Source code for finesse.cymath.gaussbeam

#cython: boundscheck=False, wraparound=False, initializedcheck=False

"""Low-level calculations for Gaussian beam properties.

This module provides functions for computing properties of Gaussian beams
and transforming Gaussian beam parameters via the ABCD ray-matrix framework.

.. note::
    These are low-level functions intended for use in Cython extensions. Users
    should use the functions and classes given in :mod:`finesse.gaussian` instead
    of those defined here.
"""

cpdef complex_t transform_q(
    const double[:, ::1] M,
    complex_t q1,
    double nr1,
    double nr2
) noexcept nogil:
    cdef:
        complex_t q1_factor = q1 / nr1

    return nr2 * (M[0][0] * q1_factor + M[0][1]) / (M[1][0] * q1_factor + M[1][1])

cdef complex_t c_transform_q(
    const double* M,
    complex_t q1,
    double nr1,
    double nr2
) noexcept nogil:
    """Assumes M is a C-contiguous array of size 2x2"""
    cdef:
        complex_t q1_factor = q1 / nr1

    return nr2 * (M[0] * q1_factor + M[1]) / (M[2] * q1_factor + M[3])

cpdef complex_t inv_transform_q(
    const double[:, ::1] M,
    complex_t q2,
    double nr1,
    double nr2
) noexcept nogil:
    cdef:
        complex_t q2_factor = q2 / nr2

    return nr1 * (M[0][1] - M[1][1] * q2_factor) / (M[1][0] * q2_factor - M[0][0])


cdef void c_abcd_multiply(
    const double* m1,
    const double* m2,
    double* out
) noexcept nogil:
    assert m1 != NULL
    assert m2 != NULL
    assert out != NULL
    cdef:
        double A1 = m1[0]
        double B1 = m1[1]
        double C1 = m1[2]
        double D1 = m1[3]

        double A2 = m2[0]
        double B2 = m2[1]
        double C2 = m2[2]
        double D2 = m2[3]

    out[0] = A1 * A2 + B1 * C2
    out[1] = A1 * B2 + B1 * D2
    out[2] = C1 * A2 + D1 * C2
    out[3] = C1 * B2 + D1 * D2

cdef void abcd_multiply(
    const double[:, ::1] m1,
    const double[:, ::1] m2,
    double[:, ::1] out,
) noexcept nogil:
    cdef:
        double A1 = m1[0][0]
        double B1 = m1[0][1]
        double C1 = m1[1][0]
        double D1 = m1[1][1]

        double A2 = m2[0][0]
        double B2 = m2[0][1]
        double C2 = m2[1][0]
        double D2 = m2[1][1]

    out[0][0] = A1 * A2 + B1 * C2
    out[0][1] = A1 * B2 + B1 * D2
    out[1][0] = C1 * A2 + D1 * C2
    out[1][1] = C1 * B2 + D1 * D2

cpdef void sym_abcd_multiply(
    object[:, ::1] m1,
    object[:, ::1] m2,
    object[:, ::1] out,
) noexcept:
    cdef:
        object A1 = m1[0][0]
        object B1 = m1[0][1]
        object C1 = m1[1][0]
        object D1 = m1[1][1]

        object A2 = m2[0][0]
        object B2 = m2[0][1]
        object C2 = m2[1][0]
        object D2 = m2[1][1]

    out[0][0] = A1 * A2 + B1 * C2
    out[0][1] = A1 * B2 + B1 * D2
    out[1][0] = C1 * A2 + D1 * C2
    out[1][1] = C1 * B2 + D1 * D2


cpdef bint is_abcd_changing(object[:, ::1] M) noexcept:
    cdef:
        Py_ssize_t i, j
        bint is_changing

    for i in range(2):
        for j in range(2):
            is_changing = getattr(M[i][j], "is_changing", False)
            if is_changing:
                return True

    return False