Single-Mode Cavity

The maxwelllink.em_solvers.single_mode_cavity module provides a lightweight electromagnetic solver that replaces a full FDTD grid with a single damped harmonic oscillator. It evolves entirely in atomic units while supporting the same Molecule abstraction used by the Meep backend, making it well suited for rapid prototyping, regression tests, and workflows focused on one classical cavity mode. Multiple molecular dipole components can be coupled simultaneously by supplying composite axes such as "xy".

Note

The cavity replaces the full EM grid with canonical coordinate \(\mathbf{q}_c\) and momentum \(\mathbf{p}_c = \dot{\mathbf{q}}_c\) obeying the component-wise equation

\[\ddot{\mathbf{q}}_c = -\omega_c^{2} \mathbf{q}_c - \varepsilon \sum_{m} \boldsymbol{\mu}_{m} - \kappa \dot{\mathbf{q}}_c + D(t),\]

where \(\omega_c\) is frequency_au, \(\kappa\) is damping_au, \(\varepsilon = 1/\sqrt{\epsilon_0 V}\) is coupling_strength, and \(D(t)\) is the optional external drive. The sum runs over the dipole components selected by coupling_axis for each coupled molecule. The effective electric field returned to the drivers is

\[\mathbf{E}(t) = -\varepsilon\, \mathbf{q}_c(t) - \delta_{\mathrm{DSE}} \frac{\varepsilon^{2}}{\omega_c^{2}}\, \boldsymbol{\mu}(t),\]

with \(\boldsymbol{\mu}(t)\) the summed molecular dipole restricted to the requested axes and \(\delta_{\mathrm{DSE}} = 1\) only when include_dse=True.

Requirements

  • No additional dependencies beyond the MaxwellLink Python stack are required.

Usage

Socket mode

import maxwelllink as mxl

hub = mxl.SocketHub(host="127.0.0.1", port=31415, timeout=10.0, latency=1e-5)
molecule = mxl.Molecule(hub=hub)

sim = mxl.SingleModeSimulation(
    dt_au=0.5,
    frequency_au=0.242,
    damping_au=0.0,
    molecules=[molecule],
    coupling_strength=1e-4,
    qc_initial=[0, 0, 1e-5],
    coupling_axis="z",
    hub=hub,
    record_history=True,
)

sim.run(steps=4000)

Launch mxl_driver --model tls --port 31415 ... (or another driver) after running this script.

Non-socket mode

import maxwelllink as mxl

tls = mxl.Molecule(
    driver="tls",
    driver_kwargs=dict(
        omega=0.242,
        mu12=187.0,
        orientation=2,
        pe_initial=1e-4,
    ),
)

sim = mxl.SingleModeSimulation(
    dt_au=0.5,
    frequency_au=0.242,
    damping_au=0.0,
    molecules=[tls],
    coupling_strength=1e-4,
    qc_initial=[0, 0, 1e-5],
    coupling_axis="z",
    record_history=True,
)

sim.run(steps=4000)

Parameters

Name

Description

dt_au

Integration time step in atomic units. Must be positive.

frequency_au

Cavity angular frequency \(\omega_c\) (a.u.).

damping_au

Linear damping coefficient \(\kappa\) applied to the cavity momentum (a.u.).

molecules

Iterable of Molecule instances. Socket and non-socket molecules can be mixed in the same simulation.

drive

Constant float or callable drive(time_au) returning the external drive term. Defaults to 0.0.

coupling_strength

Scalar prefactor \(g\) for the molecular polarization feedback. Default: 1.0.

coupling_axis

One or more dipole components to couple (case-insensitive union of "x", "y", "z", e.g. "xy"). Default: "xy".

hub

Optional SocketHub shared by all socket-mode molecules. The simulation infers the hub from the first socket molecule when omitted.

qc_initial

Initial cavity coordinate vector (sequence of three floats or scalar applied to each coupled axis). Default: [0.0, 0.0, 0.0].

pc_initial

Initial cavity momentum vector (a.u.). Default: [0.0, 0.0, 0.0].

mu_initial

Initial total molecular dipole vector prior to axis masking (a.u.). Default: [0.0, 0.0, 0.0].

dmudt_initial

Initial time derivative of the total molecular dipole vector (a.u.). Default: [0.0, 0.0, 0.0].

shift_dipole_baseline

When True subtract the initial dipole so the simulation starts from a zero baseline (helps with large permanent dipoles). Default: False.

molecule_half_step

When True extrapolate molecular responses from half-step data (use False for full-step drivers). Default: False.

record_history

When True store histories for time, field, momentum, drive, and net molecular response. Default: True.

include_dse

When True add the dipole self-energy correction to the field returned to the molecules and account for it in the cavity energy. Default: False.

Returned data

Calling SingleModeSimulation with record_history=True populates:

  • SingleModeSimulation.time_history – time stamps in atomic units.

  • SingleModeSimulation.qc_history – cavity coordinate \(q_c(t)\).

  • SingleModeSimulation.pc_history – cavity momentum \(\dot{q}_c(t)\).

  • SingleModeSimulation.drive_history – external drive values.

  • SingleModeSimulation.molecule_response_history – summed molecular response along coupling_axis.

  • SingleModeSimulation.energy_history – total energy of the cavity and coupled molecules (requires record_history=True).

Each Molecule keeps additional_data_history, which records driver data (e.g., TLS populations, energies, timestamps). Socket drivers may append extra JSON payloads through the hub; embedded drivers populate the same history via maxwelllink.molecule.molecule.Molecule.append_additional_data().

Notes

  • Provide either steps or until to SingleModeSimulation.run(), not both.

  • Socket-mode molecules must all bind to the same SocketHub; the simulation waits until every driver acknowledges initialization.

  • Setting record_history=False avoids list allocations for throughput-critical runs.