gsim 0.0.0__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.
@@ -0,0 +1,160 @@
1
+ """Result models for Palace simulations.
2
+
3
+ This module contains Pydantic models for simulation results and validation.
4
+ """
5
+
6
+ from __future__ import annotations
7
+
8
+ from pathlib import Path
9
+
10
+ from pydantic import BaseModel, ConfigDict, Field
11
+
12
+
13
+ class ValidationResult(BaseModel):
14
+ """Result of simulation configuration validation.
15
+
16
+ Attributes:
17
+ valid: Whether the configuration is valid
18
+ errors: List of error messages
19
+ warnings: List of warning messages
20
+ """
21
+
22
+ model_config = ConfigDict(validate_assignment=True)
23
+
24
+ valid: bool
25
+ errors: list[str] = Field(default_factory=list)
26
+ warnings: list[str] = Field(default_factory=list)
27
+
28
+ def __bool__(self) -> bool:
29
+ return self.valid
30
+
31
+ def __str__(self) -> str:
32
+ lines = []
33
+ if self.valid:
34
+ lines.append("Validation: PASSED")
35
+ else:
36
+ lines.append("Validation: FAILED")
37
+ if self.errors:
38
+ lines.append("Errors:")
39
+ lines.extend([f" - {e}" for e in self.errors])
40
+ if self.warnings:
41
+ lines.append("Warnings:")
42
+ lines.extend([f" - {w}" for w in self.warnings])
43
+ return "\n".join(lines)
44
+
45
+
46
+ class SimulationResult(BaseModel):
47
+ """Result from running a Palace simulation.
48
+
49
+ Attributes:
50
+ mesh_path: Path to the generated mesh file
51
+ output_dir: Output directory path
52
+ config_path: Path to the Palace config file
53
+ results: Dictionary mapping result filenames to paths
54
+ conductor_groups: Physical group info for conductors
55
+ dielectric_groups: Physical group info for dielectrics
56
+ port_groups: Physical group info for ports
57
+ boundary_groups: Physical group info for boundaries
58
+ port_info: Port metadata
59
+ """
60
+
61
+ model_config = ConfigDict(validate_assignment=True, arbitrary_types_allowed=True)
62
+
63
+ mesh_path: Path
64
+ output_dir: Path
65
+ config_path: Path | None = None
66
+ results: dict[str, Path] = Field(default_factory=dict)
67
+
68
+ # Physical group info for Palace
69
+ conductor_groups: dict = Field(default_factory=dict)
70
+ dielectric_groups: dict = Field(default_factory=dict)
71
+ port_groups: dict = Field(default_factory=dict)
72
+ boundary_groups: dict = Field(default_factory=dict)
73
+
74
+ # Port metadata
75
+ port_info: list = Field(default_factory=list)
76
+
77
+ # Mesh statistics
78
+ mesh_stats: dict = Field(default_factory=dict)
79
+
80
+ def __str__(self) -> str:
81
+ lines = ["Mesh Summary"]
82
+ lines.append("=" * 40)
83
+
84
+ # Dimensions
85
+ if self.mesh_stats:
86
+ bbox = self.mesh_stats.get("bbox", {})
87
+ if bbox:
88
+ dx = bbox.get("xmax", 0) - bbox.get("xmin", 0)
89
+ dy = bbox.get("ymax", 0) - bbox.get("ymin", 0)
90
+ dz = bbox.get("zmax", 0) - bbox.get("zmin", 0)
91
+ lines.append(f"Dimensions: {dx:.1f} x {dy:.1f} x {dz:.1f} µm")
92
+
93
+ # Mesh info
94
+ nodes = self.mesh_stats.get("nodes", 0)
95
+ elements = self.mesh_stats.get("elements", 0)
96
+ tets = self.mesh_stats.get("tetrahedra", 0)
97
+ if nodes or elements:
98
+ lines.append(f"Nodes: {nodes:,}")
99
+ lines.append(f"Elements: {elements:,}")
100
+ if tets:
101
+ lines.append(f"Tetrahedra: {tets:,}")
102
+
103
+ # Edge lengths
104
+ edge = self.mesh_stats.get("edge_length", {})
105
+ if edge:
106
+ e_min, e_max = edge.get("min", 0), edge.get("max", 0)
107
+ lines.append(f"Edge length: {e_min:.2f} - {e_max:.2f} µm")
108
+
109
+ # Mesh quality (gamma)
110
+ quality = self.mesh_stats.get("quality", {})
111
+ if quality:
112
+ q_min = quality.get("min", 0)
113
+ q_mean = quality.get("mean", 0)
114
+ lines.append(f"Quality: {q_mean:.3f} (min: {q_min:.3f})")
115
+
116
+ # SICN quality (shows invalid elements)
117
+ sicn = self.mesh_stats.get("sicn", {})
118
+ if sicn:
119
+ invalid = sicn.get("invalid", 0)
120
+ if invalid > 0:
121
+ lines.append(
122
+ f"SICN: {sicn.get('mean', 0):.3f} ({invalid} invalid!)"
123
+ )
124
+ else:
125
+ lines.append(f"SICN: {sicn.get('mean', 0):.3f} (all valid)")
126
+
127
+ # Physical groups
128
+ groups = self.mesh_stats.get("groups", {})
129
+ if groups:
130
+ volumes = groups.get("volumes", [])
131
+ surfaces = groups.get("surfaces", [])
132
+ lines.append("-" * 40)
133
+ if volumes:
134
+ lines.append(f"Volumes ({len(volumes)}):")
135
+ for v in volumes:
136
+ name = v["name"] if isinstance(v, dict) else v
137
+ tag = v.get("tag", "") if isinstance(v, dict) else ""
138
+ lines.append(f" - {name}" + (f" [{tag}]" if tag else ""))
139
+ if surfaces:
140
+ lines.append(f"Surfaces ({len(surfaces)}):")
141
+ for s in surfaces:
142
+ name = s["name"] if isinstance(s, dict) else s
143
+ tag = s.get("tag", "") if isinstance(s, dict) else ""
144
+ lines.append(f" - {name}" + (f" [{tag}]" if tag else ""))
145
+
146
+ lines.append("-" * 40)
147
+ lines.append(f"Mesh: {self.mesh_path}")
148
+ if self.config_path:
149
+ lines.append(f"Config: {self.config_path}")
150
+
151
+ return "\n".join(lines)
152
+
153
+ def __repr__(self) -> str:
154
+ return self.__str__()
155
+
156
+
157
+ __all__ = [
158
+ "SimulationResult",
159
+ "ValidationResult",
160
+ ]
@@ -0,0 +1,59 @@
1
+ """Material configuration model for Palace simulations.
2
+
3
+ This module contains the MaterialConfig Pydantic model for material property overrides
4
+ in simulations. Layer and stack configuration is handled by gsim.common.stack.
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ from typing import Literal, Self
10
+
11
+ from pydantic import BaseModel, ConfigDict, Field
12
+
13
+
14
+ class MaterialConfig(BaseModel):
15
+ """EM properties for a material.
16
+
17
+ Used for material property overrides in simulation classes.
18
+
19
+ Attributes:
20
+ type: Material type (conductor, dielectric, or semiconductor)
21
+ conductivity: Conductivity in S/m (for conductors)
22
+ permittivity: Relative permittivity (for dielectrics)
23
+ loss_tangent: Dielectric loss tangent
24
+ """
25
+
26
+ model_config = ConfigDict(validate_assignment=True)
27
+
28
+ type: Literal["conductor", "dielectric", "semiconductor"]
29
+ conductivity: float | None = Field(default=None, ge=0)
30
+ permittivity: float | None = Field(default=None, ge=1.0)
31
+ loss_tangent: float | None = Field(default=None, ge=0, le=1)
32
+
33
+ @classmethod
34
+ def conductor(cls, conductivity: float = 5.8e7) -> Self:
35
+ """Create a conductor material."""
36
+ return cls(type="conductor", conductivity=conductivity)
37
+
38
+ @classmethod
39
+ def dielectric(cls, permittivity: float, loss_tangent: float = 0.0) -> Self:
40
+ """Create a dielectric material."""
41
+ return cls(
42
+ type="dielectric", permittivity=permittivity, loss_tangent=loss_tangent
43
+ )
44
+
45
+ def to_dict(self) -> dict[str, object]:
46
+ """Convert to dictionary for YAML output."""
47
+ d: dict[str, object] = {"type": self.type}
48
+ if self.conductivity is not None:
49
+ d["conductivity"] = self.conductivity
50
+ if self.permittivity is not None:
51
+ d["permittivity"] = self.permittivity
52
+ if self.loss_tangent is not None:
53
+ d["loss_tangent"] = self.loss_tangent
54
+ return d
55
+
56
+
57
+ __all__ = [
58
+ "MaterialConfig",
59
+ ]
@@ -11,7 +11,7 @@ from enum import Enum
11
11
  from typing import TYPE_CHECKING
12
12
 
13
13
  if TYPE_CHECKING:
14
- from gsim.palace.stack import LayerStack
14
+ from gsim.common.stack import LayerStack
15
15
 
16
16
 
17
17
  class PortType(Enum):
gsim/viz.py CHANGED
@@ -5,10 +5,13 @@ This module provides visualization tools for meshes and simulation results.
5
5
 
6
6
  from __future__ import annotations
7
7
 
8
+ import logging
8
9
  from pathlib import Path
9
10
 
10
- import meshio # type: ignore[import-untyped]
11
- import pyvista as pv # type: ignore[import-untyped]
11
+ import meshio
12
+ import pyvista as pv
13
+
14
+ logger = logging.getLogger(__name__)
12
15
 
13
16
 
14
17
  def plot_mesh(
@@ -44,7 +47,7 @@ def plot_mesh(
44
47
  else:
45
48
  plotter = pv.Plotter(off_screen=True, window_size=[1200, 900])
46
49
 
47
- plotter.set_background("white")
50
+ plotter.set_background("white") # type: ignore[arg-type]
48
51
 
49
52
  if show_groups:
50
53
  # Filter to matching groups
@@ -64,7 +67,7 @@ def plot_mesh(
64
67
  line_width=1,
65
68
  label=group_map.get(gid, str(gid)),
66
69
  )
67
- plotter.add_legend()
70
+ plotter.add_legend() # type: ignore[call-arg]
68
71
  else:
69
72
  plotter.add_mesh(mesh, style="wireframe", color="black", line_width=1)
70
73
 
@@ -79,8 +82,8 @@ def plot_mesh(
79
82
  plotter.close()
80
83
  # Display in notebook if available
81
84
  try:
82
- from IPython.display import Image, display # type: ignore[import-untyped]
85
+ from IPython.display import Image, display
83
86
 
84
87
  display(Image(str(output)))
85
88
  except ImportError:
86
- print(f"Saved: {output}")
89
+ logger.info("Saved mesh plot to %s", output)
@@ -1,14 +1,15 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: gsim
3
- Version: 0.0.0
4
- Author-email: flaport <floris.laporte@gmail.com>
3
+ Version: 0.0.3
4
+ Author-email: GDSFactory <contact@gdsfactory.com>
5
5
  Classifier: Programming Language :: Python :: 3.12
6
6
  Classifier: Programming Language :: Python :: 3.13
7
+ Classifier: Programming Language :: Python :: 3.14
7
8
  Classifier: Operating System :: OS Independent
8
- Requires-Python: <3.14,>=3.12
9
+ Requires-Python: >=3.12
9
10
  Description-Content-Type: text/markdown
10
- Requires-Dist: gdsfactory>=8.32.2
11
- Requires-Dist: gdsfactoryplus>=1.3.7
11
+ Requires-Dist: gdsfactory>=9.32.0
12
+ Requires-Dist: gdsfactoryplus>=1.3.12
12
13
  Requires-Dist: gmsh
13
14
  Requires-Dist: meshio>=5.0.0
14
15
  Requires-Dist: plotly
@@ -43,8 +44,10 @@ Requires-Dist: towncrier>=24.0.0; extra == "dev"
43
44
  Requires-Dist: vega-datasets>=0.9.0; extra == "dev"
44
45
  Requires-Dist: nbstripout>=0.8.1; extra == "dev"
45
46
  Requires-Dist: ty>=0.0.13; extra == "dev"
47
+ Provides-Extra: docs
48
+ Requires-Dist: ihp-gdsfactory>=0.1.4; extra == "docs"
46
49
 
47
- # Gsim 0.0.0
50
+ # Gsim 0.0.3
48
51
 
49
52
  > a GDSFactory Simulation Plugin
50
53
 
@@ -0,0 +1,35 @@
1
+ gsim/__init__.py,sha256=nh1lQGlwYoL_ugWb6OIZHqtqs-AUEwN0GmJXNWsD7vc,288
2
+ gsim/gcloud.py,sha256=47ThJn-MSMSi2jGb4rElUknN70iY-YIO3mk6LxBRt7E,7426
3
+ gsim/viz.py,sha256=joFz6c7XasW8YER8ZLtJlqKFnzkt0O96Ye9hFxyfUUo,2673
4
+ gsim/common/__init__.py,sha256=HYVmB77s_0ELtEsp3ryaBod3thwiMPiz5rN-oc1SBxU,1298
5
+ gsim/common/geometry.py,sha256=WdFhbHFZjKM7HL35UDmNgmgwWJHPf3YFs-sxMd4w6f4,2170
6
+ gsim/common/stack/__init__.py,sha256=0v44u-BQSnW7Gb9t7a9tZ0HFxBVaCFKIAbXf40C3sFU,4023
7
+ gsim/common/stack/extractor.py,sha256=dRm63yOZntjV_TWp7c7yOCQs-32-xuFtvT1fHYGwxNU,17849
8
+ gsim/common/stack/materials.py,sha256=hQunUO3YwXDecrJxlklCTDcv0oXdSbhG_ByksgoOMrU,5164
9
+ gsim/common/stack/visualization.py,sha256=avBKbuXHcFXksK7xcjsiHgd2VDCTVhIPrpVj2wOokoI,19294
10
+ gsim/palace/__init__.py,sha256=SVUI7YRDKQeeKziu4Lc8hKGLRk_nxt4mK8o-hvveiec,3744
11
+ gsim/palace/base.py,sha256=XFmPM6KJFV5B-tl1217nmkC8D8g5AkJfvmHVW2WVP78,12561
12
+ gsim/palace/driven.py,sha256=w0j-hoXtt_XbTO9vt9e8_wWQqIhAIFEoZFth-sfYKYQ,25029
13
+ gsim/palace/eigenmode.py,sha256=2RXWW5Ph9-gbBSQMQqfCsac2kIt-XM4HX43fbnx0jVY,19001
14
+ gsim/palace/electrostatic.py,sha256=E0LKcWecBEZ0Z3WYwnUFRgqZtSwmvXx3dfbvq6WxRRU,13259
15
+ gsim/palace/mesh/__init__.py,sha256=m6p_RsxYgVXP5euVRoxpGag50R9TzCrkLH_vR8Ll2hc,1438
16
+ gsim/palace/mesh/config_generator.py,sha256=YebLBybZ3RK5dKpFb1U5SJAT_zw1a5SOHHAsaatkC-I,11581
17
+ gsim/palace/mesh/generator.py,sha256=c1-fshWHwB6H05wZiwEKzaYq403UOKn7CS0OPuJrkwY,8217
18
+ gsim/palace/mesh/geometry.py,sha256=jhnqpnTt9c2Ahs-FH7RAlpvol8swk4JyCvDdBpfRUfk,14675
19
+ gsim/palace/mesh/gmsh_utils.py,sha256=G8JJUSlUL2Rr1tcM9G0M6F9UjxePFpWSUGfmJ-LWh8E,13801
20
+ gsim/palace/mesh/groups.py,sha256=f-en11W2-RtR18xLMbSWHoWMf50-N59_yCNbUwE2nns,6243
21
+ gsim/palace/mesh/pipeline.py,sha256=cMGyuHuY6ZJYoT3cjf1Jneck2UZQTgGQQhG-D-0oz9Q,6695
22
+ gsim/palace/models/__init__.py,sha256=CHjp_1apFtROmBtyWmwuk8EpOYNj8WLqqAX2LPuSeic,1497
23
+ gsim/palace/models/geometry.py,sha256=9jD2HKeJKYhyaBLLCNc4LyuW-OpIouX32WYiE2XP9wg,987
24
+ gsim/palace/models/mesh.py,sha256=20aOEKViSe58JavFB90L02ZTGrNiopKiyUm_9MC3vJw,3446
25
+ gsim/palace/models/numerical.py,sha256=waWxOlOXTIoSdnxa5FujGv6DAfVBnu7GXAAoUv7P1DU,1818
26
+ gsim/palace/models/ports.py,sha256=ZcWwOGP59qPGjvv9Cu_gZ7pdlfbfAeaABSYqOLfWadw,4520
27
+ gsim/palace/models/problems.py,sha256=CPVsCprNWx3Sch5Y6RZMVJmw9Qo_zDmGygKoOIqT30s,6568
28
+ gsim/palace/models/results.py,sha256=14Lsc1uKOjhQwGixb0GRSS4A4tFulvNr-wQj_a_u5L4,5607
29
+ gsim/palace/models/stack.py,sha256=g3cw-YliXAoMqEoynMXYUY2Ys39llpN-9nPhRBQYfYU,1975
30
+ gsim/palace/ports/__init__.py,sha256=IoP11atw-Uf447AkZC5ixNcgqlNrC3GCnTGugjR_wgw,803
31
+ gsim/palace/ports/config.py,sha256=DK8TwspCsghQFl1uqKzu-YYEhjfu37rMDuHErOLPPgU,12289
32
+ gsim-0.0.3.dist-info/METADATA,sha256=_j2Xmw-F1l7bpIdVGlvmfYDQ2nuoyosOIeyXBffemT8,4347
33
+ gsim-0.0.3.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
34
+ gsim-0.0.3.dist-info/top_level.txt,sha256=USwf5QaCLsXq3JCR6ejGvHANZmIifvuQAAl7w-cUE0Y,5
35
+ gsim-0.0.3.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (80.10.1)
2
+ Generator: setuptools (80.10.2)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -1,18 +0,0 @@
1
- gsim/__init__.py,sha256=FmMjn3al4lB-2cGAlMcYoDpfEgb1CotlaBTKbfCCbfA,288
2
- gsim/gcloud.py,sha256=ulYaNyGXCRoTbud0im1qHyuwcvIpNpk1RRvnRxekCe4,5155
3
- gsim/viz.py,sha256=cakE-oH_O0wuL51gURl5YjLeCZQz-FFUzfr2jn2-MI4,2645
4
- gsim/palace/__init__.py,sha256=FHY3L9NRGx5xFCU-mLHKIDjJZc_G0kcIMoq6pX9RHyo,2938
5
- gsim/palace/mesh/__init__.py,sha256=vif960c46QbH1fkr4J9ydFh5ODcmxRS_Nx3D6JaVlMw,1207
6
- gsim/palace/mesh/generator.py,sha256=wQR64aqRMuHwA6klLHIASr03Z6tIUqHvvuwvovtwOBY,30735
7
- gsim/palace/mesh/gmsh_utils.py,sha256=G8JJUSlUL2Rr1tcM9G0M6F9UjxePFpWSUGfmJ-LWh8E,13801
8
- gsim/palace/mesh/pipeline.py,sha256=K5G1mb5kk9_y_lVHQH7fOOUquarlGEBtw3NTcNpni60,5936
9
- gsim/palace/ports/__init__.py,sha256=IoP11atw-Uf447AkZC5ixNcgqlNrC3GCnTGugjR_wgw,803
10
- gsim/palace/ports/config.py,sha256=LHgKqpk4w7rutUBEf-368bRu2l4N02m-Y8qPdKOuQmk,12289
11
- gsim/palace/stack/__init__.py,sha256=xcofg-9HuAiymv_77_AuEtTyVnpAjBbxOqRC3-kjQXs,3910
12
- gsim/palace/stack/extractor.py,sha256=elQn4aEux9_gslyPB1zDTdcOpdiBbCADF7B9vVPd6hg,20440
13
- gsim/palace/stack/materials.py,sha256=IzUGuPufWu7tx4uTuERodygsh8mA-BZh7NQfSBYLLBU,4637
14
- gsim/palace/stack/visualization.py,sha256=JwUDmdWqKYjSfeBX_EA1vp3ggxYAX8lI5soNIKHpwkg,19216
15
- gsim-0.0.0.dist-info/METADATA,sha256=ZNJ5JOBN4ruqnQszxFq9jP-Z1lxDpRP3lEI_RHvaxt4,4225
16
- gsim-0.0.0.dist-info/WHEEL,sha256=qELbo2s1Yzl39ZmrAibXA2jjPLUYfnVhUNTlyF1rq0Y,92
17
- gsim-0.0.0.dist-info/top_level.txt,sha256=USwf5QaCLsXq3JCR6ejGvHANZmIifvuQAAl7w-cUE0Y,5
18
- gsim-0.0.0.dist-info/RECORD,,