Skip to content
Open
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
2 changes: 2 additions & 0 deletions example_cycles/simple_turbojet.py
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,8 @@ def viewer(prob, pt, file=sys.stdout):
shaft_full_names = [f'{pt}.{s}' for s in shaft_names]
pyc.print_shaft(prob, shaft_full_names, file=file)

pyc.print_balances(prob, pt, file=file)

def map_plots(prob, pt):
comp_names = ['comp']
comp_full_names = [f'{pt}.{c}' for c in comp_names]
Expand Down
6 changes: 3 additions & 3 deletions pycycle/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,9 @@

from pycycle.connect_flow import connect_flow

from pycycle.viewers import print_bleed, print_burner, print_compressor, print_flow_station, \
print_mixer, print_nozzle, print_shaft, print_turbine, \
plot_compressor_maps, plot_turbine_maps
from pycycle.viewers import print_balances, print_bleed, print_burner, print_compressor, \
print_flow_station, print_mixer, print_nozzle, print_shaft, \
print_turbine, plot_compressor_maps, plot_turbine_maps


from pycycle.mp_cycle import MPCycle, Cycle
70 changes: 70 additions & 0 deletions pycycle/viewers.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

import numpy as np

import openmdao.api as om

# protection incase env doesn't have matplotlib installed, since its not strictly required
try:
import matplotlib
Expand Down Expand Up @@ -308,6 +310,74 @@ def print_mixer(prob, element_names, file=sys.stdout):
file=file, flush=True)


def print_balances(prob, pt, file=sys.stdout):
"""
Print all balance components and their state variables for a cycle point.

Parameters
----------
prob : om.Problem
OpenMDAO problem containing the pyCycle model.
pt : str
Name of the cycle point to inspect.
file : file-like
Output file stream. Default is sys.stdout.
"""
root = prob.model._get_subsystem(pt)
if root is None:
print(f"Cycle point '{pt}' not found.", file=file, flush=True)
return

# Find all BalanceComp instances using OpenMDAO's system_iter with type filter
balance_comps = list(root.system_iter(include_self=True, recurse=True, typ=om.BalanceComp))

if not balance_comps:
print("No balance components found.", file=file, flush=True)
return

len_header = 120
print("-" * len_header, file=file, flush=True)
print(" BALANCE COMPONENTS", file=file, flush=True)
print("-" * len_header, file=file, flush=True)

for bal_comp in balance_comps:
print(f"\n {bal_comp.pathname}", file=file, flush=True)
print(" " + "-" * 95, file=file, flush=True)

# Access balance metadata from _state_vars
if hasattr(bal_comp, '_state_vars') and bal_comp._state_vars:
line_tmpl = ' {:<15} | {:>10} | {:>10} | {:>16} | {:>16} | {:>14} | {:>14}'
print(line_tmpl.format('Name', 'Units', 'Eq Units', 'LHS', 'RHS', 'Value', 'Residual'),
file=file, flush=True)
print(" " + "-" * 91, file=file, flush=True)

for var_name, var_info in bal_comp._state_vars.items():
units = var_info.get('units') or 'None'
eq_units = var_info.get('eq_units') or 'None'
lhs_name = var_info.get('lhs_name', f'lhs:{var_name}')
rhs_name = var_info.get('rhs_name', f'rhs:{var_name}')

# Get current value
try:
val = prob.get_val(f'{bal_comp.pathname}.{var_name}')[0]
val_str = f'{val:.6g}'
except Exception:
val_str = 'N/A'

# Get residual value
try:
resid = prob.model._residuals[f'{bal_comp.pathname}.{var_name}'][0]
resid_str = f'{resid:.6g}'
except Exception:
resid_str = 'N/A'

print(line_tmpl.format(var_name, str(units), str(eq_units),
lhs_name, rhs_name, val_str, resid_str),
file=file, flush=True)

print("-" * len_header, file=file, flush=True)


def plot_compressor_maps(prob, element_names, eff_vals=np.array([0,0.5,0.55,0.6,0.65,0.7,0.75,0.8,0.85,0.9,0.95,1.0]),alphas=[0]):

for e_name in element_names:
Expand Down
Loading