Source code for psc_sim.ltspice_netlist

"""LTspice .net deck generation (HTML-compatible topology)."""

from __future__ import annotations

from pathlib import Path
from typing import Literal

import numpy as np

from psc_sim.parameters import CellParameters
from psc_sim.simulation.defaults import DEFAULT_IV_SWEEP, DEFAULT_TRAN_SPEC
from psc_sim.simulation.eis_grid import default_eis_freqs
from psc_sim.simulation.types import SweepSpec, TranSpec

SimKind = Literal["dc", "ac", "tran"]


def _ac_list_command(freqs: np.ndarray) -> str:
    parts = " ".join(f"{float(f):.6g}" for f in np.asarray(freqs, dtype=float))
    return f".ac list {parts}"


def _format_lt_time(seconds: float) -> str:
    return f"{seconds * 1e3:g}m"


def _pulse_string(tran: TranSpec) -> str:
    return (
        f"PULSE({tran.pulse_v_low:g} {tran.pulse_v_high:g} "
        f"{_format_lt_time(tran.pulse_delay_s)} "
        f"{_format_lt_time(tran.pulse_rise_s)} "
        f"{_format_lt_time(tran.pulse_fall_s)} "
        f"{_format_lt_time(tran.pulse_on_s)} "
        f"{_format_lt_time(tran.pulse_period_s)})"
    )


[docs] def build_netlist( p: CellParameters, sim: SimKind = "dc", spec: SweepSpec | None = None, ac_freqs: np.ndarray | None = None, tran_spec: TranSpec | None = None, ) -> str: """Return a .net deck matching `solar_cell_sim_app.html` `renderSpice` topology.""" if sim == "dc": s = spec or DEFAULT_IV_SWEEP cmd = f".dc Vbias {s.v_min:g} {s.v_max:g} {s.step:g}" vac = "" vtran = "" elif sim == "ac": freqs = ac_freqs if ac_freqs is not None else default_eis_freqs() cmd = _ac_list_command(freqs) vac = " AC 1" vtran = "" else: tran = tran_spec or DEFAULT_TRAN_SPEC cmd = f".tran {_format_lt_time(tran.t_step_s)} {_format_lt_time(tran.t_stop_s)}" vac = "" vtran = f" {_pulse_string(tran)}" return f"""* psc-sim auto-generated (aligned with solar_cell_sim_app.html) * Mode: {sim.upper()} | T={p.T:g} K Iph_src net_A 0 DC {p.Iph:.12g} .model DCEL D(Is={p.I0:.12g} N={p.n:g} Rs=0 Cjo={p.Cj:.12g} T_ABS={p.T:g}) D1 net_A net_K DCEL Rs_ext net_K V_out {p.Rs:.12g} Rsh_ext net_A 0 {p.Rsh:.12g} Rion_ext V_out net_ion {p.Rion:.12g} Cion_ext net_ion 0 {p.Cion:.12g} Vbias V_out 0 DC 0{vac}{vtran} {cmd} .probe I(Vbias) V(V_out) .end """
def write_netlist( path: Path | str, p: CellParameters, sim: SimKind = "dc", spec: SweepSpec | None = None, ac_freqs: np.ndarray | None = None, tran_spec: TranSpec | None = None, ) -> Path: path = Path(path) path.write_text( build_netlist(p, sim, spec=spec, ac_freqs=ac_freqs, tran_spec=tran_spec), encoding="utf-8", ) return path