meanas/README.md
2026-04-19 00:41:07 -07:00

228 lines
7.9 KiB
Markdown

# meanas
**meanas** is a python package for electromagnetic simulations
** UNSTABLE / WORK IN PROGRESS **
Formerly known as [fdfd_tools](https://mpxd.net/code/jan/fdfd_tools).
This package is intended for building simulation inputs, analyzing
simulation outputs, and running short simulations on unspecialized hardware.
It is designed to provide tooling and a baseline for other, high-performance
purpose- and hardware-specific solvers.
**Contents**
- Finite difference frequency domain (FDFD)
* Library of sparse matrices for representing the electromagnetic wave
equation in 3D, as well as auxiliary matrices for conversion between fields
* Waveguide mode operators
* Waveguide mode eigensolver
* Stretched-coordinate PML boundaries (SCPML)
* Functional versions of most operators
* Anisotropic media (limited to diagonal elements eps_xx, eps_yy, eps_zz, mu_xx, ...)
* Arbitrary distributions of perfect electric and magnetic conductors (PEC / PMC)
- Finite difference time domain (FDTD)
* Basic Maxwell time-steps
* Poynting vector and energy calculation
* Convolutional PMLs
This package does *not* provide a fast matrix solver, though by default
`meanas.fdfd.solvers.generic(...)` will call
`scipy.sparse.linalg.qmr(...)` to perform a solve.
For 2D FDFD problems this should be fine; likewise, the waveguide mode
solver uses scipy's eigenvalue solver, with reasonable results.
For solving large (or 3D) FDFD problems, I recommend a GPU-based iterative
solver, such as [opencl_fdfd](https://mpxd.net/code/jan/opencl_fdfd) or
those included in [MAGMA](http://icl.cs.utk.edu/magma/index.html). Your
solver will need the ability to solve complex symmetric (non-Hermitian)
linear systems, ideally with double precision.
- [Source repository](https://mpxd.net/code/jan/meanas)
- [PyPI](https://pypi.org/project/meanas)
- [Github mirror](https://github.com/anewusername/meanas)
## Installation
**Requirements:**
* python >=3.11
* numpy
* scipy
Install from PyPI with pip:
```bash
pip3 install meanas
```
Optional extras:
- `meanas[test]`: pytest and coverage
- `meanas[docs]`: MkDocs-based documentation toolchain
- `meanas[examples]`: optional runtime dependencies used by the tracked examples
- `meanas[dev]`: the union of `test`, `docs`, and `examples`, plus local lint/docs-publish helpers
Examples:
```bash
pip3 install 'meanas[test]'
pip3 install 'meanas[docs]'
pip3 install 'meanas[examples]'
pip3 install 'meanas[dev]'
```
### Development install
Install python3 and git:
```bash
# This is for Debian/Ubuntu/other-apt-based systems; you may need an alternative command
sudo apt install python3 build-essential python3-dev git
```
In-place development install:
```bash
# Download using git
git clone https://mpxd.net/code/jan/meanas.git
# If you'd like to create a virtualenv, do so:
python3 -m venv my_venv
# If you are using a virtualenv, activate it
source my_venv/bin/activate
# Install in-place (-e, editable) from ./meanas, including development dependencies ([dev])
pip3 install --user -e './meanas[dev]'
# Run tests
cd meanas
python3 -m pytest -rsxX | tee test_results.txt
```
#### See also:
- [git book](https://git-scm.com/book/en/v2)
- [venv documentation](https://docs.python.org/3/tutorial/venv.html)
- [python language reference](https://docs.python.org/3/reference/index.html)
- [python standard library](https://docs.python.org/3/library/index.html)
## Use
`meanas` is organized around a few core workflows:
- `meanas.fdfd`: frequency-domain wave equations, sparse operators, SCPML, and
iterative solves for driven problems.
- `meanas.fdfd.waveguide_2d` / `meanas.fdfd.waveguide_3d`: waveguide mode
solvers, mode-source construction, and overlap windows for port-based
excitation and analysis.
- `meanas.fdtd`: Yee-step updates, CPML boundaries, flux/energy accounting, and
on-the-fly phasor extraction for comparing time-domain runs against FDFD.
- `meanas.fdmath`: low-level finite-difference operators, vectorization helpers,
and derivations shared by the FDTD and FDFD layers.
The most mature user-facing workflows are:
1. Build an FDFD operator or waveguide port source, then solve a driven
frequency-domain problem.
2. Run an FDTD simulation, extract one or more frequency-domain phasors with
`meanas.fdtd.accumulate_phasor(...)`, and compare those phasors against an
FDFD reference on the same Yee grid.
## Documentation
API and workflow docs are generated from the package docstrings with
[MkDocs](https://www.mkdocs.org/), [Material for MkDocs](https://squidfunk.github.io/mkdocs-material/),
and [mkdocstrings](https://mkdocstrings.github.io/).
When hosted on a Forgejo instance, the intended setup is:
- publish the generated site from a dedicated `docs-site` branch
- serve that branch from the instance's static-pages host
- point the repository's **Wiki** tab at the published docs URL
This repository now uses a version-controlled wrapper script rather than a
Forgejo runner. After a successful `git push`, the wrapper builds the docs
locally and force-updates the `docs-site` branch from the same machine.
Use the wrapper instead of `git push` when publishing from your development
machine:
```bash
./scripts/push_with_docs.sh
```
It only auto-publishes after successful pushes of local `master` to `origin`.
For unusual refspecs or other remotes, push manually and publish the docs
branch separately if needed.
To persist the published docs URL for canonical MkDocs links in this clone, set
the local git config value with:
```bash
./scripts/configure_docs_url.sh 'https://docs.example.com/meanas/'
```
The wrapper will also respect a shell-level `DOCS_SITE_URL` override if one is
set.
Install the docs toolchain with:
```bash
pip3 install -e './meanas[docs]'
```
Then build the docs site with:
```bash
./make_docs.sh
```
This produces:
- a normal multi-page site under `site/`
- a combined printable single-page HTML site under `site/print_page/`
- an optional fully inlined `site/standalone.html` when `htmlark` is available
The version-controlled push wrapper publishes this same output to the
`docs-site` branch.
The docs build uses a local MathJax bundle vendored under `docs/assets/`, so
the rendered HTML does not rely on external services for equation rendering.
Tracked examples under `examples/` are the intended starting points:
- `examples/fdtd.py`: broadband FDTD pulse excitation, phasor extraction, and a
residual check against the matching FDFD operator.
- `examples/waveguide.py`: waveguide mode solving, unidirectional mode-source
construction, overlap readout, and FDTD/FDFD comparison on a guided structure.
- `examples/fdfd.py`: direct frequency-domain waveguide excitation and overlap /
Poynting analysis without a time-domain run.
Several examples rely on optional packages such as
[gridlock](https://mpxd.net/code/jan/gridlock).
### Frequency-domain waveguide workflow
For a structure with a constant cross-section in one direction:
1. Build `dxes` and the diagonal `epsilon` / `mu` distributions on the Yee grid.
2. Solve the port mode with `meanas.fdfd.waveguide_3d.solve_mode(...)`.
3. Build a unidirectional source with `compute_source(...)`.
4. Build a matching overlap window with `compute_overlap_e(...)`.
5. Solve the full FDFD problem and project the result onto the overlap window or
evaluate plane flux with `meanas.fdfd.functional.poynting_e_cross_h(...)`.
### Time-domain phasor workflow
For a broadband or continuous-wave FDTD run:
1. Advance the fields with `meanas.fdtd.maxwell_e/maxwell_h` or
`updates_with_cpml(...)`.
2. Inject electric current using the same sign convention used throughout the
examples and library: `E -= dt * J / epsilon`.
3. Accumulate the desired phasor with `accumulate_phasor(...)` or the Yee-aware
wrappers `accumulate_phasor_e/h/j(...)`.
4. Build the matching FDFD operator on the stretched `dxes` if CPML/SCPML is
part of the simulation, and compare the extracted phasor to the FDFD field or
residual.