Meep FDTD Solver ================ The :mod:`maxwelllink.em_solvers.meep` backend couples **MaxwellLink** molecules to `Meep `_ (``pymeep``) simulations. It wraps `meep.Simulation `_, converts between Meep units and atomic units, creates regularized polarization sources, and shuttles electric-field integrals and driver responses each time step. .. note:: The Meep backend advances the classical Maxwell equations .. math:: \partial_t \mathbf{D}(\mathbf{r}, t) = \nabla \times \mathbf{H}(\mathbf{r}, t) - \mathbf{J}_{\mathrm{mol}}(\mathbf{r}, t), \qquad \partial_t \mathbf{B}(\mathbf{r}, t) = - \nabla \times \mathbf{E}(\mathbf{r}, t), with constitutive relations :math:`\mathbf{D} = \varepsilon_0 \varepsilon^{\ast}_{\mathrm{r}}(\mathbf{r}, \omega)\, \mathbf{E}` and :math:`\mathbf{B} = \mu\, \mathbf{H}` (typically :math:`\mu = \mu_0`). Molecular sources enter through .. math:: \mathbf{J}_{\mathrm{mol}}(\mathbf{r}, t) = \sum_{m} \partial_t \mathbf{P}_{\mathrm{mol}}^{m}(\mathbf{r}, t), \qquad \mathbf{P}_{\mathrm{mol}}^{m}(\mathbf{r}, t) = \sum_{i=x,y,z} \gamma\, \mu_{m}^{i}(t)\, \boldsymbol{\kappa}_{m}^{i}(\mathbf{r}), where each spatial kernel :math:`\boldsymbol{\kappa}_{m}^{i}` is normalized over the molecular volume :math:`\Omega_m`. The solver supplies every coupled molecule with the regularized electric field .. math:: \widetilde{E}_{m}^{i}(t) = \int_{\Omega_m} d\mathbf{r}\, \mathbf{E}(\mathbf{r}, t) \cdot \boldsymbol{\kappa}_{m}^{i}(\mathbf{r}), and expects the returned dipole time derivative :math:`d\mu_{m}^{i}/dt` to reconstruct :math:`\mathbf{J}_{\mathrm{mol}}` self-consistently on the FDTD grid. Requirements ------------ - `pymeep` (imported as :mod:`meep`) must be installed. Import failures raise a clear :class:`ImportError`. - Optional `mpi4py` support is detected automatically. When present, only the Meep master rank communicates with the molecular drivers while amplitudes are broadcast to worker ranks. Usage ----- Socket mode ^^^^^^^^^^^ .. code-block:: python import meep as mp import maxwelllink as mxl from maxwelllink import sockets as mxs host, port = mxs.get_available_host_port() hub = mxl.SocketHub(host=host, port=port, timeout=10.0, latency=1e-5) molecule = mxl.Molecule( hub=hub, center=mp.Vector3(0, 0, 0), size=mp.Vector3(1, 1, 1), sigma=0.1, dimensions=2, ) sim = mxl.MeepSimulation( hub=hub, molecules=[molecule], time_units_fs=0.1, cell_size=mp.Vector3(8, 8, 0), geometry=[], sources=[], boundary_layers=[mp.PML(3.0)], resolution=10, ) # Launch the driver separately (e.g. mxl_driver --model tls --port ...) sim.run(until=90) Non-socket mode ^^^^^^^^^^^^^^^ .. code-block:: python import meep as mp import maxwelllink as mxl molecule = mxl.Molecule( driver="tls", driver_kwargs=dict( omega=0.242, mu12=187.0, orientation=2, pe_initial=1e-4, ), center=mp.Vector3(), size=mp.Vector3(1, 1, 1), sigma=0.1, dimensions=2, ) sim = mxl.MeepSimulation( molecules=[molecule], time_units_fs=0.1, cell_size=mp.Vector3(8, 8, 0), geometry=[], sources=[], boundary_layers=[mp.PML(3.0)], resolution=10, ) sim.run(until=90) **MaxwellLink** inserts the appropriate coupling step automatically: sockets when ``hub`` is provided, or embedded drivers otherwise. Parameters ---------- .. list-table:: :header-rows: 1 * - Name - Description * - ``hub`` - Optional :class:`~maxwelllink.sockets.sockets.SocketHub`. Required for socket-connected molecules; ignored for embedded drivers. * - ``molecules`` - Iterable of :class:`~maxwelllink.molecule.molecule.Molecule` instances. They are wrapped into :class:`~maxwelllink.em_solvers.meep.MoleculeMeepWrapper` and may mix socket and non-socket modes. * - ``time_units_fs`` - Meep time unit expressed in femtoseconds (default ``0.1``). Used to refresh molecular time steps and unit conversions. * - ``geometry`` - Sequence of Meep geometry objects forwarded to :class:`meep.Simulation`. * - ``sources`` - List of native Meep sources. Molecular sources are added automatically; this list is for additional excitations. * - ``cell_size`` - Simulation domain size passed to :class:`meep.Simulation`. * - ``boundary_layers`` - List of boundary conditions (for example ``[mp.PML(thickness)]``). * - ``resolution`` - Spatial resolution (pixels per distance unit). Used to derive ``dx`` and enforce ``Courant = 0.5``. * - ``**kwargs`` - Remaining keyword arguments are forwarded verbatim to :class:`meep.Simulation` (e.g. ``default_material``, ``k_point``, ``symmetries``). Returned data ------------- - ``sim.molecules`` – list of :class:`MoleculeMeepWrapper` instances. Each wrapper exposes the underlying :class:`~maxwelllink.molecule.molecule.Molecule`. - ``molecule.additional_data_history`` – diagnostics produced by the driver (time stamps, populations, energies, custom JSON payloads). - Standard Meep data channels remain available (e.g. ``sim.fields``, flux regions, near-to-far field monitors). - For debugging, ``maxwelllink.em_solvers.meep.instantaneous_source_amplitudes`` stores the most recent source amplitudes per polarization fingerprint. Notes ----- - :class:`MeepSimulation` enforces ``Courant = 0.5``. Provide ``resolution`` and other grid parameters accordingly. - MPI runs automatically confine socket communication to rank 0 while broadcasting amplitudes to all ranks; disconnections pause the solver until the hub reports reconnection.