gsim 0.0.2__py3-none-any.whl → 0.0.3__py3-none-any.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.
- gsim/__init__.py +1 -1
- gsim/common/__init__.py +9 -13
- gsim/common/stack/extractor.py +4 -4
- gsim/common/stack/materials.py +2 -2
- gsim/common/stack/visualization.py +3 -3
- gsim/gcloud.py +78 -25
- gsim/palace/__init__.py +53 -64
- gsim/palace/base.py +313 -8
- gsim/palace/driven.py +26 -302
- gsim/palace/eigenmode.py +44 -264
- gsim/palace/electrostatic.py +35 -259
- gsim/palace/mesh/__init__.py +13 -1
- gsim/palace/mesh/config_generator.py +367 -0
- gsim/palace/mesh/generator.py +40 -899
- gsim/palace/mesh/geometry.py +472 -0
- gsim/palace/mesh/groups.py +170 -0
- gsim/palace/models/__init__.py +8 -15
- gsim/palace/models/mesh.py +9 -9
- gsim/palace/models/numerical.py +9 -9
- gsim/palace/models/ports.py +4 -5
- gsim/palace/models/problems.py +1 -1
- gsim/palace/models/results.py +5 -4
- gsim/viz.py +9 -6
- {gsim-0.0.2.dist-info → gsim-0.0.3.dist-info}/METADATA +6 -5
- gsim-0.0.3.dist-info/RECORD +35 -0
- {gsim-0.0.2.dist-info → gsim-0.0.3.dist-info}/WHEEL +1 -1
- gsim-0.0.2.dist-info/RECORD +0 -32
- {gsim-0.0.2.dist-info → gsim-0.0.3.dist-info}/top_level.txt +0 -0
gsim/__init__.py
CHANGED
gsim/common/__init__.py
CHANGED
|
@@ -35,27 +35,23 @@ from gsim.common.stack import (
|
|
|
35
35
|
Stack = LayerStack
|
|
36
36
|
|
|
37
37
|
__all__ = [
|
|
38
|
-
|
|
38
|
+
"MATERIALS_DB",
|
|
39
39
|
"Geometry",
|
|
40
|
-
|
|
40
|
+
"Layer",
|
|
41
41
|
"LayerStack",
|
|
42
|
+
"MaterialProperties",
|
|
42
43
|
"Stack",
|
|
43
|
-
"Layer",
|
|
44
44
|
"StackLayer",
|
|
45
45
|
"ValidationResult",
|
|
46
|
-
# Stack functions
|
|
47
|
-
"get_stack",
|
|
48
|
-
"load_stack_yaml",
|
|
49
46
|
"extract_from_pdk",
|
|
50
47
|
"extract_layer_stack",
|
|
51
|
-
"parse_layer_stack",
|
|
52
|
-
"print_stack",
|
|
53
|
-
"print_stack_table",
|
|
54
|
-
"plot_stack",
|
|
55
|
-
# Materials
|
|
56
|
-
"MATERIALS_DB",
|
|
57
|
-
"MaterialProperties",
|
|
58
48
|
"get_material_properties",
|
|
49
|
+
"get_stack",
|
|
50
|
+
"load_stack_yaml",
|
|
59
51
|
"material_is_conductor",
|
|
60
52
|
"material_is_dielectric",
|
|
53
|
+
"parse_layer_stack",
|
|
54
|
+
"plot_stack",
|
|
55
|
+
"print_stack",
|
|
56
|
+
"print_stack_table",
|
|
61
57
|
]
|
gsim/common/stack/extractor.py
CHANGED
|
@@ -288,7 +288,7 @@ def _get_gds_layer_tuple(layer_level: LayerLevel) -> tuple[int, int]:
|
|
|
288
288
|
if hasattr(layer, "layer"):
|
|
289
289
|
inner = layer.layer
|
|
290
290
|
if hasattr(inner, "layer") and hasattr(inner, "datatype"):
|
|
291
|
-
return (int(inner.layer), int(inner.datatype))
|
|
291
|
+
return (int(inner.layer), int(inner.datatype)) # type: ignore[arg-type]
|
|
292
292
|
if isinstance(inner, int):
|
|
293
293
|
datatype = getattr(layer, "datatype", 0)
|
|
294
294
|
return (int(inner), int(datatype) if datatype else 0)
|
|
@@ -299,11 +299,11 @@ def _get_gds_layer_tuple(layer_level: LayerLevel) -> tuple[int, int]:
|
|
|
299
299
|
return (int(innermost), int(datatype) if datatype else 0)
|
|
300
300
|
|
|
301
301
|
if hasattr(layer, "layer") and hasattr(layer, "datatype"):
|
|
302
|
-
return (int(layer.layer), int(layer.datatype))
|
|
302
|
+
return (int(layer.layer), int(layer.datatype)) # type: ignore[arg-type]
|
|
303
303
|
|
|
304
304
|
if hasattr(layer, "value"):
|
|
305
305
|
if isinstance(layer.value, tuple):
|
|
306
|
-
return (int(layer.value[0]), int(layer.value[1]))
|
|
306
|
+
return (int(layer.value[0]), int(layer.value[1])) # type: ignore[arg-type]
|
|
307
307
|
if isinstance(layer.value, int):
|
|
308
308
|
return (int(layer.value), 0)
|
|
309
309
|
|
|
@@ -314,7 +314,7 @@ def _get_gds_layer_tuple(layer_level: LayerLevel) -> tuple[int, int]:
|
|
|
314
314
|
return (0, 0)
|
|
315
315
|
|
|
316
316
|
try:
|
|
317
|
-
return (int(layer), 0)
|
|
317
|
+
return (int(layer), 0) # type: ignore[arg-type]
|
|
318
318
|
except (TypeError, ValueError):
|
|
319
319
|
logger.warning("Could not parse layer %s, using (0, 0)", layer)
|
|
320
320
|
return (0, 0)
|
gsim/common/stack/materials.py
CHANGED
|
@@ -33,14 +33,14 @@ class MaterialProperties(BaseModel):
|
|
|
33
33
|
return d
|
|
34
34
|
|
|
35
35
|
@classmethod
|
|
36
|
-
def conductor(cls, conductivity: float = 5.8e7) ->
|
|
36
|
+
def conductor(cls, conductivity: float = 5.8e7) -> MaterialProperties:
|
|
37
37
|
"""Create a conductor material."""
|
|
38
38
|
return cls(type="conductor", conductivity=conductivity)
|
|
39
39
|
|
|
40
40
|
@classmethod
|
|
41
41
|
def dielectric(
|
|
42
42
|
cls, permittivity: float, loss_tangent: float = 0.0
|
|
43
|
-
) ->
|
|
43
|
+
) -> MaterialProperties:
|
|
44
44
|
"""Create a dielectric material."""
|
|
45
45
|
return cls(
|
|
46
46
|
type="dielectric", permittivity=permittivity, loss_tangent=loss_tangent
|
|
@@ -43,15 +43,15 @@ def _get_gds_layer_number(layer_level: LayerLevel) -> int | None:
|
|
|
43
43
|
if hasattr(layer, "layer"):
|
|
44
44
|
inner = layer.layer
|
|
45
45
|
if hasattr(inner, "layer"):
|
|
46
|
-
return int(inner.layer)
|
|
46
|
+
return int(inner.layer) # type: ignore[arg-type]
|
|
47
47
|
if isinstance(inner, int):
|
|
48
48
|
return int(inner)
|
|
49
49
|
|
|
50
50
|
# Handle enum with value
|
|
51
51
|
if hasattr(layer, "value"):
|
|
52
52
|
if isinstance(layer.value, tuple):
|
|
53
|
-
return int(layer.value[0])
|
|
54
|
-
return int(layer.value)
|
|
53
|
+
return int(layer.value[0]) # type: ignore[arg-type]
|
|
54
|
+
return int(layer.value) # type: ignore[arg-type]
|
|
55
55
|
|
|
56
56
|
return None
|
|
57
57
|
|
gsim/gcloud.py
CHANGED
|
@@ -16,17 +16,74 @@ Usage:
|
|
|
16
16
|
|
|
17
17
|
from __future__ import annotations
|
|
18
18
|
|
|
19
|
-
import zipfile
|
|
20
19
|
from pathlib import Path
|
|
21
20
|
from typing import TYPE_CHECKING
|
|
22
21
|
|
|
23
|
-
from gdsfactoryplus import sim
|
|
22
|
+
from gdsfactoryplus import sim
|
|
24
23
|
|
|
25
24
|
if TYPE_CHECKING:
|
|
26
25
|
from collections.abc import Callable
|
|
27
26
|
from typing import Literal
|
|
28
27
|
|
|
29
28
|
|
|
29
|
+
def _handle_failed_job(job, output_dir: Path, verbose: bool) -> None:
|
|
30
|
+
"""Handle a failed simulation job by downloading logs and raising informative error.
|
|
31
|
+
|
|
32
|
+
Args:
|
|
33
|
+
job: The finished Job object with non-zero exit code
|
|
34
|
+
output_dir: Directory to download logs to
|
|
35
|
+
verbose: Whether to print progress
|
|
36
|
+
|
|
37
|
+
Raises:
|
|
38
|
+
RuntimeError: Always raised with detailed error information
|
|
39
|
+
"""
|
|
40
|
+
error_parts = [
|
|
41
|
+
f"Simulation failed with exit code {job.exit_code}",
|
|
42
|
+
f"Status: {job.status.value}",
|
|
43
|
+
]
|
|
44
|
+
|
|
45
|
+
if job.status_reason:
|
|
46
|
+
error_parts.append(f"Reason: {job.status_reason}")
|
|
47
|
+
if job.detail_reason:
|
|
48
|
+
error_parts.append(f"Details: {job.detail_reason}")
|
|
49
|
+
|
|
50
|
+
# Try to download logs even though job failed
|
|
51
|
+
try:
|
|
52
|
+
if job.download_urls:
|
|
53
|
+
if verbose:
|
|
54
|
+
print("Downloading logs from failed job...") # noqa: T201
|
|
55
|
+
|
|
56
|
+
raw_results = sim.download_results(job, output_dir=output_dir)
|
|
57
|
+
|
|
58
|
+
# Flatten results to find all files
|
|
59
|
+
all_files: dict[str, Path] = {}
|
|
60
|
+
for result_path in raw_results.values():
|
|
61
|
+
if result_path.is_dir():
|
|
62
|
+
for file_path in result_path.rglob("*"):
|
|
63
|
+
if file_path.is_file() and not file_path.name.startswith("."):
|
|
64
|
+
all_files[file_path.name] = file_path
|
|
65
|
+
else:
|
|
66
|
+
all_files[result_path.name] = result_path
|
|
67
|
+
|
|
68
|
+
# Look for log files and display them
|
|
69
|
+
log_files = ["palace.log", "stdout.log", "stderr.log", "output.log"]
|
|
70
|
+
for log_name in log_files:
|
|
71
|
+
if log_name in all_files:
|
|
72
|
+
content = all_files[log_name].read_text()
|
|
73
|
+
error_parts.append(f"\n--- {log_name} (last 100 lines) ---")
|
|
74
|
+
lines = content.strip().split("\n")
|
|
75
|
+
error_parts.append("\n".join(lines[-100:]))
|
|
76
|
+
break
|
|
77
|
+
|
|
78
|
+
if verbose and all_files:
|
|
79
|
+
print(f"Logs downloaded to {output_dir}") # noqa: T201
|
|
80
|
+
|
|
81
|
+
except Exception as e:
|
|
82
|
+
error_parts.append(f"(Failed to download logs: {e})")
|
|
83
|
+
|
|
84
|
+
raise RuntimeError("\n".join(error_parts))
|
|
85
|
+
|
|
86
|
+
|
|
30
87
|
def _get_job_definition(job_type: str):
|
|
31
88
|
"""Get JobDefinition enum value by name."""
|
|
32
89
|
job_type_upper = job_type.upper()
|
|
@@ -37,7 +94,7 @@ def _get_job_definition(job_type: str):
|
|
|
37
94
|
|
|
38
95
|
|
|
39
96
|
def upload_simulation_dir(input_dir: str | Path, job_type: str):
|
|
40
|
-
"""
|
|
97
|
+
"""Upload a simulation directory for cloud execution.
|
|
41
98
|
|
|
42
99
|
Args:
|
|
43
100
|
input_dir: Directory containing simulation files
|
|
@@ -47,21 +104,8 @@ def upload_simulation_dir(input_dir: str | Path, job_type: str):
|
|
|
47
104
|
PreJob object from gdsfactoryplus
|
|
48
105
|
"""
|
|
49
106
|
input_dir = Path(input_dir)
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
try:
|
|
53
|
-
with zipfile.ZipFile(zip_path, "w", zipfile.ZIP_STORED) as zf:
|
|
54
|
-
for file in input_dir.rglob("*"):
|
|
55
|
-
if file.is_file():
|
|
56
|
-
zf.write(file, arcname=file.relative_to(input_dir))
|
|
57
|
-
|
|
58
|
-
job_definition = _get_job_definition(job_type)
|
|
59
|
-
pre_job = sim.upload_simulation(path=zip_path, job_definition=job_definition)
|
|
60
|
-
finally:
|
|
61
|
-
if zip_path.exists():
|
|
62
|
-
zip_path.unlink()
|
|
63
|
-
|
|
64
|
-
return pre_job
|
|
107
|
+
job_definition = _get_job_definition(job_type)
|
|
108
|
+
return sim.upload_simulation(path=input_dir, job_definition=job_definition)
|
|
65
109
|
|
|
66
110
|
|
|
67
111
|
def run_simulation(
|
|
@@ -125,18 +169,27 @@ def run_simulation(
|
|
|
125
169
|
|
|
126
170
|
# Check status
|
|
127
171
|
if finished_job.exit_code != 0:
|
|
128
|
-
|
|
129
|
-
f"Simulation failed with exit code {finished_job.exit_code}. "
|
|
130
|
-
f"Status: {finished_job.status.value}"
|
|
131
|
-
)
|
|
172
|
+
_handle_failed_job(finished_job, output_dir, verbose)
|
|
132
173
|
|
|
133
174
|
# Download
|
|
134
|
-
|
|
175
|
+
raw_results = sim.download_results(finished_job)
|
|
176
|
+
|
|
177
|
+
# Flatten results: gdsfactoryplus returns extracted directories,
|
|
178
|
+
# but we want a dict of filename -> Path for individual files
|
|
179
|
+
results: dict[str, Path] = {}
|
|
180
|
+
for result_path in raw_results.values():
|
|
181
|
+
if result_path.is_dir():
|
|
182
|
+
# Recursively find all files in the extracted directory
|
|
183
|
+
for file_path in result_path.rglob("*"):
|
|
184
|
+
if file_path.is_file() and not file_path.name.startswith("."):
|
|
185
|
+
results[file_path.name] = file_path
|
|
186
|
+
else:
|
|
187
|
+
results[result_path.name] = result_path
|
|
135
188
|
|
|
136
189
|
if verbose and results:
|
|
190
|
+
# Find common parent directory for display
|
|
137
191
|
first_path = next(iter(results.values()))
|
|
138
|
-
|
|
139
|
-
print(f"Downloaded {len(results)} files to {download_dir}") # noqa: T201
|
|
192
|
+
print(f"Downloaded {len(results)} files to {first_path.parent}") # noqa: T201
|
|
140
193
|
|
|
141
194
|
return results
|
|
142
195
|
|
gsim/palace/__init__.py
CHANGED
|
@@ -29,12 +29,30 @@ from __future__ import annotations
|
|
|
29
29
|
|
|
30
30
|
from functools import partial
|
|
31
31
|
|
|
32
|
-
from gsim.gcloud import print_job_summary
|
|
33
|
-
from gsim.gcloud import run_simulation as _run_simulation
|
|
34
|
-
|
|
35
32
|
# Common components (shared with FDTD)
|
|
36
33
|
from gsim.common import Geometry, LayerStack, Stack
|
|
37
34
|
|
|
35
|
+
# Stack utilities (from common, shared with FDTD)
|
|
36
|
+
from gsim.common.stack import (
|
|
37
|
+
MATERIALS_DB,
|
|
38
|
+
Layer,
|
|
39
|
+
MaterialProperties,
|
|
40
|
+
StackLayer,
|
|
41
|
+
extract_from_pdk,
|
|
42
|
+
extract_layer_stack,
|
|
43
|
+
get_material_properties,
|
|
44
|
+
get_stack,
|
|
45
|
+
load_stack_yaml,
|
|
46
|
+
material_is_conductor,
|
|
47
|
+
material_is_dielectric,
|
|
48
|
+
parse_layer_stack,
|
|
49
|
+
plot_stack,
|
|
50
|
+
print_stack,
|
|
51
|
+
print_stack_table,
|
|
52
|
+
)
|
|
53
|
+
from gsim.gcloud import print_job_summary
|
|
54
|
+
from gsim.gcloud import run_simulation as _run_simulation
|
|
55
|
+
|
|
38
56
|
# New simulation classes (composition, no inheritance)
|
|
39
57
|
from gsim.palace.driven import DrivenSim
|
|
40
58
|
from gsim.palace.eigenmode import EigenmodeSim
|
|
@@ -58,7 +76,6 @@ from gsim.palace.models import (
|
|
|
58
76
|
GeometryConfig,
|
|
59
77
|
MagnetostaticConfig,
|
|
60
78
|
MaterialConfig,
|
|
61
|
-
MeshConfig as MeshConfigModel,
|
|
62
79
|
NumericalConfig,
|
|
63
80
|
PortConfig,
|
|
64
81
|
SimulationResult,
|
|
@@ -67,6 +84,9 @@ from gsim.palace.models import (
|
|
|
67
84
|
ValidationResult,
|
|
68
85
|
WavePortConfig,
|
|
69
86
|
)
|
|
87
|
+
from gsim.palace.models import (
|
|
88
|
+
MeshConfig as MeshConfigModel,
|
|
89
|
+
)
|
|
70
90
|
|
|
71
91
|
# Port utilities
|
|
72
92
|
from gsim.palace.ports import (
|
|
@@ -79,91 +99,60 @@ from gsim.palace.ports import (
|
|
|
79
99
|
extract_ports,
|
|
80
100
|
)
|
|
81
101
|
|
|
82
|
-
# Stack utilities (from common, shared with FDTD)
|
|
83
|
-
from gsim.common.stack import (
|
|
84
|
-
MATERIALS_DB,
|
|
85
|
-
Layer,
|
|
86
|
-
LayerStack,
|
|
87
|
-
MaterialProperties,
|
|
88
|
-
StackLayer,
|
|
89
|
-
ValidationResult as StackValidationResult,
|
|
90
|
-
extract_from_pdk,
|
|
91
|
-
extract_layer_stack,
|
|
92
|
-
get_material_properties,
|
|
93
|
-
get_stack,
|
|
94
|
-
load_stack_yaml,
|
|
95
|
-
material_is_conductor,
|
|
96
|
-
material_is_dielectric,
|
|
97
|
-
parse_layer_stack,
|
|
98
|
-
plot_stack,
|
|
99
|
-
print_stack,
|
|
100
|
-
print_stack_table,
|
|
101
|
-
)
|
|
102
|
-
|
|
103
102
|
# Visualization
|
|
104
103
|
from gsim.viz import plot_mesh
|
|
105
104
|
|
|
106
|
-
|
|
107
105
|
__all__ = [
|
|
108
|
-
|
|
106
|
+
"MATERIALS_DB",
|
|
107
|
+
"CPWPortConfig",
|
|
108
|
+
"DrivenConfig",
|
|
109
109
|
"DrivenSim",
|
|
110
|
+
"EigenmodeConfig",
|
|
110
111
|
"EigenmodeSim",
|
|
112
|
+
"ElectrostaticConfig",
|
|
111
113
|
"ElectrostaticSim",
|
|
112
|
-
# Common components (shared with FDTD)
|
|
113
114
|
"Geometry",
|
|
114
|
-
"Stack",
|
|
115
|
-
# Problem configs
|
|
116
|
-
"DrivenConfig",
|
|
117
|
-
"EigenmodeConfig",
|
|
118
|
-
"ElectrostaticConfig",
|
|
119
|
-
"MagnetostaticConfig",
|
|
120
|
-
"TransientConfig",
|
|
121
|
-
# Port configs
|
|
122
|
-
"CPWPortConfig",
|
|
123
|
-
"PortConfig",
|
|
124
|
-
"TerminalConfig",
|
|
125
|
-
"WavePortConfig",
|
|
126
|
-
# Other configs
|
|
127
115
|
"GeometryConfig",
|
|
116
|
+
"GroundPlane",
|
|
117
|
+
"Layer",
|
|
118
|
+
"LayerStack",
|
|
119
|
+
"MagnetostaticConfig",
|
|
128
120
|
"MaterialConfig",
|
|
121
|
+
"MaterialProperties",
|
|
122
|
+
"MeshConfig",
|
|
129
123
|
"MeshConfigModel",
|
|
124
|
+
"MeshPreset",
|
|
125
|
+
"MeshResult",
|
|
130
126
|
"NumericalConfig",
|
|
127
|
+
"PalacePort",
|
|
128
|
+
"PortConfig",
|
|
129
|
+
"PortGeometry",
|
|
130
|
+
"PortType",
|
|
131
131
|
"SimulationResult",
|
|
132
|
+
"Stack",
|
|
133
|
+
"StackLayer",
|
|
134
|
+
"TerminalConfig",
|
|
135
|
+
"TransientConfig",
|
|
132
136
|
"ValidationResult",
|
|
133
|
-
|
|
134
|
-
"
|
|
135
|
-
"
|
|
136
|
-
"
|
|
137
|
-
"MaterialProperties",
|
|
137
|
+
"WavePortConfig",
|
|
138
|
+
"configure_cpw_port",
|
|
139
|
+
"configure_inplane_port",
|
|
140
|
+
"configure_via_port",
|
|
138
141
|
"extract_from_pdk",
|
|
139
142
|
"extract_layer_stack",
|
|
143
|
+
"extract_ports",
|
|
144
|
+
"generate_mesh",
|
|
140
145
|
"get_material_properties",
|
|
141
146
|
"get_stack",
|
|
142
147
|
"load_stack_yaml",
|
|
143
148
|
"material_is_conductor",
|
|
144
149
|
"material_is_dielectric",
|
|
145
150
|
"parse_layer_stack",
|
|
151
|
+
"plot_mesh",
|
|
146
152
|
"plot_stack",
|
|
153
|
+
"print_job_summary",
|
|
147
154
|
"print_stack",
|
|
148
155
|
"print_stack_table",
|
|
149
|
-
# Mesh utilities
|
|
150
|
-
"GroundPlane",
|
|
151
|
-
"MeshConfig",
|
|
152
|
-
"MeshPreset",
|
|
153
|
-
"MeshResult",
|
|
154
|
-
"generate_mesh",
|
|
155
|
-
"plot_mesh",
|
|
156
|
-
# Port utilities
|
|
157
|
-
"PalacePort",
|
|
158
|
-
"PortGeometry",
|
|
159
|
-
"PortType",
|
|
160
|
-
"StackLayer",
|
|
161
|
-
"configure_cpw_port",
|
|
162
|
-
"configure_inplane_port",
|
|
163
|
-
"configure_via_port",
|
|
164
|
-
"extract_ports",
|
|
165
|
-
# Cloud
|
|
166
|
-
"print_job_summary",
|
|
167
156
|
"run_simulation",
|
|
168
157
|
]
|
|
169
158
|
|