Coverage for klayout_pex/pex25d/exporters.py: 69%
35 statements
« prev ^ index » next coverage.py v7.16.1, created at 2026-09-17 19:08 +0000
« prev ^ index » next coverage.py v7.16.1, created at 2026-09-17 19:08 +0000
1#
2# --------------------------------------------------------------------------------
3# SPDX-FileCopyrightText: 2024-2026 Martin Jan Köhler and Harald Pretl
4# Johannes Kepler University, Institute for Integrated Circuits.
5#
6# This file is part of KPEX
7# (see https://github.com/iic-jku/klayout-pex).
8#
9# This program is free software: you can redistribute it and/or modify
10# it under the terms of the GNU General Public License as published by
11# the Free Software Foundation, either version 3 of the License, or
12# (at your option) any later version.
13#
14# This program is distributed in the hope that it will be useful,
15# but WITHOUT ANY WARRANTY; without even the implied warranty of
16# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17# GNU General Public License for more details.
18#
19# You should have received a copy of the GNU General Public License
20# along with this program. If not, see <http://www.gnu.org/licenses/>.
21# SPDX-License-Identifier: GPL-3.0-or-later
22# --------------------------------------------------------------------------------
23#
25"""
26Generation of solver-native input files from a ``PEX25DScene``.
28The specification calls these solver *adapters*; this module is named after the
29operation the CLI exposes, ``pex25d export``.
31Exporting is the one part of this package that is not pure format work: turning
32a scene into a solver's input needs polygon booleans and meshing, so a backend
33depends on a geometry library. Backends are therefore imported on use, and a
34missing dependency is reported rather than surfacing as an ImportError from an
35unexpected place. Reading, validating, converting and resolving stay
36dependency-free.
37"""
39from __future__ import annotations
41from dataclasses import dataclass
42from enum import StrEnum
43from typing import *
46class SolverTarget(StrEnum):
47 """Engines a PEX25D scene can be written out for."""
49 FASTERCAP = 'fastercap'
50 FASTCAP2 = 'fastcap2'
52 DEFAULT = 'fastercap'
55class ExportError(RuntimeError):
56 """The scene could not be written out for the requested target."""
59class ExporterUnavailable(ExportError):
60 """The backend for a target is not importable in this installation."""
63@dataclass
64class ExporterOptions:
65 """Knobs the CLI exposes for solver input generation."""
67 delaunay_amax: float = 0.0
68 """Maximum triangle area; 0 leaves it to the mesher."""
70 delaunay_b: float = 1.0
71 """Minimum mesh angle as b = 2·sin(angle); 1.0 is 30 degrees."""
73 field_margin_um: float = 8.0
74 """
75 How far the laterally unbounded materials — the simple bands, the films that
76 cover the field, the background, the ground plane — are drawn beyond the
77 geometry. Ignored when the scene carries a DOMAIN_BOX, which says it
78 outright.
79 """
81 write_stl: bool = False
82 """Also dump the generated solids as STL, for looking at."""
84 geometry_check: bool = False
85 """Run the generator's own geometry validation before writing."""
88def export(scene: Any,
89 target: SolverTarget,
90 output_dir_path: str,
91 prefix: str = '',
92 options: Optional[ExporterOptions] = None) -> List[str]:
93 """
94 Export ``scene`` as native input for ``target`` into ``output_dir_path``.
96 Does not run the engine.
98 :return: the paths written, most significant first — for FasterCap the
99 ``.lst`` file, followed by the per-surface files it references.
100 """
101 match target:
102 case SolverTarget.FASTERCAP | SolverTarget.FASTCAP2:
103 backend = load_fastercap_backend()
104 case _:
105 raise ExportError(f"No exporter for '{target.value}'")
107 return backend(scene=scene, target=target, output_dir_path=output_dir_path,
108 prefix=prefix, options=options or ExporterOptions())
111def load_fastercap_backend() -> Callable[..., List[str]]:
112 """
113 The FasterCap / FastCap2 backend, which needs KLayout.
115 Both engines read the same list-file format, so one backend serves them.
116 """
117 try:
118 from ..fastercap.pex25d_exporter import export_fastercap
119 except ImportError as e:
120 raise ExporterUnavailable(
121 f"The FasterCap exporter needs KLayout, which is not importable here. "
122 f"Everything else the pex25d tool does works without it.\n"
123 f"Original error: {e}"
124 ) from e
125 return export_fastercap