Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .claude/CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,8 @@ pipeline orchestration, and GUI stay in their own packages.
- **Geometries:** a `BaseGeometry` subclass provides `name`, `stackup_xml`,
`simconfig_filename`, `input_parameter_iterator`, `create_gds_file`, and
`create_dataset`; `is_feasible(params)` is optional and rejects draws before
they are drawn, and `feasibility_constraints()` states the same rules as
they are drawn, `simulation_ports(params)` is optional and changes port fields
(never their number or order) per sample, and `feasibility_constraints()` states the same rules as
expressions (`geometry/constraints.py` grammar) for the ONNX metadata — a
test must keep the two in agreement. Never clamp or repair parameters inside `create_gds_file` —
the parameter table records the requested values, so the model would learn a
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ Each stage can be left out, e.g. to retrain on existing simulation results. An i
| Stage | Class | What it does |
|-------|-------|--------------|
| GDS generation | `GDSGenerator` | Samples the geometry's parameters and draws a GDS layout for each |
| Design-rule check | `DRCChecker` | Snaps layouts to the manufacturing grid and drops those that violate the IHP SG13G2 rules |
| Design-rule check | `DRCChecker` | Snaps layouts to the manufacturing grid and drops those that violate the IHP SG13G2 rules or have a port marker off its metal |
| GDS conversion | `GDSConverter` | Meshes the layouts for Palace with [gds2palace](https://github.com/VolkerMuehlhaus/gds2palace_ihp_sg13g2) |
| EM simulation | `PalaceSimulator` | Runs Palace and stores the S-parameters as Touchstone files |
| Model training | `ModelTrainer` | Trains (and by default tunes) a PyTorch model from geometry and frequency to S-parameters |
Expand Down
16 changes: 15 additions & 1 deletion docs/custom_class.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,10 @@ The Python class should be a `@dataclass` extending `orca.BaseGeometry` and must

**Optional methods:**

- `electrical_parameters(ntwk) -> dict[str, np.ndarray]` — The figures of merit of a network of this geometry, which `ModelTester` reports the model's error for next to the S-parameter error: curves over `ntwk.f` (such as L, R and Q) and scalars as 0-d arrays (such as the self-resonance frequency `srf_f`). Which port is which is a property of the layout, so the geometry decides how to read its network. `orca.utils.postprocessing` has the usual ones, with the ports given explicitly: `inductor_parameters(ntwk, ends, shorted)` and `transformer_parameters(ntwk, primary, secondary, shorted)`, which drive each winding differentially with its center tap (`shorted`) AC-grounded. Import it inside the method. The default returns nothing, so only the S-parameter error is reported. Errors are relative, except for the names in the class attribute `absolute_error_parameters` (e.g. `frozenset({"k"})` for a coupling factor that is near zero for weak coupling). With `ModelTester(plot=True)` the same parameters are plotted, reference against prediction.
- `feasibility_constraints() -> list[str]` — The same rules as `is_feasible()`, written as boolean expressions over the input parameter names, e.g. `"bottom_linewidth <= bottom_winding_diameter / 3"`. `OnnxExporter` stores them in the model's `input_constraints` metadata, so COBRA can refuse a query for a geometry that cannot be built instead of returning a prediction the model was never trained for. The grammar is a small subset of Python (arithmetic, comparisons, `and`/`or`/`not`, `a if c else b`, and `abs min max sqrt sin cos tan radians ceil floor round`, plus `pi` and `sqrt2`), documented in `orca.geometry.constraints`; anything else is rejected at export. Derive the strings from the same numbers as `is_feasible()` and add a test that they agree on random draws (see `tests/test_constraints.py` for the presets' version).
- `is_feasible(params) -> bool` — Whether a parameter combination describes a layout that can be drawn (default: always `True`). `GDSGenerator` calls it for every draw of the iterator; rejected draws are counted and, with the `"sobol"`, `"lhs"` and `"random"` strategies, replaced by further draws, so the requested number of samples is met with buildable layouts only. Put cheap, closed-form constraints between parameters here — a winding that must fit its diameter, a feed gap that must fit the octagon's side. The presets derive it from the same check their cell code runs, so the two cannot disagree.
- `simulation_ports(params) -> list[dict]` — The gds2palace ports of one sample, as entries of the simconfig's `ports` list (default: the simconfig's ports unchanged). Which metal a port has to reach is a property of the layout, so it may depend on the parameters: `InductorOcta` feeds a single turn on TopMetal2 and more turns on TopMetal1, so it returns ports 1/2 with `"to_layername": "TopMetal2"` for `turns == 1`. Change port fields only; the simulation settings stay those of the simconfig, so every sample of one model is meshed and solved alike. Keep every port, with its number and in its order — the Touchstone files and the model's outputs depend on them — which `ports_for(params)`, the method the stages call, checks. `DRCChecker` checks each layout against its own ports and `GDSConverter` hands them to gds2palace.

!!! warning "Reject, never clamp"

Expand Down Expand Up @@ -114,7 +116,7 @@ class TransformerOcta(BaseGeometry):
"""

name: str = "tf_octa_c_ports"
stackup_xml: str = StackupXML.SG13G2_FEM_200um # from orca.geometry.presets
stackup_xml: str = StackupXML.SG13G2_FEM_200um_passi3D # from orca.geometry.presets
simconfig_filename: str = os.path.join(os.path.dirname(__file__), "tf_octa_c_ports.simcfg")
input_parameter_iterator: InputParameterIterator = field(default_factory=_input_parameters)

Expand All @@ -132,6 +134,16 @@ class TransformerOcta(BaseGeometry):
output_normalizer=StandardNormalizer(),
)

# Close to zero for weakly coupled windings, where a relative error says nothing
absolute_error_parameters: ClassVar[frozenset[str]] = frozenset({"k"})

def electrical_parameters(self, ntwk: "rf.Network") -> dict[str, "np.ndarray"]:
from orca.utils.postprocessing import transformer_parameters

# Zero-based ports: 0 op, 1 on (top winding), 2 ip, 3 in (bottom winding),
# 4 and 5 the center taps, AC-grounded as in differential use
return transformer_parameters(ntwk, primary=(0, 1), secondary=(2, 3), shorted=(4, 5))

@staticmethod
def create_gds_file(name: str, output_path: str, params: dict[str, Any]) -> str:
#
Expand Down Expand Up @@ -333,3 +345,5 @@ Example:
]
}
```

The `ports` list is the default for every sample. When the metal a port lands on changes with the parameters, override `simulation_ports(params)` in the geometry class rather than keeping a second simcfg: one file of simulation settings cannot drift apart between samples of the same model. Each port's marker on its `source_layernum` must touch the metals it connects; `DRCChecker` drops layouts where it does not, as such a port would simulate as an open circuit.
2 changes: 1 addition & 1 deletion docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ flowchart LR
| Stage | Purpose |
|---|---|
| `GDSGenerator` | Samples geometry parameters and writes GDS layout files |
| `DRCChecker` | Snaps layouts to the manufacturing grid and drops those violating the SG13G2 design rules |
| `DRCChecker` | Snaps layouts to the manufacturing grid and drops those violating the SG13G2 design rules or with port markers off their metal |
| `GDSConverter` | Converts GDS files to Palace-compatible mesh inputs |
| `PalaceSimulator` | Runs full-wave EM simulations and stores Touchstone results |
| `ModelTrainer` | Trains a PyTorch neural network on the simulation dataset |
Expand Down
Loading
Loading