Skip to content

IFTE-EDA/load-pull-optimization

Repository files navigation

Load-Pull Sweep Script with Xyce (Harmonic Balance)

test-amplifier-new_load_pull_smith

This script is used to perform a load-pull analysis for a power amplifier (or any DUT). A load variation is carried out in the reflection coefficient space (Γ-plane). For each Γ point, an equivalent output load (R+L or R+C) is generated automatically, followed by a harmonic-balance simulation using Xyce.

From the harmonic-balance results generated by Xyce (hb_fd.HB.FD.csv), the following quantities are extracted: Output power Pout (in dBm) at the fundamental frequency Magnitudes of the output currents at the fundamental and harmonics |I(k·f0)|

As a result, a CSV file and a Smith chart visualization are generated.

Functional Overview

  • Load-pull sweep in the Γ-plane
  • Automatic distinction between inductive and capacitive loads:
    • X > 0 → R + L
    • X < 0 → R + C
  • Harmonic-balance simulation with Xyce
  • Automatic skipping of DC-failed points
  • Output:
    • CSV file containing valid load-pull results
    • Smith chart with color-coded output power

Dependencies

Software

  • Xyce (must be callable from the command line as “Xyce”)
  • Python version 3.10 or newer

Python Libraries

  • numpy
  • pandas
  • click
  • matplotlib
  • pysmithchart
  • dataclasses

When using “uv run”, dependencies can be installed automatically.

Requirements for the Netlist Template (IMPORTANT)

The script uses exactly ONE netlist template. In the template, the output load must be defined using a placeholder that is automatically replaced during the sweep.

Load-Pull Load Anchor Replacement

Instead of using a textual placeholder, the load-pull system identifies a load anchor element directly in the netlist.

The user must provide the name of a resistor element that defines where the load is connected, for example:

RLoad  _net3  out  50

This resistor acts as a structural anchor. At runtime, the script locates this element by name, determines the two connected nodes, and replaces the single resistor with a parameterized load-pull network. The anchor element is specified via the command line:

--load-name RLoad

The anchor resistor is replaced by the following unified load-pull topology:

.param RLP=50
.param LLP=1e-12
.param CLP=1e-12
.param USEL=1
.param USEC=0
.param GAMMAR=0
.param GAMMAI=0
.param ZR=0
.param ZI=0
LBf0  _net3 nLP1 0.663n
CLP0  nLP1  0    0.530p
LLP2  nLP1  nLP  0.663n
R_Loadpull nLP nZ {RLP}
RselL      nZ nL {USEL*1e-6 + (1-USEL)*1e12}
L_Loadpull nL 0 {LLP}

RselC      nZ nC {USEC*1e-6 + (1-USEC)*1e12}
C_Loadpull nC 0 {CLP}
Rbleed_nZ nC 0 100meg
Cb_harm _net3 nHP1 0.265p
LHP     nHP1  0    1.326n
CHP2    nHP1  nHP  0.265p

Operation Principle

  • RLoad represents the real part of the load impedance.
  • <node_in> and <node_out> are automatically extracted from the original anchor element.
  • The internal node nZ is an auxiliary node used to form a series connection and to ensure a valid DC path.
  • Two large bleed resistor (e.g., 100 MΩ) provides a DC leakage path, improving DC operating-point convergence.

Two parallel reactive branches are present:

  • Inductive branch (RselL + L_Loadpull)
  • Inductive branch (RselL + L_Loadpull)

The active branch is selected via the parameters USEL and USEC:

  • Inductive load (X > 0):

    • USEL = 1, USEC = 0
    • The inductive branch is enabled (RselL ≈ 1e-6 Ω)
    • The capacitive branch is effectively disconnected (RselC ≈ 1e12 Ω)
  • Capacitive load (X < 0):

    • USEL = 0, USEC = 1
    • The capacitive branch is enabled (RselC ≈ 1e-6 Ω)
    • The inductive branch is effectively disconnected (RselL ≈ 1e12 Ω)

This approach avoids maintaining separate netlists for inductive and capacitive loads and enables efficient parameter sweeping using a single unified load-pull topology.

STEP Sweep is Auto-Generated

  • The user only provides the template netlist (with the anchor resistor).
  • The Python script generates a new “stepped netlist” automatically:
    • It replaces the anchor resistor by the parameterized load-pull topology.
    • It inserts the required .param definitions (RLP/LLP/CLP/USEL/USEC, plus optional debug parameters like GAMMAR/GAMMAI/ZR/ZI).
    • It generates a Γ grid in Python and converts Γ → Z (50Ω reference).
    • It writes all sweep points into a Xyce .DATA table.
    • It adds: .STEP data=<table_name> .DATA <table_name> … (all Γ rows)
    • It calls Xyce once on the generated netlist. Typical stepped table columns include:
  • GAMMAR, GAMMAI (Γ real/imag)
  • ZR, ZI (Z real/imag, for logging/debug)
  • RLP, LLP, CLP, USEL, USEC (load implementation parameters)

Fundamental vs. Harmonics Separation (LPF/HPF Diplexer)

ADS load-pull can freely control the termination at:

  • Fundamental (f0): Γ is swept (load varies)
  • Harmonics (k·f0, k≥2): often set to Γ=0 (i.e., 50Ω) to emulate matched harmonic terminations Xyce does not provide an “ideal port” that independently enforces Γ(f0) and Γ(2f0/3f0/…) the same way ADS can. To approximate the ADS setup, this project inserts a diplexer (low-pass + high-pass) at the DUT output node:
  • Low-pass path (LPF):
    • Designed such that the fundamental f0 mainly flows into the load-pull impedance Z (Γ swept).
  • High-pass path (HPF):
    • Designed such that higher harmonics mainly flow into a fixed 50Ω termination (Γ=0). In other words:
  • Fundamental termination ≈ swept Z(Γ)
  • Harmonic termination ≈ 50Ω (matched) Notes:
  • The diplexer is made of L/C elements, so it is not perfectly ideal.
  • The cutoff frequency is chosen between f0 and 2f0 (e.g., around 12 GHz for f0=8 GHz) to route 8 GHz to LPF and 16 GHz+ to HPF.

Command-Line Usage

Minimal Invocation (Default Parameters)

uv run load-pull-optimization_mpi.py test-amplifier-new.spice --load-name Rload

By default, output files are stored in the same directory as the netlist.

Display Help

uv run load-pull-optimization_mpi --help

Command-Line Options

netlist (required argument)

Path to the netlist template:

uv run load-pull-optimization_mpi.py test-amplifier-new.spice --load-name Rload

--load-name (required argument)

Specifies the name of the resistor element in the netlist that acts as the load anchor for the load-pull network:

uv run load-pull-optimization_mpi.py test-amplifier-new.spice --load-name Rload

--r-max

Maximum radius |Γ| for the load-pull sweep:

uv run load-pull-optimization_mpi.py test-amplifier-new.spice --load-name Rload --r-max 0.95

--n-grid

Number of grid points N in [-r_max, r_max]. The effective number of simulated points is approximately:

(pi / 4) *

Example:

uv run load-pull-optimization_mpi.py test-amplifier-new.spice --load-name Rload --n-grid 31

--freq

Fundamental frequency in Hz for which Pout and harmonics are evaluated:

uv run load-pull-optimization_mpi.py test-amplifier-new.spice --load-name Rload --freq 8e9

--output_dir

Output directory for CSV and PNG files. If not specified: output is written to the netlist directory If specified: directory is created automatically if required Example:

uv run load-pull-optimization_mpi.py test-amplifier-new.spice --load-name Rload --output_dir ./results

--mpi

Number of MPI processes used to run Xyce. Controls parallel execution of the sweep. This accelerates large Γ sweeps significantly. Example:

uv uv run load-pull-optimization_mpi.py test-amplifier-new.spice --load-name Rload --mpi 8

--mpiexec

MPI launcher command. If not specified:

  • Windows → defaults to mpiexec
  • Linux/macOS → defaults to mpirun You can use this option if:
  • MPI launcher is not in PATH
  • You want to specify a full path to mpiexec/mpirun
  • You use a non-default MPI distribution Example (Windows full path):
uv run load-pull-optimization_mpi.py test-amplifier-new.spice --load-name Rload --mpi 8 --mpiexec "C:\Program Files\Microsoft MPI\Bin\mpiexec.exe"

Output Files

CSV File

<netlist_name>_load_pull_data_xyce.csv

Contains the following columns:

  • Gamma_real, Gamma_imag
  • Z_real, Z_imag
  • R, L, C
  • p_out_dbm
  • I_harm1_mag, I_harm2_mag, I_harm3_mag, ... Points with DC failures are not included in this file

Smith-Diagramm

<netlist_name>_load_pull_smith.png

Each point corresponds to a Γ value Color scale represents output power Pout (dBm) DC-failed points are not displayed

Handling of DC Failures

If Xyce terminates with an error code (returncode ≠ 0) (e.g., “DC step #1 failed”):

  • The point is considered invalid
  • p_out_dbm is set to NaN
  • The point is not plotted
  • The point does not appear in the final CSV This behavior is typical and appropriate for load-pull analyses.

Calculation Details

Output power is calculated as:

P = Re{ V · I* }

Harmonic currents |I(k·f0)| are magnitudes of the complex HB current phasors. The reported currents are RMS values.

Example of a Complete Invocation

uv load-pull-optimization_mpi.py test-amplifier-new.spice --loda-name Rload --r-max 0.9 --n-grid 25 --freq 8e9 --z0 50 --output_dir ./lp_result --mpi 8 --mpiexec "C:\Program Files\Microsoft MPI\Bin\mpiexec.exe"

About

Perform load pull optimization using Xyce

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages