witwin-maxwell 0.3.0__py3-none-win_amd64.whl

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.
Files changed (107) hide show
  1. witwin/maxwell/__init__.py +164 -0
  2. witwin/maxwell/adapters/__init__.py +1 -0
  3. witwin/maxwell/adapters/gds.py +203 -0
  4. witwin/maxwell/adapters/tidy3d.py +1669 -0
  5. witwin/maxwell/adjoint_inputs.py +70 -0
  6. witwin/maxwell/compiler/__init__.py +11 -0
  7. witwin/maxwell/compiler/materials.py +1355 -0
  8. witwin/maxwell/compiler/monitors.py +164 -0
  9. witwin/maxwell/compiler/sources.py +222 -0
  10. witwin/maxwell/fdfd/__init__.py +3 -0
  11. witwin/maxwell/fdfd/adjoint/__init__.py +3 -0
  12. witwin/maxwell/fdfd/adjoint/bridge.py +180 -0
  13. witwin/maxwell/fdfd/ams.py +300 -0
  14. witwin/maxwell/fdfd/krylov.py +280 -0
  15. witwin/maxwell/fdfd/plotting.py +110 -0
  16. witwin/maxwell/fdfd/postprocess.py +33 -0
  17. witwin/maxwell/fdfd/solver.py +1057 -0
  18. witwin/maxwell/fdtd/__init__.py +4 -0
  19. witwin/maxwell/fdtd/adjoint/__init__.py +21 -0
  20. witwin/maxwell/fdtd/adjoint/bridge.py +746 -0
  21. witwin/maxwell/fdtd/adjoint/capabilities.py +29 -0
  22. witwin/maxwell/fdtd/adjoint/core.py +3614 -0
  23. witwin/maxwell/fdtd/adjoint/dispatch.py +684 -0
  24. witwin/maxwell/fdtd/adjoint/native.py +2561 -0
  25. witwin/maxwell/fdtd/adjoint/profiler.py +195 -0
  26. witwin/maxwell/fdtd/adjoint/reverse_common.py +207 -0
  27. witwin/maxwell/fdtd/adjoint/seeds.py +524 -0
  28. witwin/maxwell/fdtd/boundary/__init__.py +37 -0
  29. witwin/maxwell/fdtd/boundary/bloch.py +90 -0
  30. witwin/maxwell/fdtd/boundary/common.py +41 -0
  31. witwin/maxwell/fdtd/boundary/cpml.py +527 -0
  32. witwin/maxwell/fdtd/boundary/runtime.py +209 -0
  33. witwin/maxwell/fdtd/checkpoint.py +227 -0
  34. witwin/maxwell/fdtd/coords.py +32 -0
  35. witwin/maxwell/fdtd/cuda/__init__.py +11 -0
  36. witwin/maxwell/fdtd/cuda/backend.py +3532 -0
  37. witwin/maxwell/fdtd/cuda/build.py +292 -0
  38. witwin/maxwell/fdtd/cuda/extension.cpp +2053 -0
  39. witwin/maxwell/fdtd/cuda/kernels/adjoint.cu +5290 -0
  40. witwin/maxwell/fdtd/cuda/kernels/aniso.cu +1704 -0
  41. witwin/maxwell/fdtd/cuda/kernels/boundary.cu +424 -0
  42. witwin/maxwell/fdtd/cuda/kernels/common.cu +74 -0
  43. witwin/maxwell/fdtd/cuda/kernels/common.cuh +82 -0
  44. witwin/maxwell/fdtd/cuda/kernels/dispersive.cu +782 -0
  45. witwin/maxwell/fdtd/cuda/kernels/electric.cu +3613 -0
  46. witwin/maxwell/fdtd/cuda/kernels/magnetic.cu +781 -0
  47. witwin/maxwell/fdtd/cuda/kernels/observers.cu +347 -0
  48. witwin/maxwell/fdtd/cuda/kernels/projection.cu +211 -0
  49. witwin/maxwell/fdtd/cuda/kernels/sources.cu +1482 -0
  50. witwin/maxwell/fdtd/cuda/kernels/spectral.cu +297 -0
  51. witwin/maxwell/fdtd/cuda/launch.h +23 -0
  52. witwin/maxwell/fdtd/cuda/prebuilt/witwin_maxwell_fdtd_cuda.pyd +0 -0
  53. witwin/maxwell/fdtd/cuda/runtime/__init__.py +6 -0
  54. witwin/maxwell/fdtd/cuda/runtime/dispatcher.py +6 -0
  55. witwin/maxwell/fdtd/cuda/runtime/graph.py +33 -0
  56. witwin/maxwell/fdtd/cuda/tensors.h +35 -0
  57. witwin/maxwell/fdtd/dispersion.py +48 -0
  58. witwin/maxwell/fdtd/evaluation.py +290 -0
  59. witwin/maxwell/fdtd/excitation/__init__.py +27 -0
  60. witwin/maxwell/fdtd/excitation/injection.py +1102 -0
  61. witwin/maxwell/fdtd/excitation/modes.py +1675 -0
  62. witwin/maxwell/fdtd/excitation/spatial.py +469 -0
  63. witwin/maxwell/fdtd/excitation/temporal.py +510 -0
  64. witwin/maxwell/fdtd/excitation/tfsf_apply.py +264 -0
  65. witwin/maxwell/fdtd/excitation/tfsf_common.py +421 -0
  66. witwin/maxwell/fdtd/excitation/tfsf_specs.py +490 -0
  67. witwin/maxwell/fdtd/excitation/tfsf_state.py +778 -0
  68. witwin/maxwell/fdtd/io.py +31 -0
  69. witwin/maxwell/fdtd/material_pullback.py +371 -0
  70. witwin/maxwell/fdtd/meshing/__init__.py +3 -0
  71. witwin/maxwell/fdtd/meshing/autogrid.py +335 -0
  72. witwin/maxwell/fdtd/observers.py +1453 -0
  73. witwin/maxwell/fdtd/plotting.py +121 -0
  74. witwin/maxwell/fdtd/postprocess.py +205 -0
  75. witwin/maxwell/fdtd/runtime/__init__.py +119 -0
  76. witwin/maxwell/fdtd/runtime/initialization.py +236 -0
  77. witwin/maxwell/fdtd/runtime/materials.py +1563 -0
  78. witwin/maxwell/fdtd/runtime/module_cache.py +31 -0
  79. witwin/maxwell/fdtd/runtime/spectral.py +581 -0
  80. witwin/maxwell/fdtd/runtime/stepping.py +1987 -0
  81. witwin/maxwell/fdtd/solver.py +502 -0
  82. witwin/maxwell/geometry/__init__.py +5 -0
  83. witwin/maxwell/geometry/polyslab.py +299 -0
  84. witwin/maxwell/materials.py +3 -0
  85. witwin/maxwell/media.py +1467 -0
  86. witwin/maxwell/monitors.py +743 -0
  87. witwin/maxwell/ports.py +113 -0
  88. witwin/maxwell/postprocess/RCS.py +139 -0
  89. witwin/maxwell/postprocess/__init__.py +42 -0
  90. witwin/maxwell/postprocess/diffraction.py +219 -0
  91. witwin/maxwell/postprocess/directivity.py +152 -0
  92. witwin/maxwell/postprocess/emission.py +67 -0
  93. witwin/maxwell/postprocess/modal.py +324 -0
  94. witwin/maxwell/postprocess/nfft.py +266 -0
  95. witwin/maxwell/postprocess/scattering_parameters.py +358 -0
  96. witwin/maxwell/postprocess/stratton_chu.py +1193 -0
  97. witwin/maxwell/result.py +967 -0
  98. witwin/maxwell/scene.py +1338 -0
  99. witwin/maxwell/simulation.py +659 -0
  100. witwin/maxwell/sources.py +917 -0
  101. witwin/maxwell/visualization/__init__.py +28 -0
  102. witwin/maxwell/visualization/interactive.py +484 -0
  103. witwin/maxwell/visualization/plots.py +568 -0
  104. witwin_maxwell-0.3.0.dist-info/METADATA +184 -0
  105. witwin_maxwell-0.3.0.dist-info/RECORD +107 -0
  106. witwin_maxwell-0.3.0.dist-info/WHEEL +4 -0
  107. witwin_maxwell-0.3.0.dist-info/licenses/LICENSE +13 -0
@@ -0,0 +1,292 @@
1
+ from __future__ import annotations
2
+
3
+ import os
4
+ import shutil
5
+ import subprocess
6
+ import sys
7
+ import tempfile
8
+ from pathlib import Path
9
+
10
+ import torch
11
+ from torch.utils.cpp_extension import load
12
+
13
+
14
+ def _candidate_vcvars64_paths() -> list[Path]:
15
+ paths: list[Path] = []
16
+ program_files_x86 = os.environ.get("ProgramFiles(x86)")
17
+ if program_files_x86:
18
+ vswhere = Path(program_files_x86) / "Microsoft Visual Studio" / "Installer" / "vswhere.exe"
19
+ if vswhere.exists():
20
+ try:
21
+ install_root = subprocess.check_output(
22
+ [
23
+ str(vswhere),
24
+ "-latest",
25
+ "-products",
26
+ "*",
27
+ "-requires",
28
+ "Microsoft.VisualStudio.Component.VC.Tools.x86.x64",
29
+ "-property",
30
+ "installationPath",
31
+ ],
32
+ text=True,
33
+ encoding="mbcs",
34
+ errors="replace",
35
+ ).strip()
36
+ except (OSError, subprocess.CalledProcessError):
37
+ install_root = ""
38
+ if install_root:
39
+ paths.append(Path(install_root) / "VC" / "Auxiliary" / "Build" / "vcvars64.bat")
40
+
41
+ for env_name in ("VSINSTALLDIR",):
42
+ root = os.environ.get(env_name)
43
+ if root:
44
+ paths.append(Path(root) / "VC" / "Auxiliary" / "Build" / "vcvars64.bat")
45
+
46
+ program_files = os.environ.get("ProgramFiles", r"C:\Program Files")
47
+ for edition in ("Community", "Professional", "Enterprise", "BuildTools"):
48
+ paths.append(
49
+ Path(program_files)
50
+ / "Microsoft Visual Studio"
51
+ / "2022"
52
+ / edition
53
+ / "VC"
54
+ / "Auxiliary"
55
+ / "Build"
56
+ / "vcvars64.bat"
57
+ )
58
+
59
+ seen: set[Path] = set()
60
+ unique_paths: list[Path] = []
61
+ for path in paths:
62
+ resolved = path.resolve() if path.exists() else path
63
+ if resolved in seen:
64
+ continue
65
+ seen.add(resolved)
66
+ unique_paths.append(path)
67
+ return unique_paths
68
+
69
+
70
+ def _load_vcvars64_environment() -> bool:
71
+ for vcvars in _candidate_vcvars64_paths():
72
+ if not vcvars.exists():
73
+ continue
74
+ fd, probe_name = tempfile.mkstemp(prefix="witwin_maxwell_vcvars_probe_", suffix=".cmd")
75
+ os.close(fd)
76
+ probe = Path(probe_name)
77
+ probe.write_text(f'@echo off\ncall "{vcvars}" >nul\nset\n', encoding="utf-8")
78
+ try:
79
+ output = subprocess.check_output(
80
+ ["cmd.exe", "/d", "/c", str(probe)],
81
+ text=True,
82
+ encoding="mbcs",
83
+ errors="replace",
84
+ )
85
+ except (OSError, subprocess.CalledProcessError):
86
+ continue
87
+ finally:
88
+ try:
89
+ probe.unlink()
90
+ except OSError:
91
+ pass
92
+ updates: dict[str, str] = {}
93
+ for line in output.splitlines():
94
+ if "=" not in line:
95
+ continue
96
+ key, value = line.split("=", 1)
97
+ updates[key] = value
98
+ for key, value in updates.items():
99
+ os.environ[key] = value
100
+ path_value = updates.get("PATH", updates.get("Path"))
101
+ if path_value is not None:
102
+ os.environ["PATH"] = path_value
103
+ os.environ["Path"] = path_value
104
+ return True
105
+ return False
106
+
107
+
108
+ def _ensure_windows_build_tools_on_path() -> None:
109
+ if os.name != "nt":
110
+ return
111
+ os.environ.setdefault("VSLANG", "1033")
112
+ if shutil.which("cl") is None:
113
+ _load_vcvars64_environment()
114
+ if shutil.which("cl") is None:
115
+ return
116
+
117
+ current_path = os.environ.get("PATH") or os.environ.get("Path") or ""
118
+ prefixes: list[str] = []
119
+ vc_tools = os.environ.get("VCToolsInstallDir")
120
+ if vc_tools:
121
+ prefixes.append(str(Path(vc_tools) / "bin" / "Hostx64" / "x64"))
122
+ vs_install = os.environ.get("VSINSTALLDIR")
123
+ if vs_install:
124
+ prefixes.append(
125
+ str(Path(vs_install) / "Common7" / "IDE" / "CommonExtensions" / "Microsoft" / "CMake" / "Ninja")
126
+ )
127
+ if not prefixes:
128
+ return
129
+ merged_path = os.pathsep.join([*prefixes, current_path])
130
+ os.environ["PATH"] = merged_path
131
+ os.environ["Path"] = merged_path
132
+
133
+
134
+ def _ensure_cuda_home_from_nvcc() -> None:
135
+ if os.environ.get("CUDA_HOME") or os.environ.get("CUDA_PATH"):
136
+ return
137
+ nvcc = shutil.which("nvcc")
138
+ if nvcc is None:
139
+ return
140
+ cuda_home = Path(nvcc).resolve().parents[1]
141
+ os.environ["CUDA_HOME"] = str(cuda_home)
142
+ if os.name == "nt":
143
+ os.environ["CUDA_PATH"] = str(cuda_home)
144
+
145
+
146
+ def source_root() -> Path:
147
+ return Path(__file__).resolve().parent
148
+
149
+
150
+ def prebuilt_root() -> Path:
151
+ return source_root() / "prebuilt"
152
+
153
+
154
+ def extension_suffix() -> str:
155
+ return ".pyd" if os.name == "nt" else ".so"
156
+
157
+
158
+ def prebuilt_extension_path() -> Path:
159
+ return prebuilt_root() / f"witwin_maxwell_fdtd_cuda{extension_suffix()}"
160
+
161
+
162
+ def extension_sources() -> list[Path]:
163
+ root = source_root()
164
+ return [
165
+ root / "extension.cpp",
166
+ root / "kernels" / "common.cu",
167
+ root / "kernels" / "magnetic.cu",
168
+ root / "kernels" / "electric.cu",
169
+ root / "kernels" / "boundary.cu",
170
+ root / "kernels" / "projection.cu",
171
+ root / "kernels" / "aniso.cu",
172
+ root / "kernels" / "dispersive.cu",
173
+ root / "kernels" / "sources.cu",
174
+ root / "kernels" / "spectral.cu",
175
+ root / "kernels" / "observers.cu",
176
+ root / "kernels" / "adjoint.cu",
177
+ ]
178
+
179
+
180
+ def _cuda_gencode_flags() -> list[str]:
181
+ """Translate the release architecture list directly into nvcc flags."""
182
+ value = os.environ.get("WITWIN_CUDA_GENCODE_ARCHES")
183
+ if not value:
184
+ return []
185
+ flags: list[str] = []
186
+ for entry in value.split(";"):
187
+ entry = entry.strip()
188
+ if not entry:
189
+ continue
190
+ include_ptx = entry.endswith("+PTX")
191
+ number = entry.removesuffix("+PTX").replace(".", "")
192
+ if not number.isdigit():
193
+ raise ValueError(f"Invalid CUDA architecture {entry!r} in WITWIN_CUDA_GENCODE_ARCHES.")
194
+ flags.append(f"-gencode=arch=compute_{number},code=sm_{number}")
195
+ if include_ptx:
196
+ flags.append(f"-gencode=arch=compute_{number},code=compute_{number}")
197
+ return flags
198
+
199
+
200
+ def _conda_torch_ldflags() -> list[str]:
201
+ # Conda-distributed torch keeps c10.lib/torch_cuda.lib in <env>\Library\lib
202
+ # instead of site-packages\torch\lib, which cpp_extension does not search.
203
+ if os.name != "nt":
204
+ return []
205
+ library_lib = Path(sys.prefix) / "Library" / "lib"
206
+ if (library_lib / "c10.lib").exists():
207
+ return [f"/LIBPATH:{library_lib}"]
208
+ return []
209
+
210
+
211
+ class _StableOpsModule:
212
+ """Attribute-compatible view of the dispatcher operators."""
213
+
214
+ def __init__(self, library_path: Path) -> None:
215
+ self.__file__ = str(library_path)
216
+
217
+ def is_available(self) -> bool:
218
+ return bool(torch.cuda.is_available())
219
+
220
+ def debug_linear_indices(self, shape):
221
+ size_x, size_y, size_z = (int(value) for value in shape)
222
+ return torch.ops.witwin_maxwell_fdtd_cuda.debug_linear_indices(size_x, size_y, size_z)
223
+
224
+ def __getattr__(self, name: str):
225
+ return getattr(torch.ops.witwin_maxwell_fdtd_cuda, name)
226
+
227
+
228
+ def _load_extension_file(library_path: Path) -> _StableOpsModule:
229
+ torch.ops.load_library(str(library_path))
230
+ if not hasattr(torch.ops.witwin_maxwell_fdtd_cuda, "update_magnetic_hx_standard"):
231
+ raise ImportError(f"{library_path} does not register the Stable ABI Maxwell operators.")
232
+ return _StableOpsModule(library_path)
233
+
234
+
235
+ def _load_packaged_prebuilt_extension():
236
+ module_path = prebuilt_extension_path()
237
+ if not module_path.exists():
238
+ return None
239
+ return _load_extension_file(module_path)
240
+
241
+
242
+ def _load_prebuilt_extension(build_directory: Path):
243
+ # Profilers such as Nsight Systems break torch's MSVC detection in child
244
+ # processes, which rewrites build.ninja and forces a rebuild that then
245
+ # fails under the profiler. Loading the already-built module directly
246
+ # avoids invoking the build toolchain entirely.
247
+ module_path = build_directory / f"witwin_maxwell_fdtd_cuda{extension_suffix()}"
248
+ if not module_path.exists():
249
+ raise FileNotFoundError(
250
+ f"WITWIN_MAXWELL_FDTD_CUDA_PREBUILT=1 but {module_path} does not exist; "
251
+ "run a normal build first."
252
+ )
253
+ return _load_extension_file(module_path)
254
+
255
+
256
+ def build_extension(*, verbose: bool = False):
257
+ root = source_root()
258
+ default_build_directory = Path(tempfile.gettempdir()) / "witwin_maxwell_fdtd_cuda" / "stable_abi_v1"
259
+ build_directory = Path(os.environ.get("WITWIN_MAXWELL_FDTD_CUDA_BUILD_DIR", default_build_directory))
260
+ if os.environ.get("WITWIN_MAXWELL_FDTD_CUDA_SKIP_PREBUILT") != "1":
261
+ try:
262
+ module = _load_packaged_prebuilt_extension()
263
+ except Exception: # noqa: BLE001 - stale/ABI-mismatched prebuilt, rebuild instead
264
+ module = None
265
+ if module is not None:
266
+ return module
267
+ if os.environ.get("WITWIN_MAXWELL_FDTD_CUDA_PREBUILT") == "1":
268
+ return _load_prebuilt_extension(build_directory)
269
+ _ensure_windows_build_tools_on_path()
270
+ _ensure_cuda_home_from_nvcc()
271
+ build_directory.mkdir(parents=True, exist_ok=True)
272
+ library_path = load(
273
+ name="witwin_maxwell_fdtd_cuda",
274
+ sources=[str(path) for path in extension_sources()],
275
+ build_directory=str(build_directory),
276
+ extra_include_paths=[str(root), str(root / "kernels")],
277
+ extra_cflags=(
278
+ ["/O2", "/DTORCH_TARGET_VERSION=0x020a000000000000"]
279
+ if os.name == "nt"
280
+ else ["-O3", "-DTORCH_TARGET_VERSION=0x020a000000000000"]
281
+ ),
282
+ extra_cuda_cflags=[
283
+ "-O3",
284
+ "-DTORCH_TARGET_VERSION=0x020a000000000000",
285
+ "-DUSE_CUDA",
286
+ *_cuda_gencode_flags(),
287
+ ],
288
+ extra_ldflags=_conda_torch_ldflags(),
289
+ is_python_module=False,
290
+ verbose=verbose,
291
+ )
292
+ return _StableOpsModule(Path(library_path))