Source code for squadds.simulations.drivenmodal.capacitance
"""Capacitance extraction helpers for frequency-dependent driven-modal data."""
from __future__ import annotations
import numpy as np
import pandas as pd
[docs]
def capacitance_matrix_from_y(freq_hz: float, y_matrix) -> np.ndarray:
"""Compute the capacitance matrix from the imaginary part of the admittance matrix."""
if freq_hz <= 0:
raise ValueError("freq_hz must be positive.")
omega = 2 * np.pi * freq_hz
c_matrix = np.imag(np.asarray(y_matrix, dtype=complex)) / omega
return 0.5 * (c_matrix + c_matrix.T)
[docs]
def maxwell_capacitance_dataframe(
c_matrix,
*,
node_names: list[str],
ground_name: str = "ground",
) -> pd.DataFrame:
"""Expand an active-node capacitance matrix into a full Maxwell matrix with ground."""
active = np.asarray(c_matrix, dtype=float)
if active.shape != (len(node_names), len(node_names)):
raise ValueError("node_names must match the capacitance matrix dimensions.")
size = active.shape[0]
maxwell = np.zeros((size + 1, size + 1), dtype=float)
maxwell[:size, :size] = active
row_sums = active.sum(axis=1)
maxwell[:size, size] = -row_sums
maxwell[size, :size] = -row_sums
maxwell[size, size] = row_sums.sum()
labels = [*node_names, ground_name]
return pd.DataFrame(maxwell, index=labels, columns=labels)
[docs]
def capacitance_dataframe_from_y_sweep(freqs_hz, y_matrices, node_names: list[str]) -> pd.DataFrame:
"""Flatten a Y-parameter sweep into a dataframe of capacitance entries by node pair."""
freqs = np.asarray(freqs_hz, dtype=float)
matrices = np.asarray(y_matrices, dtype=complex)
if matrices.shape[0] != len(freqs):
raise ValueError("y_matrices must have the same leading dimension as freqs_hz.")
if matrices.shape[1] != len(node_names) or matrices.shape[2] != len(node_names):
raise ValueError("node_names must match the Y-matrix dimensions.")
rows = []
for freq_hz, y_matrix in zip(freqs, matrices, strict=True):
c_matrix = capacitance_matrix_from_y(freq_hz, y_matrix)
row = {"frequency_hz": freq_hz}
for row_name, row_values in zip(node_names, c_matrix, strict=True):
for column_name, value in zip(node_names, row_values, strict=True):
row[f"{row_name}__{column_name}_F"] = float(value)
rows.append(row)
return pd.DataFrame(rows)