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.
- witwin/maxwell/__init__.py +164 -0
- witwin/maxwell/adapters/__init__.py +1 -0
- witwin/maxwell/adapters/gds.py +203 -0
- witwin/maxwell/adapters/tidy3d.py +1669 -0
- witwin/maxwell/adjoint_inputs.py +70 -0
- witwin/maxwell/compiler/__init__.py +11 -0
- witwin/maxwell/compiler/materials.py +1355 -0
- witwin/maxwell/compiler/monitors.py +164 -0
- witwin/maxwell/compiler/sources.py +222 -0
- witwin/maxwell/fdfd/__init__.py +3 -0
- witwin/maxwell/fdfd/adjoint/__init__.py +3 -0
- witwin/maxwell/fdfd/adjoint/bridge.py +180 -0
- witwin/maxwell/fdfd/ams.py +300 -0
- witwin/maxwell/fdfd/krylov.py +280 -0
- witwin/maxwell/fdfd/plotting.py +110 -0
- witwin/maxwell/fdfd/postprocess.py +33 -0
- witwin/maxwell/fdfd/solver.py +1057 -0
- witwin/maxwell/fdtd/__init__.py +4 -0
- witwin/maxwell/fdtd/adjoint/__init__.py +21 -0
- witwin/maxwell/fdtd/adjoint/bridge.py +746 -0
- witwin/maxwell/fdtd/adjoint/capabilities.py +29 -0
- witwin/maxwell/fdtd/adjoint/core.py +3614 -0
- witwin/maxwell/fdtd/adjoint/dispatch.py +684 -0
- witwin/maxwell/fdtd/adjoint/native.py +2561 -0
- witwin/maxwell/fdtd/adjoint/profiler.py +195 -0
- witwin/maxwell/fdtd/adjoint/reverse_common.py +207 -0
- witwin/maxwell/fdtd/adjoint/seeds.py +524 -0
- witwin/maxwell/fdtd/boundary/__init__.py +37 -0
- witwin/maxwell/fdtd/boundary/bloch.py +90 -0
- witwin/maxwell/fdtd/boundary/common.py +41 -0
- witwin/maxwell/fdtd/boundary/cpml.py +527 -0
- witwin/maxwell/fdtd/boundary/runtime.py +209 -0
- witwin/maxwell/fdtd/checkpoint.py +227 -0
- witwin/maxwell/fdtd/coords.py +32 -0
- witwin/maxwell/fdtd/cuda/__init__.py +11 -0
- witwin/maxwell/fdtd/cuda/backend.py +3532 -0
- witwin/maxwell/fdtd/cuda/build.py +292 -0
- witwin/maxwell/fdtd/cuda/extension.cpp +2053 -0
- witwin/maxwell/fdtd/cuda/kernels/adjoint.cu +5290 -0
- witwin/maxwell/fdtd/cuda/kernels/aniso.cu +1704 -0
- witwin/maxwell/fdtd/cuda/kernels/boundary.cu +424 -0
- witwin/maxwell/fdtd/cuda/kernels/common.cu +74 -0
- witwin/maxwell/fdtd/cuda/kernels/common.cuh +82 -0
- witwin/maxwell/fdtd/cuda/kernels/dispersive.cu +782 -0
- witwin/maxwell/fdtd/cuda/kernels/electric.cu +3613 -0
- witwin/maxwell/fdtd/cuda/kernels/magnetic.cu +781 -0
- witwin/maxwell/fdtd/cuda/kernels/observers.cu +347 -0
- witwin/maxwell/fdtd/cuda/kernels/projection.cu +211 -0
- witwin/maxwell/fdtd/cuda/kernels/sources.cu +1482 -0
- witwin/maxwell/fdtd/cuda/kernels/spectral.cu +297 -0
- witwin/maxwell/fdtd/cuda/launch.h +23 -0
- witwin/maxwell/fdtd/cuda/prebuilt/witwin_maxwell_fdtd_cuda.pyd +0 -0
- witwin/maxwell/fdtd/cuda/runtime/__init__.py +6 -0
- witwin/maxwell/fdtd/cuda/runtime/dispatcher.py +6 -0
- witwin/maxwell/fdtd/cuda/runtime/graph.py +33 -0
- witwin/maxwell/fdtd/cuda/tensors.h +35 -0
- witwin/maxwell/fdtd/dispersion.py +48 -0
- witwin/maxwell/fdtd/evaluation.py +290 -0
- witwin/maxwell/fdtd/excitation/__init__.py +27 -0
- witwin/maxwell/fdtd/excitation/injection.py +1102 -0
- witwin/maxwell/fdtd/excitation/modes.py +1675 -0
- witwin/maxwell/fdtd/excitation/spatial.py +469 -0
- witwin/maxwell/fdtd/excitation/temporal.py +510 -0
- witwin/maxwell/fdtd/excitation/tfsf_apply.py +264 -0
- witwin/maxwell/fdtd/excitation/tfsf_common.py +421 -0
- witwin/maxwell/fdtd/excitation/tfsf_specs.py +490 -0
- witwin/maxwell/fdtd/excitation/tfsf_state.py +778 -0
- witwin/maxwell/fdtd/io.py +31 -0
- witwin/maxwell/fdtd/material_pullback.py +371 -0
- witwin/maxwell/fdtd/meshing/__init__.py +3 -0
- witwin/maxwell/fdtd/meshing/autogrid.py +335 -0
- witwin/maxwell/fdtd/observers.py +1453 -0
- witwin/maxwell/fdtd/plotting.py +121 -0
- witwin/maxwell/fdtd/postprocess.py +205 -0
- witwin/maxwell/fdtd/runtime/__init__.py +119 -0
- witwin/maxwell/fdtd/runtime/initialization.py +236 -0
- witwin/maxwell/fdtd/runtime/materials.py +1563 -0
- witwin/maxwell/fdtd/runtime/module_cache.py +31 -0
- witwin/maxwell/fdtd/runtime/spectral.py +581 -0
- witwin/maxwell/fdtd/runtime/stepping.py +1987 -0
- witwin/maxwell/fdtd/solver.py +502 -0
- witwin/maxwell/geometry/__init__.py +5 -0
- witwin/maxwell/geometry/polyslab.py +299 -0
- witwin/maxwell/materials.py +3 -0
- witwin/maxwell/media.py +1467 -0
- witwin/maxwell/monitors.py +743 -0
- witwin/maxwell/ports.py +113 -0
- witwin/maxwell/postprocess/RCS.py +139 -0
- witwin/maxwell/postprocess/__init__.py +42 -0
- witwin/maxwell/postprocess/diffraction.py +219 -0
- witwin/maxwell/postprocess/directivity.py +152 -0
- witwin/maxwell/postprocess/emission.py +67 -0
- witwin/maxwell/postprocess/modal.py +324 -0
- witwin/maxwell/postprocess/nfft.py +266 -0
- witwin/maxwell/postprocess/scattering_parameters.py +358 -0
- witwin/maxwell/postprocess/stratton_chu.py +1193 -0
- witwin/maxwell/result.py +967 -0
- witwin/maxwell/scene.py +1338 -0
- witwin/maxwell/simulation.py +659 -0
- witwin/maxwell/sources.py +917 -0
- witwin/maxwell/visualization/__init__.py +28 -0
- witwin/maxwell/visualization/interactive.py +484 -0
- witwin/maxwell/visualization/plots.py +568 -0
- witwin_maxwell-0.3.0.dist-info/METADATA +184 -0
- witwin_maxwell-0.3.0.dist-info/RECORD +107 -0
- witwin_maxwell-0.3.0.dist-info/WHEEL +4 -0
- 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))
|