VTB Utilities
This page lists utilities provided within the VTB repository.
VTBPlot
It is highly recommended that contributions to the VTB provide the corresponding plot scripts where possible. For line plots, it is recommended to use the VTB's python plot class VTBPlot, which enables a consistent style for VTB plots.
VTBPlot is a thin wrapper around matplotlib. It creates a single-axes figure with a VTB style, and saves the figure. It is located in python/virtual_test_bed/plotting/VTBPlot.py.
Making the class importable
A plot script that sits next to a model's input files needs to be able to import VTBPlot. While the repository's python directory could be added to the PYTHONPATH environment variable, it is preferred to have it work without modifying environment variables. The following code snippet can be used at the top of a plot script to add the python directory to the system path:
# Add VTB python directory to path
def find_vtb_python_dir():
this_dir = Path(__file__).resolve().parent
for folder in [this_dir, *this_dir.parents]: # this directory, then each one above it
if (folder / "python" / "virtual_test_bed").is_dir():
return folder / "python"
raise RuntimeError("Could not find python/virtual_test_bed above " + str(this_dir))
sys.path.append(str(find_vtb_python_dir()))
(microreactors/gcmr/balance_of_plant/plot.py)Basic usage
Create a VTBPlot with the axis labels, add one or more lines, and call finish() with the name of the image file to write:
from virtual_test_bed.plotting import VTBPlot
# (load data from file into time, T_inlet, and T_outlet)
plot = VTBPlot("Time [h]", "Temperature [K]")
plot.plot(time, T_inlet, label="Core outlet")
plot.plot(time, T_outlet, label="Core outlet")
plot.legend()
plot.finish("temperature.png")
Lines that do not specify a
colortake the next color in the VTB cycle, in order.plot,semilogy,errorbar,axvline,axhlineandlegendaccept the same arguments as the corresponding matplotlib functions.plot.set_xlim(xmin, xmax)andplot.set_ylim(ymin, ymax)set the axis limits; they take effect whenfinish()is called.plot.axandplot.figare the underlying matplotlib axes and figure, for anything not covered above.Optional arguments to
VTBPlotincludetitle,grid('y','x','both'orNone),figsizeandusetex(LaTeX text, which requires a LaTeX installation).finish()also closes the figure, so many plots can be made in one script.
Full example
The balance-of-plant plots in Balance of Plant system are made with VTBPlot by microreactors/gcmr/balance_of_plant/plot.py:
#!/usr/bin/env python
"""Plot the balance-of-plant results shown on doc/content/microreactors/gcmr/BOP_results.md.
Usage (from this directory, after running the inputs):
python plot.py startup
python plot.py load_follow
"""
import argparse
import sys
from pathlib import Path
import pandas as pd
# Add VTB python directory to path
def find_vtb_python_dir():
this_dir = Path(__file__).resolve().parent
for folder in [this_dir, *this_dir.parents]: # this directory, then each one above it
if (folder / "python" / "virtual_test_bed").is_dir():
return folder / "python"
raise RuntimeError("Could not find python/virtual_test_bed above " + str(this_dir))
sys.path.append(str(find_vtb_python_dir()))
from virtual_test_bed.plotting import VTBPlot
def makePlots(test):
data_filename = 'htgr_' + test + '_transient.csv'
data = pd.read_csv(data_filename)
plotTorques(data, test)
plotOmega(data, test)
plotPrimaryMassFlowRate(data, test)
plotSecondaryMassFlowRate(data, test)
plotPrimaryPressure(data, test)
plotSecondaryPressure(data, test)
plotTemperature(data, test)
plotPower(data, test)
def plotTorques(data, test):
t_hours = data["time"] / 3600.0
plot = VTBPlot("Time [h]", "Torque [N·m]")
plot.plot(t_hours, data["sec_motor_torque"], label="Motor")
plot.plot(t_hours, data["turbine_torque"], label="Turbine")
plot.legend()
plot.finish(test + "_torques.png")
def plotOmega(data, test):
t_hours = data["time"] / 3600.0
plot = VTBPlot("Time [h]", "Rotation speed [rad/s]")
plot.plot(t_hours, data["shaft_speed"])
plot.finish(test + "_omega.png")
def plotPrimaryMassFlowRate(data, test):
t_hours = data["time"] / 3600.0
plot = VTBPlot("Time [h]", "Mass flow rate [kg/s]")
plot.plot(t_hours, data["core_m_dot_in"])
plot.finish(test + "_primary_m_dot.png")
def plotSecondaryMassFlowRate(data, test):
t_hours = data["time"] / 3600.0
plot = VTBPlot("Time [h]", "Mass flow rate [kg/s]")
plot.plot(t_hours, data["hx_sec_m_dot_in"])
plot.finish(test + "_secondary_m_dot.png")
def plotPrimaryPressure(data, test):
t_hours = data["time"] / 3600.0
plot = VTBPlot("Time [h]", "Pressure [MPa]")
plot.plot(t_hours, data["core_p_in"] * 1e-6, label="Core inlet")
plot.plot(t_hours, data["hx_pri_p_in"] * 1e-6, label="Primary side, heat exchanger inlet")
plot.plot(t_hours, data["pump_p_in"] * 1e-6, label="Pump inlet")
plot.legend()
plot.finish(test + "_primary_P.png")
def plotSecondaryPressure(data, test):
t_hours = data["time"] / 3600.0
plot = VTBPlot("Time [h]", "Pressure [MPa]")
plot.plot(t_hours, data["comp_p_in"] * 1e-6, label="Compressor inlet")
plot.plot(t_hours, data["comp_p_out"] * 1e-6, label="Compressor outlet")
plot.plot(t_hours, data["hx_sec_p_in"] * 1e-6, label="Secondary side, heat exchanger inlet")
plot.plot(t_hours, data["hx_sec_p_out"] * 1e-6, label="Secondary side, heat exchanger outlet")
plot.plot(t_hours, data["turb_p_in"] * 1e-6, label="Turbine inlet")
plot.plot(t_hours, data["turb_p_out"] * 1e-6, label="Turbine outlet")
plot.legend()
plot.finish(test + "_secondary_P.png")
def plotTemperature(data, test):
t_hours = data["time"] / 3600.0
plot = VTBPlot("Time [h]", "Temperature [K]")
plot.plot(t_hours, data["core_T_wall_in"], label="Wall, core inlet")
plot.plot(t_hours, data["core_T_wall_out"], label="Wall, core outlet")
plot.plot(t_hours, data["core_T_in"], label="Coolant, core inlet")
plot.plot(t_hours, data["core_T_out"], label="Coolant, core outlet")
plot.plot(t_hours, data["hx_sec_T_in"], label="Secondary side, heat exchanger inlet")
plot.plot(t_hours, data["hx_sec_T_out"], label="Secondary side, heat exchanger outlet")
plot.legend()
plot.finish(test + "_T.png")
def plotPower(data, test):
t_hours = data["time"] / 3600.0
plot = VTBPlot("Time [h]", "Power [MW]")
plot.plot(t_hours, data["core_power_difference"] * 1e-6, label="Power transferred in the core")
plot.plot(t_hours, -data["hx_pri_power_difference"] * 1e-6, label="Power transferred in the heat exchanger")
plot.plot(t_hours, -data["generator_power"] * 1e-6, label="Power transferred in the generator")
plot.legend()
plot.finish(test + "_power.png")
def main():
ap = argparse.ArgumentParser(description=__doc__.splitlines()[0])
ap.add_argument("test", help="Test case", choices=['startup', 'load_follow'])
args = ap.parse_args()
makePlots(args.test)
if __name__ == "__main__":
main()
(microreactors/gcmr/balance_of_plant/plot.py)Running python plot.py startup or python plot.py load_follow in that directory, after running the corresponding input file, writes one image per plot.