witwin-maxwell 0.0.1__tar.gz → 0.2.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- witwin_maxwell-0.2.0/.github/workflows/publish-witwin-maxwell.yml +285 -0
- {witwin_maxwell-0.0.1 → witwin_maxwell-0.2.0}/.gitignore +4 -0
- {witwin_maxwell-0.0.1 → witwin_maxwell-0.2.0}/FEATURE_LIST.md +119 -13
- {witwin_maxwell-0.0.1 → witwin_maxwell-0.2.0}/PKG-INFO +82 -93
- {witwin_maxwell-0.0.1 → witwin_maxwell-0.2.0}/README.md +76 -91
- witwin_maxwell-0.2.0/benchmark/FDFD_PERFORMANCE.md +13 -0
- {witwin_maxwell-0.0.1 → witwin_maxwell-0.2.0}/benchmark/RESULTS.md +15 -15
- witwin_maxwell-0.2.0/benchmark/fdfd_performance.py +324 -0
- witwin_maxwell-0.2.0/docs/dev/fdtd/native_cuda/bench_baseline.py +160 -0
- witwin_maxwell-0.2.0/docs/dev/fdtd/native_cuda/kernel_mapping.md +42 -0
- witwin_maxwell-0.2.0/docs/dev/fdtd/native_cuda/parity_matrix.md +31 -0
- witwin_maxwell-0.2.0/docs/dev/fdtd/native_cuda/profile_scenario.py +24 -0
- witwin_maxwell-0.2.0/docs/dev/fdtd/native_cuda/profiling_baseline.md +173 -0
- witwin_maxwell-0.2.0/docs/dev/fdtd/native_cuda/snapshot_tool.py +189 -0
- witwin_maxwell-0.2.0/docs/dev/grating-tfsf-bloch-pml-notes.md +41 -0
- witwin_maxwell-0.2.0/hatch_build.py +17 -0
- witwin_maxwell-0.2.0/pyproject.toml +38 -0
- witwin_maxwell-0.2.0/scripts/build_fdtd_cuda_prebuilt.py +68 -0
- {witwin_maxwell-0.0.1 → witwin_maxwell-0.2.0}/tests/TEST_LAYOUT.md +1 -0
- witwin_maxwell-0.2.0/tests/api/adapters/gds/test_gds_adapter.py +213 -0
- {witwin_maxwell-0.0.1 → witwin_maxwell-0.2.0}/tests/api/adapters/tidy3d/test_tidy3d_adapter.py +35 -0
- {witwin_maxwell-0.0.1 → witwin_maxwell-0.2.0}/tests/api/public/test_public_api.py +7 -5
- {witwin_maxwell-0.0.1 → witwin_maxwell-0.2.0}/tests/api/public/test_simulation_smoke.py +2 -2
- witwin_maxwell-0.2.0/tests/boundaries/absorbers/test_boundary_variants.py +158 -0
- {witwin_maxwell-0.0.1 → witwin_maxwell-0.2.0}/tests/boundaries/boundary_physics/test_fdtd_boundary_physics.py +134 -0
- witwin_maxwell-0.2.0/tests/boundaries/boundary_physics/test_fdtd_pec_material.py +65 -0
- {witwin_maxwell-0.0.1 → witwin_maxwell-0.2.0}/tests/boundaries/boundary_specs/test_fdtd_boundaries.py +23 -10
- {witwin_maxwell-0.0.1 → witwin_maxwell-0.2.0}/tests/boundaries/cpml/test_fdtd_cpml.py +12 -12
- witwin_maxwell-0.2.0/tests/boundaries/symmetry/test_symmetry_generalization.py +256 -0
- witwin_maxwell-0.2.0/tests/core/grid/test_autogrid.py +482 -0
- witwin_maxwell-0.2.0/tests/core/grid/test_gridspec_custom.py +283 -0
- witwin_maxwell-0.2.0/tests/core/grid/test_nonuniform_placement.py +146 -0
- witwin_maxwell-0.2.0/tests/core/grid/test_nonuniform_uniform_equivalence.py +197 -0
- {witwin_maxwell-0.0.1 → witwin_maxwell-0.2.0}/tests/core/scene/test_scene.py +44 -1
- witwin_maxwell-0.2.0/tests/fdfd/test_ams.py +80 -0
- witwin_maxwell-0.2.0/tests/fdfd/test_direct_solver.py +100 -0
- witwin_maxwell-0.2.0/tests/fdfd/test_krylov.py +130 -0
- witwin_maxwell-0.2.0/tests/fdfd/test_matrix_cache.py +102 -0
- witwin_maxwell-0.2.0/tests/fdfd/test_preconditioners.py +70 -0
- witwin_maxwell-0.2.0/tests/fdfd/test_symmetric_formulation.py +91 -0
- witwin_maxwell-0.2.0/tests/fdtd/cuda/_parity_backend.py +30 -0
- witwin_maxwell-0.2.0/tests/fdtd/cuda/test_cuda_adjoint_parity.py +1275 -0
- witwin_maxwell-0.2.0/tests/fdtd/cuda/test_cuda_common_parity.py +218 -0
- witwin_maxwell-0.2.0/tests/fdtd/cuda/test_cuda_cpml_extension_parity.py +346 -0
- witwin_maxwell-0.2.0/tests/fdtd/cuda/test_cuda_dispersive_parity.py +168 -0
- witwin_maxwell-0.2.0/tests/fdtd/cuda/test_cuda_electric_boundary_parity.py +321 -0
- witwin_maxwell-0.2.0/tests/fdtd/cuda/test_cuda_extension_load.py +58 -0
- witwin_maxwell-0.2.0/tests/fdtd/cuda/test_cuda_graph.py +37 -0
- witwin_maxwell-0.2.0/tests/fdtd/cuda/test_cuda_magnetic_parity.py +256 -0
- witwin_maxwell-0.2.0/tests/fdtd/cuda/test_cuda_sources_parity.py +775 -0
- witwin_maxwell-0.2.0/tests/fdtd/cuda/test_cuda_spectral_observer_parity.py +193 -0
- witwin_maxwell-0.2.0/tests/fdtd/cuda/torch_reference.py +3248 -0
- witwin_maxwell-0.2.0/tests/fdtd/test_cuda_graph.py +111 -0
- witwin_maxwell-0.2.0/tests/fdtd/test_fdtd_autoshutoff.py +121 -0
- witwin_maxwell-0.2.0/tests/gradients/test_fdfd_adjoint.py +137 -0
- {witwin_maxwell-0.0.1 → witwin_maxwell-0.2.0}/tests/gradients/test_fdtd_adjoint_bridge.py +213 -446
- {witwin_maxwell-0.0.1 → witwin_maxwell-0.2.0}/tests/gradients/test_fdtd_adjoint_rigorous.py +69 -1
- {witwin_maxwell-0.0.1 → witwin_maxwell-0.2.0}/tests/gradients/test_fdtd_mode_source_adjoint.py +56 -14
- {witwin_maxwell-0.0.1 → witwin_maxwell-0.2.0}/tests/materials/compiler/test_material_compiler.py +29 -0
- witwin_maxwell-0.2.0/tests/materials/compiler/test_pec_material.py +95 -0
- witwin_maxwell-0.2.0/tests/materials/compiler/test_polarized_averaging.py +58 -0
- witwin_maxwell-0.2.0/tests/materials/compiler/test_polyslab.py +196 -0
- witwin_maxwell-0.2.0/tests/materials/compiler/test_subpixel_gradients.py +58 -0
- witwin_maxwell-0.2.0/tests/materials/compiler/test_subpixel_normals.py +34 -0
- witwin_maxwell-0.2.0/tests/materials/compiler/test_subpixel_spec.py +67 -0
- witwin_maxwell-0.2.0/tests/materials/conductive/test_fdtd_conductive.py +214 -0
- witwin_maxwell-0.2.0/tests/monitors/diffraction/test_diffraction_monitor.py +334 -0
- witwin_maxwell-0.2.0/tests/monitors/emission/test_dipole_emission_monitor.py +179 -0
- witwin_maxwell-0.2.0/tests/monitors/material/test_permittivity_monitor.py +222 -0
- witwin_maxwell-0.2.0/tests/monitors/time/test_fdtd_time_monitors.py +255 -0
- {witwin_maxwell-0.0.1 → witwin_maxwell-0.2.0}/tests/postprocess/scattering/test_mode_overlap.py +17 -11
- witwin_maxwell-0.2.0/tests/sources/definitions/test_astigmatic_gaussian_beam.py +203 -0
- witwin_maxwell-0.2.0/tests/sources/definitions/test_custom_source_time.py +222 -0
- witwin_maxwell-0.2.0/tests/sources/definitions/test_custom_uniform_sources.py +245 -0
- {witwin_maxwell-0.0.1 → witwin_maxwell-0.2.0}/tests/sources/definitions/test_sources.py +39 -0
- {witwin_maxwell-0.0.1 → witwin_maxwell-0.2.0}/tests/sources/mode/test_mode_solver_gradients.py +10 -2
- witwin_maxwell-0.2.0/tests/sources/tfsf/test_fdtd_grating_tfsf.py +561 -0
- {witwin_maxwell-0.0.1 → witwin_maxwell-0.2.0}/tests/sources/tfsf/test_fdtd_tfsf.py +24 -24
- witwin_maxwell-0.2.0/tests/validation/benchmark/test_fdfd_performance.py +27 -0
- {witwin_maxwell-0.0.1 → witwin_maxwell-0.2.0}/tests/validation/cross_solver/test_fdfd_vs_fdtd.py +49 -4
- witwin_maxwell-0.2.0/tests/validation/physics/test_autogrid_physics.py +160 -0
- {witwin_maxwell-0.0.1 → witwin_maxwell-0.2.0}/tests/validation/physics/test_fdtd_boundary_tfsf_validation.py +88 -15
- witwin_maxwell-0.2.0/tests/validation/physics/test_nonuniform_grid_physics.py +178 -0
- witwin_maxwell-0.2.0/tests/validation/physics/test_pec_conformal.py +90 -0
- {witwin_maxwell-0.0.1 → witwin_maxwell-0.2.0}/witwin/maxwell/__init__.py +62 -3
- witwin_maxwell-0.2.0/witwin/maxwell/adapters/gds.py +203 -0
- {witwin_maxwell-0.0.1 → witwin_maxwell-0.2.0}/witwin/maxwell/adapters/tidy3d.py +14 -2
- witwin_maxwell-0.2.0/witwin/maxwell/adjoint_inputs.py +66 -0
- {witwin_maxwell-0.0.1 → witwin_maxwell-0.2.0}/witwin/maxwell/compiler/__init__.py +2 -1
- {witwin_maxwell-0.0.1 → witwin_maxwell-0.2.0}/witwin/maxwell/compiler/materials.py +157 -29
- witwin_maxwell-0.2.0/witwin/maxwell/compiler/monitors.py +164 -0
- {witwin_maxwell-0.0.1 → witwin_maxwell-0.2.0}/witwin/maxwell/compiler/sources.py +94 -2
- witwin_maxwell-0.2.0/witwin/maxwell/fdfd/adjoint/__init__.py +3 -0
- witwin_maxwell-0.2.0/witwin/maxwell/fdfd/adjoint/bridge.py +178 -0
- witwin_maxwell-0.2.0/witwin/maxwell/fdfd/ams.py +300 -0
- witwin_maxwell-0.2.0/witwin/maxwell/fdfd/krylov.py +280 -0
- {witwin_maxwell-0.0.1 → witwin_maxwell-0.2.0}/witwin/maxwell/fdfd/solver.py +393 -158
- {witwin_maxwell-0.0.1 → witwin_maxwell-0.2.0}/witwin/maxwell/fdtd/adjoint/bridge.py +22 -55
- {witwin_maxwell-0.0.1 → witwin_maxwell-0.2.0}/witwin/maxwell/fdtd/adjoint/core.py +486 -1163
- {witwin_maxwell-0.0.1 → witwin_maxwell-0.2.0}/witwin/maxwell/fdtd/adjoint/dispatch.py +127 -105
- {witwin_maxwell-0.0.1 → witwin_maxwell-0.2.0}/witwin/maxwell/fdtd/adjoint/reference.py +130 -157
- {witwin_maxwell-0.0.1 → witwin_maxwell-0.2.0}/witwin/maxwell/fdtd/adjoint/reverse_common.py +19 -31
- witwin_maxwell-0.2.0/witwin/maxwell/fdtd/boundary/bloch.py +90 -0
- {witwin_maxwell-0.0.1 → witwin_maxwell-0.2.0}/witwin/maxwell/fdtd/boundary/common.py +3 -0
- {witwin_maxwell-0.0.1 → witwin_maxwell-0.2.0}/witwin/maxwell/fdtd/boundary/cpml.py +188 -112
- witwin_maxwell-0.2.0/witwin/maxwell/fdtd/boundary/runtime.py +209 -0
- {witwin_maxwell-0.0.1 → witwin_maxwell-0.2.0}/witwin/maxwell/fdtd/checkpoint.py +7 -2
- witwin_maxwell-0.2.0/witwin/maxwell/fdtd/coords.py +32 -0
- witwin_maxwell-0.2.0/witwin/maxwell/fdtd/cuda/__init__.py +11 -0
- witwin_maxwell-0.2.0/witwin/maxwell/fdtd/cuda/backend.py +2520 -0
- witwin_maxwell-0.2.0/witwin/maxwell/fdtd/cuda/build.py +242 -0
- witwin_maxwell-0.2.0/witwin/maxwell/fdtd/cuda/extension.cpp +1235 -0
- witwin_maxwell-0.2.0/witwin/maxwell/fdtd/cuda/kernels/adjoint.cu +3244 -0
- witwin_maxwell-0.2.0/witwin/maxwell/fdtd/cuda/kernels/boundary.cu +354 -0
- witwin_maxwell-0.2.0/witwin/maxwell/fdtd/cuda/kernels/common.cu +63 -0
- witwin_maxwell-0.2.0/witwin/maxwell/fdtd/cuda/kernels/common.cuh +82 -0
- witwin_maxwell-0.2.0/witwin/maxwell/fdtd/cuda/kernels/dispersive.cu +475 -0
- witwin_maxwell-0.2.0/witwin/maxwell/fdtd/cuda/kernels/electric.cu +2298 -0
- witwin_maxwell-0.2.0/witwin/maxwell/fdtd/cuda/kernels/magnetic.cu +981 -0
- witwin_maxwell-0.2.0/witwin/maxwell/fdtd/cuda/kernels/observers.cu +350 -0
- witwin_maxwell-0.2.0/witwin/maxwell/fdtd/cuda/kernels/projection.cu +214 -0
- witwin_maxwell-0.2.0/witwin/maxwell/fdtd/cuda/kernels/sources.cu +1485 -0
- witwin_maxwell-0.2.0/witwin/maxwell/fdtd/cuda/kernels/spectral.cu +300 -0
- witwin_maxwell-0.2.0/witwin/maxwell/fdtd/cuda/launch.h +16 -0
- witwin_maxwell-0.2.0/witwin/maxwell/fdtd/cuda/runtime/__init__.py +6 -0
- witwin_maxwell-0.2.0/witwin/maxwell/fdtd/cuda/runtime/dispatcher.py +6 -0
- witwin_maxwell-0.2.0/witwin/maxwell/fdtd/cuda/runtime/graph.py +33 -0
- witwin_maxwell-0.2.0/witwin/maxwell/fdtd/cuda/runtime/parity.py +9 -0
- witwin_maxwell-0.2.0/witwin/maxwell/fdtd/cuda/tensors.h +22 -0
- witwin_maxwell-0.2.0/witwin/maxwell/fdtd/dispersion.py +48 -0
- {witwin_maxwell-0.0.1 → witwin_maxwell-0.2.0}/witwin/maxwell/fdtd/excitation/injection.py +295 -33
- {witwin_maxwell-0.0.1 → witwin_maxwell-0.2.0}/witwin/maxwell/fdtd/excitation/modes.py +28 -8
- {witwin_maxwell-0.0.1 → witwin_maxwell-0.2.0}/witwin/maxwell/fdtd/excitation/spatial.py +134 -31
- {witwin_maxwell-0.0.1 → witwin_maxwell-0.2.0}/witwin/maxwell/fdtd/excitation/temporal.py +170 -59
- {witwin_maxwell-0.0.1 → witwin_maxwell-0.2.0}/witwin/maxwell/fdtd/excitation/tfsf_apply.py +5 -0
- {witwin_maxwell-0.0.1 → witwin_maxwell-0.2.0}/witwin/maxwell/fdtd/excitation/tfsf_common.py +98 -53
- {witwin_maxwell-0.0.1 → witwin_maxwell-0.2.0}/witwin/maxwell/fdtd/excitation/tfsf_specs.py +49 -29
- {witwin_maxwell-0.0.1 → witwin_maxwell-0.2.0}/witwin/maxwell/fdtd/excitation/tfsf_state.py +219 -32
- witwin_maxwell-0.2.0/witwin/maxwell/fdtd/meshing/__init__.py +3 -0
- witwin_maxwell-0.2.0/witwin/maxwell/fdtd/meshing/autogrid.py +313 -0
- {witwin_maxwell-0.0.1 → witwin_maxwell-0.2.0}/witwin/maxwell/fdtd/observers.py +336 -1
- {witwin_maxwell-0.0.1 → witwin_maxwell-0.2.0}/witwin/maxwell/fdtd/runtime/__init__.py +4 -0
- {witwin_maxwell-0.0.1 → witwin_maxwell-0.2.0}/witwin/maxwell/fdtd/runtime/initialization.py +18 -14
- {witwin_maxwell-0.0.1 → witwin_maxwell-0.2.0}/witwin/maxwell/fdtd/runtime/materials.py +83 -18
- witwin_maxwell-0.2.0/witwin/maxwell/fdtd/runtime/module_cache.py +31 -0
- {witwin_maxwell-0.0.1 → witwin_maxwell-0.2.0}/witwin/maxwell/fdtd/runtime/spectral.py +119 -0
- witwin_maxwell-0.2.0/witwin/maxwell/fdtd/runtime/stepping.py +1213 -0
- {witwin_maxwell-0.0.1 → witwin_maxwell-0.2.0}/witwin/maxwell/fdtd/solver.py +55 -32
- {witwin_maxwell-0.0.1 → witwin_maxwell-0.2.0}/witwin/maxwell/media.py +26 -0
- {witwin_maxwell-0.0.1 → witwin_maxwell-0.2.0}/witwin/maxwell/monitors.py +250 -0
- {witwin_maxwell-0.0.1 → witwin_maxwell-0.2.0}/witwin/maxwell/postprocess/__init__.py +5 -0
- witwin_maxwell-0.2.0/witwin/maxwell/postprocess/diffraction.py +219 -0
- witwin_maxwell-0.2.0/witwin/maxwell/postprocess/emission.py +67 -0
- {witwin_maxwell-0.0.1 → witwin_maxwell-0.2.0}/witwin/maxwell/postprocess/modal.py +0 -3
- {witwin_maxwell-0.0.1 → witwin_maxwell-0.2.0}/witwin/maxwell/result.py +174 -7
- {witwin_maxwell-0.0.1 → witwin_maxwell-0.2.0}/witwin/maxwell/scene.py +351 -40
- {witwin_maxwell-0.0.1 → witwin_maxwell-0.2.0}/witwin/maxwell/simulation.py +55 -0
- {witwin_maxwell-0.0.1 → witwin_maxwell-0.2.0}/witwin/maxwell/sources.py +379 -5
- {witwin_maxwell-0.0.1 → witwin_maxwell-0.2.0}/witwin/maxwell/visualization/__init__.py +9 -1
- {witwin_maxwell-0.0.1 → witwin_maxwell-0.2.0}/witwin/maxwell/visualization/interactive.py +4 -1
- witwin_maxwell-0.0.1/.claude/settings.json +0 -16
- witwin_maxwell-0.0.1/.github/workflows/publish-witwin-maxwell.yml +0 -93
- witwin_maxwell-0.0.1/pyproject.toml +0 -23
- witwin_maxwell-0.0.1/witwin/maxwell/compiler/monitors.py +0 -73
- witwin_maxwell-0.0.1/witwin/maxwell/fdtd/adjoint/.kernels_runtime_1773795042135987100_57071.slang +0 -2090
- witwin_maxwell-0.0.1/witwin/maxwell/fdtd/adjoint/.kernels_runtime_1773800541701589400_57074.slang +0 -2090
- witwin_maxwell-0.0.1/witwin/maxwell/fdtd/adjoint/kernels.slang +0 -2090
- witwin_maxwell-0.0.1/witwin/maxwell/fdtd/boundary/helpers.slang +0 -218
- witwin_maxwell-0.0.1/witwin/maxwell/fdtd/boundary/projection.slang +0 -134
- witwin_maxwell-0.0.1/witwin/maxwell/fdtd/boundary/runtime.py +0 -83
- witwin_maxwell-0.0.1/witwin/maxwell/fdtd/boundary/update.slang +0 -1866
- witwin_maxwell-0.0.1/witwin/maxwell/fdtd/coords.py +0 -45
- witwin_maxwell-0.0.1/witwin/maxwell/fdtd/fdtd.slang +0 -9
- witwin_maxwell-0.0.1/witwin/maxwell/fdtd/kernels/common.slang +0 -54
- witwin_maxwell-0.0.1/witwin/maxwell/fdtd/kernels/dispersive.slang +0 -375
- witwin_maxwell-0.0.1/witwin/maxwell/fdtd/kernels/magnetic.slang +0 -223
- witwin_maxwell-0.0.1/witwin/maxwell/fdtd/kernels/sources.slang +0 -640
- witwin_maxwell-0.0.1/witwin/maxwell/fdtd/kernels/spectral.slang +0 -178
- witwin_maxwell-0.0.1/witwin/maxwell/fdtd/runtime/module_cache.py +0 -49
- witwin_maxwell-0.0.1/witwin/maxwell/fdtd/runtime/stepping.py +0 -699
- {witwin_maxwell-0.0.1 → witwin_maxwell-0.2.0}/COPYING +0 -0
- {witwin_maxwell-0.0.1 → witwin_maxwell-0.2.0}/assets/teapot.obj +0 -0
- {witwin_maxwell-0.0.1 → witwin_maxwell-0.2.0}/benchmark/__init__.py +0 -0
- {witwin_maxwell-0.0.1 → witwin_maxwell-0.2.0}/benchmark/__main__.py +0 -0
- {witwin_maxwell-0.0.1 → witwin_maxwell-0.2.0}/benchmark/cache.py +0 -0
- {witwin_maxwell-0.0.1 → witwin_maxwell-0.2.0}/benchmark/metrics.py +0 -0
- {witwin_maxwell-0.0.1 → witwin_maxwell-0.2.0}/benchmark/models.py +0 -0
- {witwin_maxwell-0.0.1 → witwin_maxwell-0.2.0}/benchmark/paths.py +0 -0
- {witwin_maxwell-0.0.1 → witwin_maxwell-0.2.0}/benchmark/plotting.py +0 -0
- {witwin_maxwell-0.0.1 → witwin_maxwell-0.2.0}/benchmark/report.py +0 -0
- {witwin_maxwell-0.0.1 → witwin_maxwell-0.2.0}/benchmark/runner.py +0 -0
- {witwin_maxwell-0.0.1 → witwin_maxwell-0.2.0}/benchmark/scenes/__init__.py +0 -0
- {witwin_maxwell-0.0.1 → witwin_maxwell-0.2.0}/benchmark/scenes/_common.py +0 -0
- {witwin_maxwell-0.0.1 → witwin_maxwell-0.2.0}/benchmark/scenes/dipole/__init__.py +0 -0
- {witwin_maxwell-0.0.1 → witwin_maxwell-0.2.0}/benchmark/scenes/dipole/dipole_dielectric_box.py +0 -0
- {witwin_maxwell-0.0.1 → witwin_maxwell-0.2.0}/benchmark/scenes/dipole/dipole_dielectric_sphere.py +0 -0
- {witwin_maxwell-0.0.1 → witwin_maxwell-0.2.0}/benchmark/scenes/dipole/dipole_ey.py +0 -0
- {witwin_maxwell-0.0.1 → witwin_maxwell-0.2.0}/benchmark/scenes/dipole/dipole_offcenter.py +0 -0
- {witwin_maxwell-0.0.1 → witwin_maxwell-0.2.0}/benchmark/scenes/dipole/dipole_two_freq.py +0 -0
- {witwin_maxwell-0.0.1 → witwin_maxwell-0.2.0}/benchmark/scenes/dipole/dipole_vacuum.py +0 -0
- {witwin_maxwell-0.0.1 → witwin_maxwell-0.2.0}/benchmark/scenes/dipole/high_eps_box.py +0 -0
- {witwin_maxwell-0.0.1 → witwin_maxwell-0.2.0}/benchmark/scenes/dipole/lorentz_resonator.py +0 -0
- {witwin_maxwell-0.0.1 → witwin_maxwell-0.2.0}/benchmark/scenes/dipole/multi_dielectric.py +0 -0
- {witwin_maxwell-0.0.1 → witwin_maxwell-0.2.0}/benchmark/scenes/planewave/__init__.py +0 -0
- {witwin_maxwell-0.0.1 → witwin_maxwell-0.2.0}/benchmark/scenes/planewave/dielectric_slab.py +0 -0
- {witwin_maxwell-0.0.1 → witwin_maxwell-0.2.0}/benchmark/scenes/planewave/dielectric_sphere.py +0 -0
- {witwin_maxwell-0.0.1 → witwin_maxwell-0.2.0}/benchmark/scenes/planewave/metal_sphere.py +0 -0
- {witwin_maxwell-0.0.1 → witwin_maxwell-0.2.0}/benchmark/scenes/planewave/planewave_dielectric_sphere.py +0 -0
- {witwin_maxwell-0.0.1 → witwin_maxwell-0.2.0}/benchmark/scenes/planewave/planewave_vacuum.py +0 -0
- {witwin_maxwell-0.0.1 → witwin_maxwell-0.2.0}/benchmark/tidy3d_scene.py +0 -0
- {witwin_maxwell-0.0.1 → witwin_maxwell-0.2.0}/tests/__init__.py +0 -0
- {witwin_maxwell-0.0.1 → witwin_maxwell-0.2.0}/tests/assets/cube.obj +0 -0
- {witwin_maxwell-0.0.1 → witwin_maxwell-0.2.0}/tests/assets/teapot.obj +0 -0
- {witwin_maxwell-0.0.1 → witwin_maxwell-0.2.0}/tests/conftest.py +0 -0
- {witwin_maxwell-0.0.1 → witwin_maxwell-0.2.0}/tests/core/geometry/test_mesh_geometry.py +0 -0
- {witwin_maxwell-0.0.1 → witwin_maxwell-0.2.0}/tests/core/grid/test_fdtd_coords.py +0 -0
- {witwin_maxwell-0.0.1 → witwin_maxwell-0.2.0}/tests/gradients/README.md +0 -0
- {witwin_maxwell-0.0.1 → witwin_maxwell-0.2.0}/tests/gradients/__init__.py +0 -0
- {witwin_maxwell-0.0.1 → witwin_maxwell-0.2.0}/tests/gradients/fdtd_adjoint_baselines.py +0 -0
- {witwin_maxwell-0.0.1 → witwin_maxwell-0.2.0}/tests/materials/compiler/test_fdfd_material_support.py +0 -0
- {witwin_maxwell-0.0.1 → witwin_maxwell-0.2.0}/tests/materials/dispersive/test_fdtd_dispersive.py +0 -0
- {witwin_maxwell-0.0.1 → witwin_maxwell-0.2.0}/tests/monitors/observers/test_fdtd_observers.py +0 -0
- {witwin_maxwell-0.0.1 → witwin_maxwell-0.2.0}/tests/postprocess/directivity/test_directivity.py +0 -0
- {witwin_maxwell-0.0.1 → witwin_maxwell-0.2.0}/tests/postprocess/evaluation/test_fdtd_evaluation.py +0 -0
- {witwin_maxwell-0.0.1 → witwin_maxwell-0.2.0}/tests/postprocess/rcs/test_postprocess.py +0 -0
- {witwin_maxwell-0.0.1 → witwin_maxwell-0.2.0}/tests/postprocess/scattering/test_scattering_parameters.py +0 -0
- {witwin_maxwell-0.0.1 → witwin_maxwell-0.2.0}/tests/sources/incident/test_fdtd_incident.py +0 -0
- {witwin_maxwell-0.0.1 → witwin_maxwell-0.2.0}/tests/sources/mode/test_fdtd_mode_source.py +0 -0
- {witwin_maxwell-0.0.1 → witwin_maxwell-0.2.0}/tests/sources/point/test_fdtd_source_normalization.py +0 -0
- {witwin_maxwell-0.0.1 → witwin_maxwell-0.2.0}/tests/sources/point/test_fdtd_sources.py +0 -0
- {witwin_maxwell-0.0.1 → witwin_maxwell-0.2.0}/tests/validation/benchmark/test_benchmark_system.py +0 -0
- {witwin_maxwell-0.0.1 → witwin_maxwell-0.2.0}/tests/validation/physics/test_fdtd_physics_correctness.py +0 -0
- {witwin_maxwell-0.0.1 → witwin_maxwell-0.2.0}/tests/validation/physics/test_postprocess_end_to_end_validation.py +0 -0
- {witwin_maxwell-0.0.1 → witwin_maxwell-0.2.0}/witwin/maxwell/adapters/__init__.py +0 -0
- {witwin_maxwell-0.0.1 → witwin_maxwell-0.2.0}/witwin/maxwell/fdfd/__init__.py +0 -0
- {witwin_maxwell-0.0.1 → witwin_maxwell-0.2.0}/witwin/maxwell/fdfd/plotting.py +0 -0
- {witwin_maxwell-0.0.1 → witwin_maxwell-0.2.0}/witwin/maxwell/fdfd/postprocess.py +0 -0
- {witwin_maxwell-0.0.1 → witwin_maxwell-0.2.0}/witwin/maxwell/fdtd/__init__.py +0 -0
- {witwin_maxwell-0.0.1 → witwin_maxwell-0.2.0}/witwin/maxwell/fdtd/adjoint/__init__.py +0 -0
- {witwin_maxwell-0.0.1 → witwin_maxwell-0.2.0}/witwin/maxwell/fdtd/adjoint/profiler.py +0 -0
- {witwin_maxwell-0.0.1 → witwin_maxwell-0.2.0}/witwin/maxwell/fdtd/adjoint/seeds.py +0 -0
- {witwin_maxwell-0.0.1 → witwin_maxwell-0.2.0}/witwin/maxwell/fdtd/boundary/__init__.py +0 -0
- {witwin_maxwell-0.0.1 → witwin_maxwell-0.2.0}/witwin/maxwell/fdtd/evaluation.py +0 -0
- {witwin_maxwell-0.0.1 → witwin_maxwell-0.2.0}/witwin/maxwell/fdtd/excitation/__init__.py +0 -0
- {witwin_maxwell-0.0.1 → witwin_maxwell-0.2.0}/witwin/maxwell/fdtd/io.py +0 -0
- {witwin_maxwell-0.0.1 → witwin_maxwell-0.2.0}/witwin/maxwell/fdtd/material_pullback.py +0 -0
- {witwin_maxwell-0.0.1 → witwin_maxwell-0.2.0}/witwin/maxwell/fdtd/plotting.py +0 -0
- {witwin_maxwell-0.0.1 → witwin_maxwell-0.2.0}/witwin/maxwell/fdtd/postprocess.py +0 -0
- {witwin_maxwell-0.0.1 → witwin_maxwell-0.2.0}/witwin/maxwell/materials.py +0 -0
- {witwin_maxwell-0.0.1 → witwin_maxwell-0.2.0}/witwin/maxwell/ports.py +0 -0
- {witwin_maxwell-0.0.1 → witwin_maxwell-0.2.0}/witwin/maxwell/postprocess/RCS.py +0 -0
- {witwin_maxwell-0.0.1 → witwin_maxwell-0.2.0}/witwin/maxwell/postprocess/directivity.py +0 -0
- {witwin_maxwell-0.0.1 → witwin_maxwell-0.2.0}/witwin/maxwell/postprocess/nfft.py +0 -0
- {witwin_maxwell-0.0.1 → witwin_maxwell-0.2.0}/witwin/maxwell/postprocess/scattering_parameters.py +0 -0
- {witwin_maxwell-0.0.1 → witwin_maxwell-0.2.0}/witwin/maxwell/postprocess/stratton_chu.py +0 -0
- {witwin_maxwell-0.0.1 → witwin_maxwell-0.2.0}/witwin/maxwell/visualization/plots.py +0 -0
|
@@ -0,0 +1,285 @@
|
|
|
1
|
+
name: Build and publish witwin-maxwell
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches:
|
|
6
|
+
- master
|
|
7
|
+
- "codex/**"
|
|
8
|
+
pull_request:
|
|
9
|
+
release:
|
|
10
|
+
types: [published]
|
|
11
|
+
workflow_dispatch:
|
|
12
|
+
|
|
13
|
+
jobs:
|
|
14
|
+
validate_release:
|
|
15
|
+
if: github.event_name != 'release' || (startsWith(github.event.release.tag_name, 'witwin-maxwell-v') && !github.event.release.prerelease)
|
|
16
|
+
name: Validate release
|
|
17
|
+
runs-on: ubuntu-latest
|
|
18
|
+
outputs:
|
|
19
|
+
package_dir: ${{ steps.package_dir.outputs.path }}
|
|
20
|
+
|
|
21
|
+
steps:
|
|
22
|
+
- name: Check out repository
|
|
23
|
+
uses: actions/checkout@v4
|
|
24
|
+
|
|
25
|
+
- name: Set up Python
|
|
26
|
+
uses: actions/setup-python@v5
|
|
27
|
+
with:
|
|
28
|
+
python-version: "3.11"
|
|
29
|
+
|
|
30
|
+
- name: Resolve package directory
|
|
31
|
+
id: package_dir
|
|
32
|
+
shell: bash
|
|
33
|
+
run: |
|
|
34
|
+
if [ -f pyproject.toml ]; then
|
|
35
|
+
echo "path=." >> "$GITHUB_OUTPUT"
|
|
36
|
+
elif [ -f maxwell/pyproject.toml ]; then
|
|
37
|
+
echo "path=maxwell" >> "$GITHUB_OUTPUT"
|
|
38
|
+
else
|
|
39
|
+
echo "Unable to find pyproject.toml for the witwin-maxwell package." >&2
|
|
40
|
+
exit 1
|
|
41
|
+
fi
|
|
42
|
+
|
|
43
|
+
- name: Validate release tag and package version
|
|
44
|
+
if: github.event_name == 'release'
|
|
45
|
+
shell: bash
|
|
46
|
+
env:
|
|
47
|
+
PACKAGE_DIR: ${{ steps.package_dir.outputs.path }}
|
|
48
|
+
RELEASE_TAG: ${{ github.event.release.tag_name }}
|
|
49
|
+
run: |
|
|
50
|
+
python - <<'PY'
|
|
51
|
+
import os
|
|
52
|
+
import re
|
|
53
|
+
import sys
|
|
54
|
+
import tomllib
|
|
55
|
+
from pathlib import Path
|
|
56
|
+
|
|
57
|
+
tag = os.environ["RELEASE_TAG"]
|
|
58
|
+
match = re.fullmatch(r"witwin-maxwell-v(?P<version>[0-9A-Za-z.+_-]+)", tag)
|
|
59
|
+
if match is None:
|
|
60
|
+
print(f"Release tag '{tag}' must match 'witwin-maxwell-v<version>'.", file=sys.stderr)
|
|
61
|
+
raise SystemExit(1)
|
|
62
|
+
|
|
63
|
+
expected_version = match.group("version")
|
|
64
|
+
pyproject_path = Path(os.environ["PACKAGE_DIR"]) / "pyproject.toml"
|
|
65
|
+
data = tomllib.loads(pyproject_path.read_text(encoding="utf-8"))
|
|
66
|
+
|
|
67
|
+
project = data["project"]
|
|
68
|
+
package_name = project["name"]
|
|
69
|
+
package_version = project["version"]
|
|
70
|
+
|
|
71
|
+
if package_name != "witwin-maxwell":
|
|
72
|
+
print(f"Expected package name 'witwin-maxwell', found '{package_name}'.", file=sys.stderr)
|
|
73
|
+
raise SystemExit(1)
|
|
74
|
+
|
|
75
|
+
if package_version != expected_version:
|
|
76
|
+
print(
|
|
77
|
+
f"Release tag version '{expected_version}' does not match pyproject version '{package_version}'.",
|
|
78
|
+
file=sys.stderr,
|
|
79
|
+
)
|
|
80
|
+
raise SystemExit(1)
|
|
81
|
+
|
|
82
|
+
print(f"Validated {package_name} {package_version} from {pyproject_path}.")
|
|
83
|
+
PY
|
|
84
|
+
|
|
85
|
+
build_cuda_wheels:
|
|
86
|
+
name: Build CUDA wheel / ${{ matrix.os }} / py${{ matrix.python_version }}
|
|
87
|
+
needs: validate_release
|
|
88
|
+
runs-on: ${{ matrix.os }}
|
|
89
|
+
strategy:
|
|
90
|
+
fail-fast: false
|
|
91
|
+
matrix:
|
|
92
|
+
os: [ubuntu-22.04, windows-2022]
|
|
93
|
+
python_version: ["3.10", "3.11", "3.12"]
|
|
94
|
+
|
|
95
|
+
steps:
|
|
96
|
+
- name: Check out repository
|
|
97
|
+
uses: actions/checkout@v4
|
|
98
|
+
|
|
99
|
+
- name: Set up Python
|
|
100
|
+
uses: actions/setup-python@v5
|
|
101
|
+
with:
|
|
102
|
+
python-version: ${{ matrix.python_version }}
|
|
103
|
+
|
|
104
|
+
- name: Free disk space (Linux)
|
|
105
|
+
if: runner.os == 'Linux'
|
|
106
|
+
shell: bash
|
|
107
|
+
run: |
|
|
108
|
+
echo "Disk before cleanup:"; df -h /
|
|
109
|
+
sudo rm -rf /usr/share/dotnet /opt/ghc /usr/local/lib/android \
|
|
110
|
+
/usr/local/share/boost /opt/hostedtoolcache/CodeQL \
|
|
111
|
+
/usr/local/share/powershell /usr/share/swift || true
|
|
112
|
+
sudo docker image prune --all --force || true
|
|
113
|
+
echo "Disk after cleanup:"; df -h /
|
|
114
|
+
|
|
115
|
+
- name: Install CUDA Toolkit
|
|
116
|
+
uses: Jimver/cuda-toolkit@v0.2.29
|
|
117
|
+
with:
|
|
118
|
+
cuda: "12.5.0"
|
|
119
|
+
method: local
|
|
120
|
+
log-file-suffix: "${{ runner.os }}-py${{ matrix.python_version }}"
|
|
121
|
+
|
|
122
|
+
- name: Set up MSVC
|
|
123
|
+
if: runner.os == 'Windows'
|
|
124
|
+
uses: ilammy/msvc-dev-cmd@v1
|
|
125
|
+
with:
|
|
126
|
+
arch: x64
|
|
127
|
+
|
|
128
|
+
- name: Export Windows CUDA_HOME
|
|
129
|
+
if: runner.os == 'Windows'
|
|
130
|
+
shell: pwsh
|
|
131
|
+
run: |
|
|
132
|
+
$cudaRoot = $env:CUDA_PATH
|
|
133
|
+
if (-not $cudaRoot) {
|
|
134
|
+
$nvcc = (Get-Command nvcc -ErrorAction Stop).Source
|
|
135
|
+
$cudaRoot = Split-Path (Split-Path $nvcc -Parent) -Parent
|
|
136
|
+
}
|
|
137
|
+
"CUDA_HOME=$cudaRoot" >> $env:GITHUB_ENV
|
|
138
|
+
"CUDA_PATH=$cudaRoot" >> $env:GITHUB_ENV
|
|
139
|
+
"CUDA_ROOT=$cudaRoot" >> $env:GITHUB_ENV
|
|
140
|
+
"CUDA_BIN_PATH=$cudaRoot" >> $env:GITHUB_ENV
|
|
141
|
+
|
|
142
|
+
- name: Show toolchain
|
|
143
|
+
shell: bash
|
|
144
|
+
run: |
|
|
145
|
+
python --version
|
|
146
|
+
nvcc --version
|
|
147
|
+
command -v cl || true
|
|
148
|
+
|
|
149
|
+
- name: Install CUDA extension build dependencies
|
|
150
|
+
run: |
|
|
151
|
+
python -m pip install --upgrade pip setuptools wheel ninja numpy
|
|
152
|
+
python -m pip install torch==2.6.0 --index-url https://download.pytorch.org/whl/cu124
|
|
153
|
+
python -m pip install build
|
|
154
|
+
|
|
155
|
+
- name: Build packaged FDTD CUDA extension
|
|
156
|
+
env:
|
|
157
|
+
MAX_JOBS: "2"
|
|
158
|
+
TORCH_CUDA_ARCH_LIST: "7.0;8.0;8.6;8.9;9.0+PTX"
|
|
159
|
+
WITWIN_MAXWELL_FDTD_CUDA_BUILD_DIR: ${{ runner.temp }}/witwin_maxwell_fdtd_cuda
|
|
160
|
+
run: |
|
|
161
|
+
python scripts/build_fdtd_cuda_prebuilt.py --verbose
|
|
162
|
+
|
|
163
|
+
- name: Build platform wheel
|
|
164
|
+
shell: bash
|
|
165
|
+
env:
|
|
166
|
+
PACKAGE_DIR: ${{ needs.validate_release.outputs.package_dir }}
|
|
167
|
+
run: |
|
|
168
|
+
python -m build --wheel "$PACKAGE_DIR"
|
|
169
|
+
|
|
170
|
+
- name: Normalize Linux wheel platform tag
|
|
171
|
+
if: runner.os == 'Linux'
|
|
172
|
+
shell: bash
|
|
173
|
+
env:
|
|
174
|
+
PACKAGE_DIR: ${{ needs.validate_release.outputs.package_dir }}
|
|
175
|
+
run: |
|
|
176
|
+
# PyPI rejects the raw linux_x86_64 tag; the extension is built on the
|
|
177
|
+
# ubuntu-22.04 runner (glibc 2.35), so retag to the matching manylinux
|
|
178
|
+
# tag. torch/CUDA runtime libraries are runtime dependencies and stay
|
|
179
|
+
# unbundled, so no auditwheel repair is required.
|
|
180
|
+
shopt -s nullglob
|
|
181
|
+
for whl in "$PACKAGE_DIR"/dist/*-linux_x86_64.whl; do
|
|
182
|
+
echo "Retagging $whl"
|
|
183
|
+
python -m wheel tags --platform-tag manylinux_2_35_x86_64 --remove "$whl"
|
|
184
|
+
done
|
|
185
|
+
ls -l "$PACKAGE_DIR"/dist
|
|
186
|
+
|
|
187
|
+
- name: Smoke install prebuilt wheel
|
|
188
|
+
shell: bash
|
|
189
|
+
env:
|
|
190
|
+
PACKAGE_DIR: ${{ needs.validate_release.outputs.package_dir }}
|
|
191
|
+
WITWIN_MAXWELL_FDTD_CUDA_PREBUILT: "1"
|
|
192
|
+
WITWIN_MAXWELL_FDTD_CUDA_BUILD_DIR: ${{ runner.temp }}/missing_prebuilt_build_dir
|
|
193
|
+
run: |
|
|
194
|
+
python -m pip uninstall -y witwin-maxwell || true
|
|
195
|
+
python -m pip install --no-deps "$PACKAGE_DIR"/dist/*.whl
|
|
196
|
+
python - <<'PY'
|
|
197
|
+
import importlib.util
|
|
198
|
+
import site
|
|
199
|
+
from pathlib import Path
|
|
200
|
+
|
|
201
|
+
candidates = []
|
|
202
|
+
for root in site.getsitepackages() + [site.getusersitepackages()]:
|
|
203
|
+
candidates.append(Path(root) / "witwin" / "maxwell" / "fdtd" / "cuda" / "build.py")
|
|
204
|
+
build_path = next((path for path in candidates if path.exists()), None)
|
|
205
|
+
assert build_path is not None, f"installed build.py not found in {candidates}"
|
|
206
|
+
|
|
207
|
+
spec = importlib.util.spec_from_file_location("witwin_maxwell_fdtd_cuda_build", build_path)
|
|
208
|
+
module = importlib.util.module_from_spec(spec)
|
|
209
|
+
spec.loader.exec_module(module)
|
|
210
|
+
|
|
211
|
+
path = module.prebuilt_extension_path()
|
|
212
|
+
assert path.exists(), f"missing packaged prebuilt extension: {path}"
|
|
213
|
+
extension = module.build_extension()
|
|
214
|
+
print(f"Loaded packaged FDTD CUDA extension from {extension.__file__}")
|
|
215
|
+
PY
|
|
216
|
+
|
|
217
|
+
- name: Upload wheel artifact
|
|
218
|
+
uses: actions/upload-artifact@v4
|
|
219
|
+
with:
|
|
220
|
+
name: wheel-${{ matrix.os }}-py${{ matrix.python_version }}
|
|
221
|
+
path: ${{ needs.validate_release.outputs.package_dir }}/dist/*.whl
|
|
222
|
+
if-no-files-found: error
|
|
223
|
+
|
|
224
|
+
build_sdist:
|
|
225
|
+
name: Build source distribution
|
|
226
|
+
needs: validate_release
|
|
227
|
+
runs-on: ubuntu-latest
|
|
228
|
+
|
|
229
|
+
steps:
|
|
230
|
+
- name: Check out repository
|
|
231
|
+
uses: actions/checkout@v4
|
|
232
|
+
|
|
233
|
+
- name: Set up Python
|
|
234
|
+
uses: actions/setup-python@v5
|
|
235
|
+
with:
|
|
236
|
+
python-version: "3.11"
|
|
237
|
+
|
|
238
|
+
- name: Build distributions
|
|
239
|
+
shell: bash
|
|
240
|
+
env:
|
|
241
|
+
PACKAGE_DIR: ${{ needs.validate_release.outputs.package_dir }}
|
|
242
|
+
run: |
|
|
243
|
+
python -m pip install --upgrade pip build
|
|
244
|
+
python -m build --sdist "$PACKAGE_DIR"
|
|
245
|
+
|
|
246
|
+
- name: Upload source distribution artifact
|
|
247
|
+
uses: actions/upload-artifact@v4
|
|
248
|
+
with:
|
|
249
|
+
name: sdist
|
|
250
|
+
path: ${{ needs.validate_release.outputs.package_dir }}/dist/*.tar.gz
|
|
251
|
+
if-no-files-found: error
|
|
252
|
+
|
|
253
|
+
publish:
|
|
254
|
+
name: Publish to PyPI
|
|
255
|
+
if: github.event_name == 'release'
|
|
256
|
+
needs:
|
|
257
|
+
- build_cuda_wheels
|
|
258
|
+
- build_sdist
|
|
259
|
+
runs-on: ubuntu-latest
|
|
260
|
+
permissions:
|
|
261
|
+
contents: read
|
|
262
|
+
id-token: write
|
|
263
|
+
environment:
|
|
264
|
+
name: pypi
|
|
265
|
+
url: https://pypi.org/project/witwin-maxwell/
|
|
266
|
+
|
|
267
|
+
steps:
|
|
268
|
+
- name: Download wheel artifacts
|
|
269
|
+
uses: actions/download-artifact@v4
|
|
270
|
+
with:
|
|
271
|
+
pattern: wheel-*
|
|
272
|
+
path: dist
|
|
273
|
+
merge-multiple: true
|
|
274
|
+
|
|
275
|
+
- name: Download source distribution artifact
|
|
276
|
+
uses: actions/download-artifact@v4
|
|
277
|
+
with:
|
|
278
|
+
name: sdist
|
|
279
|
+
path: dist
|
|
280
|
+
|
|
281
|
+
- name: Publish distributions to PyPI
|
|
282
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
283
|
+
with:
|
|
284
|
+
packages-dir: dist
|
|
285
|
+
skip-existing: true
|
|
@@ -172,6 +172,9 @@ venv.bak/
|
|
|
172
172
|
# mkdocs documentation
|
|
173
173
|
/site
|
|
174
174
|
.slangtorch_cache/
|
|
175
|
+
.*_runtime_*.slang
|
|
176
|
+
witwin/maxwell/fdtd/cuda/prebuilt/*.pyd
|
|
177
|
+
witwin/maxwell/fdtd/cuda/prebuilt/*.so
|
|
175
178
|
.fdtd_runtime_*.slang
|
|
176
179
|
.adjoint_kernels_runtime_*.slang
|
|
177
180
|
*.png
|
|
@@ -179,6 +182,7 @@ venv.bak/
|
|
|
179
182
|
*.npz
|
|
180
183
|
|
|
181
184
|
settings.local.json
|
|
185
|
+
.claude/
|
|
182
186
|
|
|
183
187
|
# mypy
|
|
184
188
|
.mypy_cache/
|
|
@@ -21,10 +21,16 @@ This document tracks the current user-visible capabilities of the `maxwell` pack
|
|
|
21
21
|
|
|
22
22
|
- `Domain` with explicit 3D bounds and `from_domain_range(...)`
|
|
23
23
|
- `GridSpec.uniform(...)` for isotropic grids
|
|
24
|
-
- `GridSpec.anisotropic(...)` for
|
|
25
|
-
- `GridSpec.
|
|
24
|
+
- `GridSpec.anisotropic(...)` for per-axis constant `dx`, `dy`, `dz`
|
|
25
|
+
- `GridSpec.custom(x_coords, y_coords, z_coords)` for nonuniform (graded) Yee grids from explicit node coordinates: any 1D float array-likes (list / NumPy / torch), validated per axis (strictly increasing, finite, at least two nodes) and stored as read-only float64 masters; a uniform axis is expressed by uniformly spaced coords, and the `Domain` bounds must equal the coordinate extents
|
|
26
|
+
- `GridSpec.auto(min_steps_per_wavelength=..., wavelength=None, max_ratio=..., override_structures=..., layer_refinement=...)` for adaptive (AutoGrid) meshing: at prepare time every structure and `MaterialRegion` AABB face snaps to a cell boundary, each face-bounded interval is stepped at `wavelength / (n_max * min_steps_per_wavelength)` using the maximum overlapping refractive index at the meshing wavelength (material regions contribute `sqrt(max(eps_bounds) * max(mu_bounds))`), intervals are filled with uniform or geometrically graded cells with a global adjacent-cell ratio bound of `max_ratio`, and the result materializes through the same nonuniform-grid path as `GridSpec.custom` (single downstream representation); the meshing wavelength defaults to the highest source frequency in the scene, or an explicit `wavelength=`
|
|
27
|
+
- `MeshOverrideStructure(geometry, dl)` mesh overrides for `GridSpec.auto`: a scalar or per-axis `(dx, dy, dz)` maximum step enforced inside the geometry's axis-aligned bounding box
|
|
28
|
+
- `LayerRefinementSpec(min_cells=..., axes=None)` for `GridSpec.auto`: any structure-bounded interval thinner than `min_cells` local target steps receives at least `min_cells` cells along the covered axes
|
|
29
|
+
- `GridSpec.is_custom`, `GridSpec.is_auto`, `GridSpec.min_spacing`, and `GridSpec.axis_coords(...)` for nonuniform-grid introspection
|
|
30
|
+
- `GridSpec.spacing` returns `(dx, dy, dz)` for uniform specs, with `GridSpec.is_uniform` for uniform-grid checks; both raise on `GridSpec.custom` and `GridSpec.auto`, as do the scalar `Scene.dx/dy/dz` / `Scene.grid_spacing` properties (use `scene.x/y/z`, the half-grid coordinates, or `grid.min_spacing` instead)
|
|
26
31
|
- `BoundarySpec.none()`, `BoundarySpec.pml(...)`, `BoundarySpec.periodic()`, `BoundarySpec.bloch(...)`, `BoundarySpec.pec()`, and `BoundarySpec.pmc()`
|
|
27
32
|
- Per-face boundary configuration through `BoundarySpec.faces(...)` and direct `BoundarySpec(kind=..., x=..., x_low=..., ...)` overrides, including global defaults plus per-axis or per-face specialization
|
|
33
|
+
- `BoundarySpec.bloch_wavevector="auto"` marker for solver-resolved Bloch phase workflows during FDTD preparation
|
|
28
34
|
- Public `BoundaryKind` literal type for boundary-mode selection across declarative scene APIs
|
|
29
35
|
- Shared `witwin.core.Structure` records pairing geometry and material, with `priority`, `enabled`, and `tags`
|
|
30
36
|
- `Geometry.with_material(...)` convenience path returns a shared `Structure`
|
|
@@ -33,14 +39,17 @@ This document tracks the current user-visible capabilities of the `maxwell` pack
|
|
|
33
39
|
- Scene-level modal port assembly with `Scene.add_port(...)`, plus `Scene.resolved_sources()` / `Scene.resolved_monitors()` to materialize first-class `ModePort` objects into the standard `Scene -> Simulation -> Result` workflow
|
|
34
40
|
- `Scene.clone(...)` for scene-preserving validation, benchmarking, and device-transfer workflows
|
|
35
41
|
- `Scene(...)` defaults to `device="cuda"` and requires an explicit `device="cpu"` override for scene-only CPU workflows
|
|
36
|
-
- Optional
|
|
37
|
-
- Optional subpixel material averaging via `Scene(subpixel_samples=...)`, accepting
|
|
42
|
+
- Optional domain symmetry on `Scene(symmetry=(..., ..., ...))` with per-axis `None` / `"PEC"` / `"PMC"` on either domain face, via bare mode strings (low face by default) or explicit `(mode, face)` pairs such as `("PEC", "high")`, folding the domain about any axis at either face with matching result-side expansion
|
|
43
|
+
- Optional subpixel material averaging via `Scene(subpixel_samples=...)`, accepting `int`, `(sx, sy, sz)`, or a `SubpixelSpec(samples=..., averaging=..., pec=...)` policy object; the bare `int` / tuple form keeps the legacy arithmetic / staircase behavior bitwise unchanged
|
|
44
|
+
- `SubpixelSpec(averaging="polarized")` enables Kottke normal-projection subpixel averaging (harmonic permittivity/permeability along the SDF interface normal, arithmetic tangentially) for `eps` and `mu` components, flowing through both FDFD and FDTD from the shared material compiler
|
|
45
|
+
- `SubpixelSpec(pec="conformal")` enables stable partial-fill conformal PEC edge treatment for in-domain `Material.pec()` structures in FDTD
|
|
38
46
|
- Solver-side compiled scene inspection via `Simulation.prepare()`, where `prepared.solver.scene` materializes Yee-grid dimensions, lazy meshgrid allocation, material compilation, and orthogonal material cross sections without storing that state on the public `Scene`
|
|
39
47
|
|
|
40
48
|
## Geometry
|
|
41
49
|
|
|
42
50
|
- Analytic geometry primitives:
|
|
43
51
|
`Box`, `Sphere`, `Cylinder`, `Ellipsoid`, `Cone`, `Pyramid`, `Prism`, `Torus`, `HollowBox`
|
|
52
|
+
- Extruded polygon geometry via `PolySlab(vertices, bounds, axis, sidewall_angle, reference_plane)` with Tidy3D-style linear sidewall taper and even-odd interior rule for non-convex cross-sections, plus `ComplexPolySlab(loops, ...)` for self-intersecting and multi-loop (hole-carving) cross-sections
|
|
44
53
|
- Shared core geometry constructors use `position=...` consistently across analytic primitives, `Mesh`, and `SMPLBody`
|
|
45
54
|
- Shared core geometry constructors default to `device=None`, while `Scene(...)` owns device placement and defaults to CUDA
|
|
46
55
|
- Rotation support for applicable analytic geometries
|
|
@@ -70,12 +79,16 @@ This document tracks the current user-visible capabilities of the `maxwell` pack
|
|
|
70
79
|
- Structure overlap resolution uses `Structure.priority` first, then append order among equal-priority structures
|
|
71
80
|
- Occupancy-based material blending on the scene grid, with SDF-driven soft occupancy for shared `Box`, `Sphere`, `Cylinder`, `Torus`, and `HollowBox`
|
|
72
81
|
- Phase-1.5 primitive SDF coverage for shared `Ellipsoid`, `Cone`, `Pyramid`, and `Prism`
|
|
82
|
+
- Differentiable SDF occupancy for `PolySlab` and `ComplexPolySlab`, with gradients through polygon vertices, axis bounds, and sidewall angle
|
|
73
83
|
- Differentiable mesh occupancy compilation through shared mesh signed-distance evaluation, including Slang-accelerated CUDA forward/backward distance-sign queries for watertight solid fill, geometry-state-aware static mesh SDF caching, cached BVH acceleration for larger static CUDA meshes, and shared surface-band modes
|
|
74
84
|
- Supersampled voxel averaging for smoother material interfaces on partial cells
|
|
85
|
+
- Polarized (Kottke normal-projection) subpixel averaging for `eps` and `mu`, using SDF-gradient interface normals estimated by central finite differences on the node grid (differentiable in geometry parameters), reducing normal-field error at high-contrast interfaces
|
|
86
|
+
- In-domain perfect-electric-conductor material via `Material.pec(name=None)` / `Material.is_pec`, compiled to a differentiable union PEC occupancy grid and enforced in FDTD through per-edge open-fraction coefficient scaling (`staircase` hard edge or `conformal` stable partial fill)
|
|
75
87
|
|
|
76
88
|
## Sources
|
|
77
89
|
|
|
78
90
|
- `CW`, `GaussianPulse`, and `RickerWavelet` source-time definitions
|
|
91
|
+
- `CustomSourceTime` arbitrary temporal waveform from a sampled `(times, amplitudes)` table or a callable `fn`, evaluated on the solver time grid through the Python scalar injection path (no CUDA kernel change)
|
|
79
92
|
- `PointDipole` source definition with `source_time` and selectable `profile="gaussian"|"ideal"`
|
|
80
93
|
- `PointDipole`, `ModeSource`, `ModeMonitor`, and `ModePort` use `position=...` as the public spatial-location argument
|
|
81
94
|
- `PointDipole` width compensation keeps narrow-source injected strength consistent with the default regularization width in FDTD/FDFD workflows
|
|
@@ -83,15 +96,53 @@ This document tracks the current user-visible capabilities of the `maxwell` pack
|
|
|
83
96
|
- `PlaneWave` soft source for analytical plane-wave injection on an auto-placed source plane
|
|
84
97
|
- `PlaneWave` soft source uses a single-plane directional `E/H` equivalent-current injector with calibrated Tidy3D-style incident-power scaling
|
|
85
98
|
- `GaussianBeam` soft source for analytical Gaussian-beam injection with configurable waist and focus
|
|
99
|
+
- `AstigmaticGaussianBeam` soft source for elliptical Gaussian-beam injection with independent per-axis waist `(w0_u, w0_v)` and per-axis focal offsets `focus_u`/`focus_v`, reducing exactly to `GaussianBeam` for isotropic inputs and reusing the same soft and TFSF injection paths
|
|
100
|
+
- `UniformCurrentSource(size, polarization, source_time, center=...)` for a uniform additive electric current filling an axis-aligned box region; radiated power scales as the square of the drive amplitude
|
|
101
|
+
- `CustomCurrentSource(current_dataset, source_time)` injects an arbitrary volume electric-current (`Jx/Jy/Jz`) and magnetic-current (`Mx/My/Mz`) distribution from a `CurrentDataset` (rectilinear coordinate arrays plus per-component tensors), trilinearly interpolated onto the Yee grid
|
|
102
|
+
- `CustomFieldSource(field_dataset, source_time)` replays a tangential `E/H` distribution on a plane by converting it into equivalent surface currents `J = n x H`, `M = -n x E` (normal along the single-sample `FieldDataset` axis), reproducing the corresponding directional plane wave
|
|
86
103
|
- Experimental `ModeSource` soft source for axis-aligned FDTD waveguide launching, using a full-vector generalized 2D eigenmode solve for forward source-plane assembly on real isotropic apertures, dense and sparse forward backends for that generalized solve, and a retained experimental torch-differentiable scalar eigensolve path for current trainable FDTD scenes
|
|
87
|
-
- Experimental `TFSF(bounds=...)` injection descriptor for `PlaneWave` and `
|
|
88
|
-
-
|
|
104
|
+
- Experimental `TFSF(bounds=...)` injection descriptor for `PlaneWave`, `GaussianBeam`, and `AstigmaticGaussianBeam`, with validated axis-aligned `PlaneWave` support for `CW` and `GaussianPulse`, and validated CW oblique `PlaneWave` support
|
|
105
|
+
- Experimental `TFSF.slab(axis="z", bounds=...)` injection descriptor for grating-oriented CW `PlaneWave` workflows, spanning the transverse Bloch unit cell during solver preparation for periodic grating illumination
|
|
106
|
+
- CUDA `PlaneWave` TFSF forward stepping uses native CUDA auxiliary-line updates and fused patch-application kernels to reduce per-step launch overhead
|
|
89
107
|
- `GaussianBeam` `TFSF` remains experimental and currently uses the analytical profile provider rather than the future angular-spectrum / discrete-face engine
|
|
90
108
|
- Polarization specified by field name (`"Ex"`, `"Ey"`, `"Ez"`) or explicit 3-vector
|
|
91
109
|
- Source amplitude and phase carried by `source_time`; spatial sources keep width / beam parameters and optional name
|
|
92
110
|
- Multiple sources per scene
|
|
93
111
|
- Source compilation uses `compile_fdfd_sources(...)` / `compile_fdtd_sources(...)` list-based interfaces across both solvers
|
|
94
112
|
|
|
113
|
+
## Grating TFSF Example
|
|
114
|
+
|
|
115
|
+
```python
|
|
116
|
+
import witwin.maxwell as mw
|
|
117
|
+
|
|
118
|
+
scene = mw.Scene(
|
|
119
|
+
domain=mw.Domain(bounds=((-0.5, 0.5), (-0.5, 0.5), (-1.0, 1.0))),
|
|
120
|
+
grid=mw.GridSpec.uniform(0.05),
|
|
121
|
+
boundary=mw.BoundarySpec.faces(
|
|
122
|
+
default="pml",
|
|
123
|
+
num_layers=12,
|
|
124
|
+
strength=1.0,
|
|
125
|
+
x="bloch",
|
|
126
|
+
y="bloch",
|
|
127
|
+
z="pml",
|
|
128
|
+
bloch_wavevector="auto",
|
|
129
|
+
),
|
|
130
|
+
)
|
|
131
|
+
|
|
132
|
+
scene.add_source(
|
|
133
|
+
mw.PlaneWave(
|
|
134
|
+
direction=(0.25, 0.0, 0.9682458366),
|
|
135
|
+
polarization=(1.0, 0.0, -0.2581988897),
|
|
136
|
+
source_time=mw.CW(frequency=200e12),
|
|
137
|
+
injection=mw.TFSF.slab(axis="z", bounds=(-0.4, 0.4)),
|
|
138
|
+
)
|
|
139
|
+
)
|
|
140
|
+
|
|
141
|
+
scene.add_monitor(mw.FluxMonitor("transmission", axis="z", position=0.7))
|
|
142
|
+
|
|
143
|
+
result = mw.Simulation.fdtd(scene, frequencies=[200e12]).run()
|
|
144
|
+
```
|
|
145
|
+
|
|
95
146
|
## Monitors
|
|
96
147
|
|
|
97
148
|
- `PointMonitor` for point sampling of selected electric or magnetic field components
|
|
@@ -99,7 +150,12 @@ This document tracks the current user-visible capabilities of the `maxwell` pack
|
|
|
99
150
|
- `FinitePlaneMonitor` for first-class finite rectangular plane sampling with explicit `position=(x, y, z)` and `size=(sx, sy, sz)` on a zero-thickness axis
|
|
100
151
|
- `ClosedSurfaceMonitor` for first-class finite closed Huygens-surface workflows, including `ClosedSurfaceMonitor.box(...)` and custom multi-face axis-aligned surfaces built from `FinitePlaneMonitor` faces
|
|
101
152
|
- `FluxMonitor` for plane-integrated power / flux extraction from tangential `E/H` fields
|
|
153
|
+
- `FieldTimeMonitor` for raw time-domain FDTD field recording (point, plane, or volume region) with `start` / `stop` / `interval` sampling controls, returning the sample-time tensor `t` and per-component GPU buffers through `Result.monitor(...)`
|
|
154
|
+
- `FluxTimeMonitor` for instantaneous time-domain Poynting flux (`E x H`) recorded on an axis-aligned plane with `start` / `stop` / `interval` sampling controls, returning the sample-time tensor `t` and the flux time series through `Result.monitor(...)`
|
|
102
155
|
- Experimental `ModeMonitor` for first-class modal decomposition on an axis-aligned port plane, reusing the current `ModeSource` mode specification and returning forward / backward modal amplitudes and power through `Result.monitor(...)`
|
|
156
|
+
- Experimental `DiffractionMonitor` for grating diffraction-order decomposition on an axis-aligned periodic unit-cell plane, returning per-order `(m, n)` complex tangential amplitudes, per-order Poynting power, propagating / evanescent flags, and diffraction angles through `Result.monitor(...)`, with reciprocal lattice and light-cone cutoff derived from the transverse periods and the resolved Bloch wavevector
|
|
157
|
+
- `PermittivityMonitor` and `MediumMonitor` for first-class point / plane / volume sampling of the compiled material properties (`eps`, plus `mu` and `sigma_e` for `MediumMonitor`), resolved from the compiled material tensors at result time through `Result.monitor(...)` without requesting any time stepping or extra DFT frequencies
|
|
158
|
+
- Experimental `DipoleEmissionMonitor` for the power a named `PointDipole` delivers to the field (`P = -(1/2) Re(conj(J) . E)`), formed from the co-located electric-field DFT at the dipole cell and the injected source current spectrum, returning per-frequency `power_delivered` through `Result.monitor(...)`; combine a structured run with a vacuum run through `maxwell.postprocess.purcell_factor(...)` to obtain the Purcell factor / local density of states
|
|
103
159
|
- Optional per-monitor `frequencies=` on plane and modal monitors / ports
|
|
104
160
|
- Named monitor results returned through the unified `Result` object
|
|
105
161
|
- Multi-component plane monitors with aggregated `Result.monitor(...)` payloads and collocated tangential grids for postprocessing workflows
|
|
@@ -124,9 +180,18 @@ This document tracks the current user-visible capabilities of the `maxwell` pack
|
|
|
124
180
|
- Axis-aligned diagonal electric anisotropy and diagonal `sigma_e_tensor` support in the Yee-grid operator
|
|
125
181
|
- Per-face `none` / `pml` boundary selection, including one-sided and mixed-axis PML layouts
|
|
126
182
|
- Explicit fast-fail validation for unsupported magnetic response and Kerr media
|
|
127
|
-
- Configurable GMRES settings via `GMRES(max_iter, tol, restart, solver_type)`
|
|
183
|
+
- Configurable GMRES settings via `GMRES(max_iter, tol, restart, solver_type, preconditioner)`
|
|
184
|
+
- GPU-native preconditioners for the iterative solvers: `none`, `jacobi` (default), `ssor` (relaxation via `GMRES(ssor_omega=...)`, default 0.8), `ilu` (ILU(0); unstable on the indefinite curl-curl operator — see `benchmark/FDFD_PERFORMANCE.md`), and `ams` (experimental in-repo Hiptmair–Xu auxiliary-space preconditioner with geometric multigrid; measured non-contractive on the indefinite time-harmonic operator — see the module docstring for its scope)
|
|
185
|
+
- Double-precision iterative solves via `GMRES(precision="double")`: the Krylov recurrences and preconditioner run in complex128 while assembly and returned fields stay complex64; removes the float32 round-off stagnation (measured: `sqmr`+`ssor` converges to 1e-7 at 48³ where single precision stalls at ~2e-2)
|
|
186
|
+
- Supported `solver_type` values: `gmres`, `cg`, `direct`, plus in-repo GPU Krylov engines `bicgstab`, `tfqmr`, `idr` (IDR(s)), and `sqmr` (simplified QMR; exploits the complex-symmetric system)
|
|
187
|
+
- The FDFD system is assembled in a symmetrized UPML formulation (exactly complex-symmetric via a diagonal similarity), which also measures far lower PML reflection than the previous discretization; the adjoint solve reuses the forward factorization/preconditioner as a consequence
|
|
188
|
+
- `direct` solver backed by NVIDIA cuDSS (`pip install witwin-maxwell[direct]`): factorize-once / solve-many with the factorization cached on the prepared solver and reused across source changes; complex64 LU plus iterative refinement
|
|
189
|
+
- Direct-solve reuse composes with `solver.set_frequency(...)`, which releases the stale factorization automatically
|
|
128
190
|
- Typed FDFD solver configuration through `FDFDConfig(solver=..., enable_plot=..., verbose=...)`
|
|
129
191
|
- Prepared execution via `Simulation.prepare()` before running
|
|
192
|
+
- Differentiable FDFD: scenes with trainable parameters (SceneModule parameters, `MaterialRegion` densities, trainable geometry tensors) route through an adjoint gradient bridge, so `loss.backward()` on `Result` fields propagates to material and geometry inputs; the adjoint solve reuses the cached system state (with the direct backend, a cached transpose factorization)
|
|
193
|
+
- System-matrix caching on the prepared solver: repeated `solve()` calls reuse the assembled matrix across source changes
|
|
194
|
+
- Frequency switching on the prepared solver via `solver.set_frequency(...)`, reusing compiled material components when all materials are non-dispersive
|
|
130
195
|
- Unified `Result` output containing `Ex`, `Ey`, and `Ez`
|
|
131
196
|
- Solver stats including convergence flag, solver info, residual, and solver configuration
|
|
132
197
|
|
|
@@ -134,19 +199,27 @@ This document tracks the current user-visible capabilities of the `maxwell` pack
|
|
|
134
199
|
|
|
135
200
|
- Time-domain simulation through `Simulation.fdtd(...)`
|
|
136
201
|
- CUDA-only solver execution; `Simulation.fdtd(...)` requires `Scene(device="cuda")`
|
|
202
|
+
- Compiled native CUDA kernels are the only FDTD runtime backend; the Torch reference path has been retired from the runtime and relocated to the CUDA parity tests
|
|
137
203
|
- Single- or multi-frequency DFT extraction through `frequency=` or `frequencies=[...]`
|
|
138
204
|
- Source temporal frequency (`source_time.frequency`) remains distinct from simulation / monitor extraction frequencies; Maxwell does not infer extraction frequencies implicitly
|
|
139
205
|
- ADE-based electric and magnetic dispersive-material updates for Debye, Drude, and Lorentz media
|
|
206
|
+
- Static isotropic or diagonal electric conductivity (`sigma_e`) in the time-domain update, folded into the per-component lossy-dielectric `Ca`/`Cb` coefficients via the standard semi-implicit trapezoidal scheme so simple lossy dielectrics no longer require a fitted Drude pole
|
|
140
207
|
- Axis-aligned diagonal anisotropy support for electric and magnetic material tensors on the Yee grid
|
|
208
|
+
- Nonuniform (`GridSpec.custom`) Yee grids run on the single native CUDA kernel path through per-axis primal/dual spacing arrays, so a uniform grid is just the constant-array special case (a `GridSpec.custom` built from a uniform scene's node masters reproduces the `GridSpec.uniform` run bitwise); covers all field-update variants (standard, CPML dense/compressed, Bloch, mixed Bloch+PML), physical-depth-graded CPML profiles with per-side layer thicknesses, per-face local-cell Mur deltas, physically placed sources and monitors via the float64 coordinate masters, and `dt` from the per-axis minimum spacing
|
|
209
|
+
- The reverse-time FDTD adjoint is the exact transpose of the nonuniform forward stencils (each reverse term reuses the same per-axis spacing element as its forward counterpart), so design-region gradients work unchanged on graded meshes
|
|
141
210
|
- Instantaneous isotropic electric Kerr nonlinearity with GPU-resident dynamic update coefficients
|
|
142
211
|
- Automatic run length estimation with `TimeConfig.auto(...)`
|
|
143
212
|
- Explicit run-step control with `TimeConfig(time_steps=...)`
|
|
213
|
+
- Opt-in auto-shutoff early termination stops the forward loop once relative electric-field energy decays below `Simulation.fdtd(..., shutoff=..., shutoff_check_interval=100)` (default `shutoff=0.0` disables it), with a settling/DFT/observer-aware floor so continuously driven CW and spectral runs are never truncated, plus a planned-window normalization restore so an early-stopped run's DFT/monitor spectra match the full-length run; `Result.stats()` reports `shutoff`, `shutoff_triggered`, `shutoff_step`, and `steps_run`
|
|
144
214
|
- Automatic `dt` tightening for broadband source-time objects such as `GaussianPulse` and `RickerWavelet`, and for electric or magnetic dispersive material poles such as `Drude`, `Debye`, and `Lorentz` media
|
|
145
215
|
- CPML absorber configuration through `BoundarySpec.pml(...)` plus typed `Simulation.fdtd(...)` config (`absorber=...`, `cpml_config=...`)
|
|
146
216
|
- CPML auxiliary `psi` storage auto-selects between a dense fast path and slab-allocated low-memory storage, with `cpml_config={"memory_mode": "auto"|"dense"|"slab"}` and optional `dense_memory_limit_mib` tuning
|
|
217
|
+
- Additional PML-face absorber variants selectable through `Simulation.fdtd(..., absorber=...)`: `"absorber"` (adiabatic graded-conductivity layer with no auxiliary `psi` memory) and `"stablepml"` (a CPML profile tuned for late-time stability with a higher grading order and larger complex-frequency shift), alongside the existing `"cpml"` and `"pml"` options
|
|
218
|
+
- First-order Mur absorbing boundary as a per-face `BoundarySpec.mur()` kind, applied by a native CUDA kernel after the electric update that updates persistent per-face boundary buffers in place (no per-step host arithmetic or allocation, so it is captured into the tail CUDA graph)
|
|
147
219
|
- Non-absorbing FDTD boundary conditions: periodic, Bloch phase-shifted periodic, PEC, and PMC
|
|
148
220
|
- Per-face FDTD boundary selection across `pml`, `periodic`, `pec`, `pmc`, and `none`, including mixed-axis combinations such as periodic-in-`y` plus PML-in-`x/z`
|
|
149
|
-
- Mixed
|
|
221
|
+
- Mixed x/y Bloch + z PML FDTD forward stepping for grating-oriented CW `PlaneWave` TFSF slabs, including explicit Bloch wavevectors and solver-resolved automatic Bloch phase from the incident CW plane wave
|
|
222
|
+
- Any-axis / either-face domain symmetry (PEC/PMC image plane on the chosen `low` or `high` face) combined with absorbing boundaries through `Scene(symmetry=...)` with `BoundarySpec.pml(...)`; point-like sources in the folded-away half are rejected with a clear error
|
|
150
223
|
- Spectral window and normalization configuration through `SpectralSampler(window=..., normalize_source=...)`
|
|
151
224
|
- Pulse-driven spectral extraction starts at the transient without steady-state apodization for `GaussianPulse` and `RickerWavelet`, while CW extraction still skips startup transients
|
|
152
225
|
- Optional prepared execution via `Simulation.prepare()`
|
|
@@ -162,6 +235,12 @@ This document tracks the current user-visible capabilities of the `maxwell` pack
|
|
|
162
235
|
- Internal checkpoint/replay support for adjoint-enabled FDTD runs, including CPML auxiliary state replay, TFSF auxiliary-line replay, and Bloch real/imag field checkpoints
|
|
163
236
|
- Adjoint gradient pullback from Yee-grid electric permittivity coefficients back through `Scene.compile_material_tensors()` into trainable material-graph inputs
|
|
164
237
|
- Solver stats including time steps, `dt`, absorber, requested frequencies, per-frequency DFT sample counts, elapsed time, milliseconds per step, and steps per second
|
|
238
|
+
- Native CUDA extension builds on Windows can discover and load the Visual Studio x64 build environment automatically for accelerated FDTD kernels
|
|
239
|
+
- Native CUDA extension platform wheels include the packaged FDTD CUDA extension, so ordinary `pip install witwin-maxwell` users can load the accelerated FDTD runtime without compiling locally
|
|
240
|
+
- Native CUDA extension builds resolve conda-distributed torch import libraries automatically, and `WITWIN_MAXWELL_FDTD_CUDA_PREBUILT=1` loads an already-built extension from the configured build directory without invoking the build toolchain (required under profilers such as Nsight Systems)
|
|
241
|
+
- Native CUDA CPML field updates skip full-volume coefficient reads when the decay/curl coefficient tensors are spatially uniform, detected automatically once per solve (about 1.4x faster forward stepping on homogeneous scenes)
|
|
242
|
+
- Optional CUDA-graph capture of the per-step FDTD work via `Simulation.fdtd(..., cuda_graph=True)`: the magnetic/electric Yee updates (with CPML) are captured as one graph, and the post-source tail (PEC clamp, Mur ABC, and a GPU-driven running DFT) as a second graph, collapsing per-step kernel-launch and host overhead. The running DFT is driven from a precomputed device weight table indexed by a device step counter (no per-step host arithmetic or host->device transfer), so it captures cleanly and stays bit-identical to the host path (single- and multi-frequency). Bit-exact against the non-graph path, opt-in, and automatically declined for TFSF / magnetic-source / complex-field / Kerr / dispersive scenes whose per-step work carries host input. Most effective in the launch-bound small/adaptive-grid regime (measured ~3.7x/step on a ~1.25e5-cell AutoGrid scene, bringing AutoGrid to ~10.9x faster than the fine-uniform reference -- its full cell-count ratio -- and negligible on large compute-bound uniform grids); `Result.stats()["cuda_graph_active"]` / `["tail_graph_active"]` report whether capture engaged
|
|
243
|
+
- The native CUDA module surface accepts strided tensor views, so reverse-time adjoint checks run on native CUDA reverse kernels for standard, CPML, Bloch, and dispersive scenes, validated against the relocated Torch reference; TFSF adjoint uses the native reference composition
|
|
165
244
|
- FDTD result stats include CPML auxiliary-memory mode and allocated-versus-dense `psi` byte counts
|
|
166
245
|
- Support for odd grid sizes in Yee-component field outputs
|
|
167
246
|
|
|
@@ -195,6 +274,8 @@ This document tracks the current user-visible capabilities of the `maxwell` pack
|
|
|
195
274
|
- `maxwell.postprocess.compute_directivity(...)` for radiation intensity, total radiated power, directivity, gain, radiation efficiency, and 3 dB beamwidth extraction from NFFT far fields
|
|
196
275
|
- `maxwell.postprocess.compute_s_parameters(...)` for broadband `S11` / `S21` extraction from flux-monitor results using reference-run or explicit incident-power normalization
|
|
197
276
|
- Experimental `maxwell.postprocess.compute_mode_overlap(...)` for plane-monitor or first-class `ModeMonitor` / `ModePort` modal decomposition against an axis-aligned scalar `ModeSource` reference, returning forward/backward modal amplitudes and power fractions
|
|
277
|
+
- Experimental `maxwell.postprocess.purcell_factor(structured, vacuum, name)` for the vacuum-normalized Purcell factor / local density of states of a `DipoleEmissionMonitor`, validated under `tests/monitors/emission/test_dipole_emission_monitor.py` against the analytic dipole-near-PEC-mirror curve (perpendicular orientation) and unity vacuum emission
|
|
278
|
+
- Experimental `maxwell.postprocess.compute_diffraction_orders(...)` and `enumerate_diffraction_orders(...)` for grating diffraction-order decomposition on a periodic unit-cell plane; regression-tested under `tests/monitors/diffraction/test_diffraction_monitor.py` for order-cutoff / light-cone physics, Parseval consistency between the summed order powers and the direct plane-flux integral, specular dominance at normal incidence, grating-driven redistribution of transmitted power into the `+/-1` orders, and cross-validation of the transmission/reflection coefficients against the independent Yee-grid `FluxMonitor` primitive (with an `xfail` tripwire documenting that absolute `T + R = 1` energy conservation is not recoverable under the FDTD spectral-monitor CW normalization)
|
|
198
279
|
- End-to-end validation coverage for first-class finite closed-surface Huygens workflows in homogeneous free space: rectangular-box dipole near-field reconstruction/directivity, non-rectangular orthogonal-surface dipole directivity, and TFSF Rayleigh-sphere bistatic RCS are regression-tested against analytic or direct-FDTD references under `tests/validation/physics/test_postprocess_end_to_end_validation.py`
|
|
199
280
|
- First-class closed-surface postprocessing now rejects layered or otherwise inhomogeneous exterior media explicitly instead of silently applying a free-space Green's function outside its validity range
|
|
200
281
|
|
|
@@ -206,6 +287,12 @@ This document tracks the current user-visible capabilities of the `maxwell` pack
|
|
|
206
287
|
- `PlaneWave` export places the source inside the physical interior and uses Tidy3D's infinite-plane aperture convention instead of a finite rectangular source patch
|
|
207
288
|
- Supported mappings: Domain, GridSpec, BoundarySpec (uniform or per-face PML/periodic/PEC/PMC/Bloch export), Structure (Box/Sphere/Cylinder/Cone), Material (simple conductive / Drude / Lorentz / Debye / mixed PoleResidue with `mu_r = 1`), PointDipole, PlaneWave, GaussianBeam, PointMonitor, PlaneMonitor, FinitePlaneMonitor, FluxMonitor, symmetry
|
|
208
289
|
|
|
290
|
+
## GDS Adapter
|
|
291
|
+
|
|
292
|
+
- `maxwell.adapters.gds.from_gds(path, layer=..., bounds=..., ...)` imports GDS layout polygons as `PolySlab` geometries with cell selection (explicit name or unique top-level cell), layer/datatype filtering, recursive reference flattening, extrusion parameters (`axis`, `bounds`, `sidewall_angle`, `reference_plane`), and unit conversion from the file's user unit to metres (overridable via `length_scale`)
|
|
293
|
+
- `maxwell.adapters.gds.to_gds_file(geometries, path, ...)` writes `PolySlab` / `ComplexPolySlab` cross-sections as GDS polygons on a chosen layer/datatype (multi-loop geometry is even-odd merged so holes survive as keyhole cuts), with the library unit derived from `length_scale` (micrometre user units by default)
|
|
294
|
+
- Adapter module at `maxwell/adapters/gds.py` with optional `gdstk` import
|
|
295
|
+
|
|
209
296
|
## Tidy3D Benchmarking
|
|
210
297
|
|
|
211
298
|
- `benchmark/` package as the unified Maxwell-vs-Tidy3D benchmarking entrypoint
|
|
@@ -223,6 +310,12 @@ This document tracks the current user-visible capabilities of the `maxwell` pack
|
|
|
223
310
|
- Auto-updated benchmark summary in `benchmark/RESULTS.md`, grouped by benchmark scene folder with per-metric better-direction and target-range guidance
|
|
224
311
|
- Plane-wave benchmark runs enable source-spectrum normalization on the Maxwell side so pulsed `PlaneWave` scenarios compare against the same frequency-domain reference convention as the Tidy3D export
|
|
225
312
|
|
|
313
|
+
## Performance Benchmarking
|
|
314
|
+
|
|
315
|
+
- FDFD solver performance benchmark via `python -m benchmark.fdfd_performance`, sweeping cubic grid sizes (default 32³ through 128³) on a canonical dipole + dielectric-cube scene, with `--solver`/`--precond`/`--precision` axes
|
|
316
|
+
- Per-size metrics: matrix assembly time, solve time, operator matvec count, convergence flag, explicit relative residual, and CuPy peak-GPU-memory high-water mark
|
|
317
|
+
- Results written to `benchmark/FDFD_PERFORMANCE.md` with raw JSON runs archived under `benchmark/cache/fdfd_performance/`
|
|
318
|
+
|
|
226
319
|
## Validation and Reference Utilities
|
|
227
320
|
|
|
228
321
|
- Shared material compiler used by scene construction and backend preparation
|
|
@@ -234,15 +327,26 @@ This document tracks the current user-visible capabilities of the `maxwell` pack
|
|
|
234
327
|
|
|
235
328
|
## Known Limitations
|
|
236
329
|
|
|
237
|
-
-
|
|
238
|
-
-
|
|
239
|
-
-
|
|
330
|
+
- Nonuniform (`GridSpec.custom`) grids are FDTD-only in v1: FDFD and Tidy3D export both raise `NotImplementedError` for custom grids; `GridSpec.auto` resolves to a nonuniform grid at prepare time and inherits the same restrictions (FDFD unsupported, TFSF/mode-plane locally-uniform rules apply)
|
|
331
|
+
- On nonuniform grids, TFSF-kind injections (`PlaneWave` TFSF box, grating TFSF slab) require locally uniform spacing along all three axes over the injection region expanded by one cell, and `ModeSource` / `ModeMonitor` / `ModePort` require locally uniform transverse spacing across the mode plane; both are validated with explicit errors. Soft (non-TFSF) surface sources and `PointDipole` are fully generalized, but the soft `PlaneWave` numerical-dispersion phase correction uses the per-axis minimum spacing (exact on uniform grids, an approximation on graded ones)
|
|
332
|
+
- Subpixel material averaging (`Scene(subpixel_samples=...)` with more than one sample) is not yet generalized to nonuniform grids and fails through the scalar `Scene.dx` accessor
|
|
333
|
+
- Polarized subpixel averaging is applied to `eps` and `mu` only; `sigma_e`, Kerr `chi3`, and dispersive-pole weights stay arithmetic (the normal-projection rule is not well defined for conductivity/nonlinearity, and only the static base permittivity/permeability becomes normal-aware for dispersive media)
|
|
334
|
+
- The polarized rule is baked at grid nodes and both runtimes keep their existing arithmetic node-to-Yee-edge averaging, so a residual O(dx) half-cell smoothing of the normal-aware correction remains versus evaluating the rule exactly at each Yee-edge location; this residual is far below the arithmetic/staircase error it replaces
|
|
335
|
+
- Conformal PEC (`SubpixelSpec(pec="conformal")`) is FDTD-only: FDFD raises `NotImplementedError` for in-domain PEC materials, and the FDTD scheme is the stable partial-fill (edge-fraction E-suppression) variant of the Dey-Mittra family; classical area-scaled Dey-Mittra (H-side `1/A_open` with an area floor), contour-path H-loop averaging, and surface-impedance boundaries remain future work
|
|
336
|
+
- Subpixel averaging normals and PEC fill fractions reuse per-structure signed-distance fields, so accuracy is bounded by SDF quality for primitives with kinked distance fields (faces/edges/corners)
|
|
240
337
|
- Maxwell supports axis-aligned diagonal anisotropy through `DiagonalTensor3`, but `Material.orientation` and full `Tensor3x3` rotation / off-diagonal tensors remain unsupported
|
|
241
338
|
- Kerr media cannot be combined with dispersive or anisotropic materials in the same scene in v1
|
|
339
|
+
- Experimental `DiffractionMonitor` is v1-limited: it assumes the monitor plane spans one full transverse unit cell (periods taken from the transverse domain lengths), targets FDTD `CW` grating scenes with transverse Bloch/periodic boundaries, and reports per-order power as a share of the transmitted plane flux. Absolute per-order diffraction efficiency normalized against a separately measured incident power is not asserted, because the FDTD spectral-monitor CW normalization is steady-state/ratio-based rather than an absolute cross-run power balance
|
|
340
|
+
- Experimental `DipoleEmissionMonitor` is v1-limited: it reports `power_delivered` from the single co-located dipole cell (a point approximation of the profile-weighted current integral) and requires FDTD `PointDipole` sources; the Purcell factor is only obtained by explicitly normalizing against a separate vacuum run through `maxwell.postprocess.purcell_factor(...)`, because the discrete effective source volume that sets the absolute power scale has no reliable closed form, so a lone run returns `purcell_factor=None`
|
|
242
341
|
- FDFD supports electric anisotropy only; static magnetic media and magnetic dispersion still fail explicitly
|
|
243
|
-
- FDTD
|
|
244
|
-
- Mixed Bloch boundary configurations
|
|
342
|
+
- FDTD supports static electric conductivity (`sigma_e`) in the forward update but still lacks static magnetic conductivity (`sigma_m`), and the FDTD adjoint bridge rejects `sigma_e` media because the reverse-time kernels do not model the conduction-loss decay
|
|
343
|
+
- Mixed Bloch boundary configurations outside the supported x/y Bloch + z PML grating FDTD path still fail explicitly
|
|
344
|
+
- TFSF slab runtime support is currently limited to CW `PlaneWave` grating slabs with `axis="z"`; non-Bloch slabs, non-`PlaneWave` slab sources, and broadband automatic fixed-angle Bloch workflows fail explicitly because automatic Bloch phase is single-frequency metadata
|
|
345
|
+
- Automatic Bloch wavevectors are solver-preparation metadata and are rejected by unresolved Tidy3D export
|
|
245
346
|
- FDFD currently supports per-face boundary mixing only for `none` and `pml`
|
|
347
|
+
- Domain symmetry (`Scene(symmetry=...)`) is FDTD-only (FDFD rejects it), applies a single image plane per axis at the chosen `low`/`high` face, and requires the user to supply the pre-folded half/quarter domain with a physically symmetric source layout; the symmetry-plane face must be `none` or `pml`. Tidy3D export encodes symmetry about the domain center only and drops the per-face (`low`/`high`) selection
|
|
348
|
+
- The first-order `BoundarySpec.mur()` absorbing boundary leaves a higher reflected residual than a PML absorber (single-snapshot residual energy roughly an order of magnitude above a reflecting PEC box, versus about two orders for PML), applies only to the real electric field so it cannot be combined with Bloch complex-field runs, and has no second-order variant in v1
|
|
349
|
+
- The `"absorber"` and `"stablepml"` variants share the existing PML face plumbing (`BoundarySpec.pml(...)`); `"stablepml"` overrides the CPML grading/alpha profile, so a user-supplied `cpml_config` does not override the stable-profile grading keys
|
|
246
350
|
- Tidy3D export and the FDTD adjoint bridge reject anisotropy, magnetic dispersion, and Kerr media explicitly in v1
|
|
247
351
|
- Experimental `ModeSource`, `ModeMonitor`, and `ModePort` are currently limited to FDTD `CW` soft injection / monitoring on an axis-aligned plane and no Tidy3D mode-source export support; forward mode solving now uses a full-vector generalized eigenproblem on real isotropic source apertures and can handle non-unit `mu_r`, but the differentiable path still inherits the older scalar restrictions, and the broader modal stack is still missing complex/lossy, anisotropic, bent, angled, and RF-style wave-port coverage
|
|
248
352
|
- Experimental `compute_mode_overlap(...)` currently expects aligned tangential `E/H` fields on the target port plane and inherits the same axis-aligned modal-source assumptions as the current `ModeSource` implementation
|
|
@@ -250,3 +354,5 @@ This document tracks the current user-visible capabilities of the `maxwell` pack
|
|
|
250
354
|
- First-class closed-surface postprocessing currently requires a homogeneous exterior medium immediately outside every face; layered or otherwise inhomogeneous exteriors are rejected explicitly
|
|
251
355
|
- Closed-surface validation currently covers axis-aligned planar faces, including rectangular Huygens boxes and non-rectangular orthogonal polyhedra; curved/non-planar closed surfaces still need a separate workflow and validation path
|
|
252
356
|
- Benchmark soft-plane-wave absolute calibration still needs separate validation/debugging and remains a known open correctness issue
|
|
357
|
+
- `UniformCurrentSource`, `CustomCurrentSource`, and `CustomFieldSource` are v1 forward-only: the FDTD adjoint bridge rejects them (no source pullback is implemented). `CustomFieldSource` additionally requires a planar (single-sample-axis) `FieldDataset`, injects toward `+normal` only, and reproduces the plane wave to discretization-limited tolerance (finite-aperture edge diffraction and half-cell E/H staggering leave a small backward and cross-polarized residual)
|
|
358
|
+
- `CustomSourceTime` v1 is limited to the Python scalar soft/uniform injection path: it is supported on `PointDipole` but rejected on `PlaneWave`, `GaussianBeam`, `AstigmaticGaussianBeam` (which require the native time-shifted kernel), and on `ModeSource` (CW-only); callable `fn` waveforms need an explicit `characteristic_frequency` and are not supported in the FDTD adjoint (only sampled `(times, amplitudes)` tables are), and custom-waveform samples are not differentiable
|