SHO driver
==========

The SHO driver implements a classical simple harmonic oscillator (SHO) with a
single frequency and dipole moment. It is provided by
:class:`maxwelllink.mxl_drivers.python.models.SHOModel` and ships with
**MaxwellLink** for lightweight regression tests and benchmark scenarios.

.. note::

  The SHO driver advances the classical phase-space variables :math:`(q,\,p)`
  generated by the Hamiltonian

  .. math::

     H(q, p, t) = \frac{1}{2}\,\omega_0^{2}\,q^{2} + \frac{1}{2}\,p^{2}
                  - \mu_{0}\,q\,\bigl(\widetilde{\mathbf{E}}(t)\cdot \mathbf{e}_{i}\bigr),

  written in atomic units with unit mass. Here :math:`\mathbf{e}_i` denotes the
  orientation unit vector of the dipole. The equations of motion are integrated
  with the velocity Verlet algorithm, and the emitted dipole current returned to
  Maxwell's equations is

  .. math::

     \frac{d}{dt}\langle \boldsymbol{\mu} \rangle = \mu_{0}\,p\,\mathbf{e}_{i}.

Requirements
------------

- No additional packages are required beyond **MaxwellLink**'s dependencies.
- ``numpy`` (already bundled) is used for the velocity Verlet integration.

Usage
-----

Socket mode
^^^^^^^^^^^

.. code-block:: bash

   mxl_driver --model sho --port 31415 \
     --param "omega=0.242, mu0=187, orientation=2, p_initial=1e-2, \
              q_initial=0.0, checkpoint=false, restart=false"

Non-socket mode
^^^^^^^^^^^^^^^

.. code-block:: python

   mxl.Molecule(
       driver="sho",
       driver_kwargs={
           "omega": 0.242,
           "mu0": 187.0,
           "orientation": 2,
           "p_initial": 1e-2,
           "q_initial": 0.0,
       },
       # ...
   )


Parameters
----------

.. list-table::
   :header-rows: 1

   * - Name
     - Description
   * - ``omega``
     - Oscillator frequency in atomic units. Default: ``2.4188843e-1``, corresponding to ``1.0`` in
       `Meep <https://meep.readthedocs.io/en/latest/>`_ units when ``time_units_fs=0.1``.
   * - ``mu0``
     - Dipole-coordinate coupling prefactor :math:`\mu_{0}` in atomic units, so
       that the instantaneous dipole is :math:`\mu(t)=\mu_{0}\,q(t)`; scales the
       emitted source amplitude. Default: ``1.870819866e2``, corresponding to
       ``0.1`` in `Meep <https://meep.readthedocs.io/en/latest/>`_ units when
       ``time_units_fs=0.1``.
   * - ``orientation``
     - Dipole orientation: ``0`` couples to ``E_x``, ``1`` to ``E_y``, ``2`` to
       ``E_z``. Default: ``2``.
   * - ``p_initial``
     - Initial momentum :math:`p` of the oscillator in atomic units. Default: ``0.0``.
   * - ``q_initial``
     - Initial position :math:`q` of the oscillator in atomic units. Default: ``0.0``.
   * - ``checkpoint``
     - When ``True`` write ``sho_checkpoint_id_<n>.npz`` after each step. Default:
       ``False``.
   * - ``restart``
     - When ``True`` resume from the latest checkpoint if present. Default:
       ``False``.
   * - ``verbose``
     - When ``True`` print field values and oscillator diagnostics each step.
       Default: ``False``.

Returned data
-------------

- ``time_au`` – Simulation time in atomic units.
- ``energy_au`` – Instantaneous oscillator energy
  :math:`\tfrac{1}{2}\omega_0^{2} q^{2} + \tfrac{1}{2} p^{2}` in atomic units.
- ``mux_au``, ``muy_au``, ``muz_au`` – Dipole vector components (non-zero along the selected orientation) in atomic units.
- ``p_au`` – Oscillator momentum :math:`p` at the current step in atomic units.
- ``q_au`` – Oscillator position :math:`q` at the current step in atomic units.

Notes
-----

- The driver exposes a deterministic analytic evolution; see
  ``tests/test_sho/test_singlemode_sho_energy_conservation.py`` for a
  single-mode strong-coupling energy-conservation reference.
- This driver is intended for demonstration and benchmarking. For productive
  classical molecular dynamics, prefer the **LAMMPS** or **DFTB+** socket
  driver, or the **ASE** Python driver.
