Receiver module: Defining the receiver geometry

Receiver system

As described in the overview, the user must provide the geometric definition of the tubular receiver and the mechanical and thermal boundary conditions as part of the required package input. The srlife.receiver module defines data structures for providing this information and some simple methods for manipulating the data.

The python class srlife.receiver.Receiver provides the top level interface and uses a hierarchy of objects to describe the receiver geometry and boundary conditions. The figure below describes the structure.

Receiver data structure

The overall data structure is hierarchical, descending from the single srlife.receiver.Receiver object describing the entire receiver. The receiver has one or more srlife.receiver.Panel objects each of which have one ore more srlife.receiver.Tube objects. Structurally, each tube in a panel is connected through its top-surface displacement through a spring. Similarly, each panel is connected to the other panels through a spring. The spring stiffness defines the type of connection, options are:

  1. A string “disconnect” meaning the spring has zero stiffness and the member floats freely, not connected to the result of the objects of its type.

  2. A string “rigid” which means the object is rigidly connected to the others of its type with an infinitely-rigid spring.

  3. A float giving the discrete spring stiffness.

The srlife.receiver.Receiver structure itself stores additional metadata:

  1. The cycle period. Typically this will be 24 hours, but could be a reduced representation, for example cutting out a period of the hold in the cold nighttime condition.

  2. The number of days (cycle repetitions) actually represented in the structural and thermal boundary conditions. This could, and almost always will be, not the full receiver life in days as the prescribed loads could represent a larger number of actual repetitions in service.

The Tube object holds basic geometric information describing a cylindrical tube, the tube discretization which is a fixed grid in cylindrical coordinates given by a fixed number of radial, circumferential, and axial subdivisions, the initial tube temperature, the discrete times at which the object stores boundary condition information and results, zero or more nodal results fields, zero or more quadrature result fields, an optional inner pressure boundary condition, an optional inner diameter thermal boundary condition, and an optional outer diameter thermal boundary condition. In addition, the tube carries a flag indicating whether the tube should be treated with a full 3D analysis or a reduced 2D or 1D analysis. For the reduced analysis the tube retains the height of the slice (2D and 1D) and the angle of the slice (1D), with respect to the full 3D cylindrical coordinate system.

The tube result and boundary condition times are a 1D array of time values, starting at zero. This array has length \(n_{time}\) and must be consistent for all the nodal results, quadrature results, pressure boundary conditions, and thermal boundary conditions.

Nodal results are stored on a fixed grid defined by an array of size

\[n_{time} \times n_{r} \times n_{\theta} \times n_{z}\]

where \(n_{r}\) is the number of radial grid points, \(n_{\theta}\) is the number of circumferential grid points, and \(n_z\) is the number of axial grid points. A 2D representation leaves off the last axis and a 1D representation leaves off the last two axes.

The inner pressure boundary condition srlife.receiver.PressureBC holds a 1D array of pressures defining the pressure at discrete times. The size of this 1D array must be \(n_{time}\) and match the tube object.

The user has two options for outer diameter thermal boundary conditions:

  1. Fixed flux boundary condition srlife.receiver.HeatFluxBC.

  2. Fixed temperature boundary condition srlife.receiver.FixedTempBC.

The data for the flux and temperature boundary conditions is an array of flux or temperature values of size

\[n_{time} \times n_{\theta} \times n_{z}\]

representing a fixed grid of points on either the tube inner or outer diameter. The user must provide the full 3D data.

Inner tube thermal BCs

By default, the inner boundary condition for each tube is a representation of heat transfer between the tubes and the working fluid. Two separate solvers are used to balance heat transfer between the tube and the fluid: a finite difference, 1D/2D/3D transient heat transfer solver for the solid temperatures and a 1D transient thermohydraulic solver for the fluid temperatures. The boundary conditions for the finite difference solver are the outside diameter boundary condition specified by the user for each tube (often the net incident flux) and convective heat transfer between the tube inner diameter and the fluid. The input conditions for the thermohydraulic solver are the flow rate and inlet temperature along each flow path in the receiver, given as a function of time throughout the user-provided load history. Heat then transfers along each flow path, with the fluid absorbing heat from each tube in the path.

These two solvers are coupled along the inner diameter of each tube. srlife solves for overall heat balance using Picard iteration on the heat transfered from the tube into the fluid (equal to the heat transfered out of the fluid and into each tube). This means that the solver starts with a guess at what this convective heat transfer will be, solves for the metal temperatures, calculates the convective heat transfer into the fluid, solves for the fluid temperatures, and iterates to solve again for the tube temperatures. This process repeats until both the fluid and tube temperatures no longer change.

The previous section discusses specifying the tube outer diameter boundary conditions, which, again, are often the next incident flux directed at each tube in the receiver. The model divides up the panels in the receiver into one or more flow paths. Fluid flows into the first panel, through the panel, into the next connected panel, and so on until it reaches the panel outlet. The user specifies which panels in the receiver are connected with a method of the srlife.receiver.Receiver class

receiver.add_flowpath(panels, times, flow_rate, inlet_temp)

where the method takes as input a list of panels in the flow path, in the order the fluid flow through time, a numpy array of times throughout the loading history for which the flow_rate and inlet_temp arrays provide the corresponding inlet mass flow rates and inlet temperatures.

Each panel in the receiver must belong to one and only one flow path.

A model of a tubular panel receiver can explicitly represent fewer tubes than the actual number in each panel to save computational cost. Because the structural damage and reliability models base the overall performance of the receiver on the worst (most damaged/least reliable) tube, these models do not need any special modification to accommodate models that use fewer than the full number of tubes to represent each panel. However, the flow velocity through each tube depends on overall mass flow rate into a panel and the actual number of tubes the flow divides into in that panel. Each srlife.receiver.Tube in the srlife.receiver.Receiver has a multiplier property that the user can set to have the tube represent more than one tube in the actual panel for the thermohydraulic calculation. For example, if there are 100 tubes in the actual panel and the user represents only two tubes per panel in the actual thermal and structural model then this multiplier could be:

for tube in panel.tubes:
   tube.multiplier = 50

Defining the model

The user can provide the required input data in two ways:
  1. The Python objects

  2. An HDF5 file

Both methods provide options for linking into external programs.

Python objects

Receiver geometry

The Receiver object contains panels and the interconnect spring stiffness between the panels.

class srlife.receiver.Receiver(period, days, panel_stiffness)

Basic definition of the tubular receiver geometry.

A receiver is a collection of panels linked together by an elastic spring stiffness. This stiffness can be a real number, “rigid” or “disconnect”

Panels can be labeled by strings. By default the names are sequential numbers.

In addition this object stores some required metadata:
  1. The daily cycle period (which can be less than 24 hours if the analysis neglects some of the night period)

  2. The number of days (see #1) explicitly represented in the analysis results.

Parameters:
  • period (float) – single daily cycle period

  • days (int) – number of daily cycles explicitly represented

  • panel_stiffness (float or string) – panel stiffness (float) or “rigid” or “disconnect”

add_flowpath(panels_in_path, times, mass_rate, inlet_temp, name=None)

Add a flow path to the receiver model

Parameters:
  • panels_in_path (list) – list of panel names in the path

  • times (np.array) – time data

  • mass_rate (np.array) – mass flow rate data

  • inlet_temp (np.array) – inlet temperature data

  • name (Optional[str]) – optional flowpath name

add_panel(panel, name=None)

Add a panel object to the receiver

Parameters:
  • panel (Panel) – panel object

  • name (Optional[str]) – panel name, by default follows fixed scheme

close(other)

Check to see if two objects are nearly equal.

Primarily used for testing

Parameters:

other (Receiver) – the object to compare against

Returns:

True if the receivers are similar.

Return type:

bool

classmethod load(fobj)

Load a Receiver from an HDF5 file

A full description of the HDF format is included in the module documentation

Parameters:

fobj (string) – either a h5py file object or a filename

Returns:

The constructed receiver object.

Return type:

Receiver

property npanels

Number of panels in the receiver

Returns:

Number of panels

Return type:

int

property ntubes

Shortcut for total number of tubes

Returns:

Number of tubes in all panels

Return type:

int

save(fobj)

Save to an HDF5 file

This saves a Receiver object to the HDF5 format.

Parameters:

fobj (str) – either a h5py file object or a filename

set_paging(page)

Tell tubes to store results on or off disk

Parameters:

page (bool) – if true, page results to disk

property tubes

Shortcut iterator over all tubes

Returns:

iterator over panels

write_vtk(basename)

Write out the receiver as individual panels with names basename_panelname

The VTK format is mostly used for additional postprocessing. The VTK format cannot be used for input.

Parameters:

basename (str) – base file name

The Panel object contains tubes and the interconnect spring stiffness between each tube in the panel

class srlife.receiver.Panel(stiffness, ntubes_actual=None)

Basic definition of a panel in a tubular receiver.

A panel is a collection of Tube object linked together by an elastic spring stiffness. This stiffness can be a real number, a string “disconnect” or a string “rigid”

Tubes in the panel can be labeled by strings. By default the names are sequential numbers.

Parameters:

stiffness – manifold spring stiffness

add_tube(tube, name=None)

Add a tube object to the panel

Parameters:
  • tube (Tube) – tube object

  • name (Optional[str]) – Tube name, defaults to fixed scheme.

close(other)

Check to see if two objects are nearly equal.

Primarily used for testing

Parameters:

other (Panel) – the object to compare against

Returns:

true if the panels are sufficiently similar

Return type:

bool

classmethod load(fobj)

Load from an HDF5 file

Parameters:

fobj (h5py.Group) – h5py group containing the panel

property ntubes

Number of tubes in the panel

Returns:

number of tubes in the panel

Return type:

int

property ntubes_actual

Number of actual tubes in the panel

Returns:

number of tubes in the full panel

Return type:

int

save(fobj)

Save to an HDF5 file

Parameters:

fobj (h5py.Group) – h5py group

write_vtk(basename)

Write out the panels as individual tubes with names basename_tubename

Parameters:

basename (string) – base file name

The Tube object contains the majority of the analysis information and results of the analysis. The structure holds the basic tube geometry, the tube discretization, described as intervals in a cylindrical coordinate system, and initial tube temperature, the thermal and mechanical boundary conditions, and result fields stored at discrete times and either at node points or quadrature points.

class srlife.receiver.Tube(outer_radius, thickness, height, nr, nt, nz, T0=0.0, page=False, multiplier=1)

Geometry, boundary conditions, and results for a single tube.

The basic tube geometry is defined by an outer radius, thickness, and height.

Results are given at fixed times and on a regular polar grid defined by a number of r, theta, and z increments. The grid points are then deduced by linear subdivision in r between the outer radius and the outer radius - t, 0 to 2 pi, and 0 to the tube height.

Result fields are general and provided by a list of names. The receiver package uses the metal temperatures, stresses, mechanical strains, and inelastic strains.

Analysis results can be provided over the full 3D grid (default), a single 2D plane (identified by a height), or a single 1D line (identified by a height and a theta position)

Boundary conditions may be provided in two ways, either as fluid conditions or net heat fluxes. These are defined in the HeatFluxBC or ConvectionBC objects below.

Parameters:
  • outer_radius (float) – tube outer radius

  • thickness (float) – tube thickness

  • height (float) – tube height

  • nr (int) – number of radial increments

  • nt (int) – number of circumferential increments

  • nz (int) – number of axial increments

  • T0 (Optional[float]) – initial temperature

  • page (Optional[bool]) – store results on disk if True

  • multiplier (Optional[int]) – number of tubes represented by this actual model, defaults to 1

add_axial_results(name, data)

Add a result distributed over the tube height at nz points

Parameters:
  • name (str) – results name

  • data (np.array) – data to store

add_blank_axial_results(name)

Add a blank axial results field

Parameters:

name (str) – name of field

add_blank_quadrature_results(name, shape)

Add a blank quadrature point result field

Parameters:
  • name (str) – parameter set name

  • shape (tuple) – required shape

add_blank_results(name, shape)

Add a blank node point result field

Parameters:
  • name (str) – parameter set name

  • shape (tuple) – required shape

add_quadrature_results(name, data)

Add a result at the quadrature points

Parameters:
  • name (str) – parameter set name

  • data (np.array) – actual results data

add_results(name, data)

Add a node point result field

Parameters:
  • name (str) – parameter set name

  • data (np.array) – actual results data

close(other)

Check to see if two objects are nearly equal.

Primarily used for testing

Parameters:

other (Tube) – the object to compare against

Returns:

true if the tubes are similar

Return type:

bool

copy_results(other)

Copy the results fields from one tube to another

Parameters:

other – other tube object

property dim

Actual problem discretization

Returns:

tuple giving the fixed grid discretization

Return type:

tuple(int)

element_surface_areas()

Calculate the element surface areas

Returns:

np.array with each element area

element_volumes()

Calculate the element volumes

Returns:

np.array with each element volume

classmethod load(fobj)

Load from an HDF5 file

Parameters:

fobj (h5py.Group) – h5py to load from

make_1D(height, angle)

Abstract the tube as 1D

Reduce to a 1D abstraction along a ray given by the provided height and angle.

Parameters:
  • height (float) – the height of the ray

  • angle (float) – the angle, in radians

make_2D(height)

Abstract the tube as 2D

Reduce to a 2D abstraction by slicing the tube at the indicated height

Parameters:

height (float) – the height at which to slice

property mesh

Calculate the problem mesh (should only be needed for I/O)

Returns:

Results of np.meshgrid over the problem discretization

property multiplier

Number of actual tubes represented by this model

Returns:

tube multiplier

Return type:

int

property ndim

Number of problem dimensions

Returns:

tube dimension

Return type:

int

property ntime

Number of time steps

Returns:

number of time steps

Return type:

int

save(fobj)

Save to an HDF5 file

Parameters:

fobj (h5py.Group) – h5py group to save to

set_bc(bc, loc)

Set the inner or outer heat flux BC

Parameters:
  • bc (ThermalBC) – boundary condition object

  • loc (string) – location – either “inner” or “outer” wall

set_paging(page, i)

Set the value of the page parameter

Parameters:
  • page – if true store results on disk

  • i – tube number to use

set_pressure_bc(bc)

Set the pressure boundary condition

Parameters:

bc (PressureBC) – boundary condition object

set_times(times)

Set the times at which data is provided

All results arrays must provide data at these discrete times.

Parameters:

times (np.array) – time values

surface_elements()

Return an indication of which are surface elements and their normal vectors.

Returns:

logical indexing array, True if on surface np.array of surface normals (zeros for solids)

write_vtk(fname)

Write to a VTK file

The tube VTK files are only used for output and postprocessign

Parameters:

fname (string) – base filename

Boundary conditions

The only mechanical boundary condition the user needs to specify is the Tube internal pressure.

class srlife.receiver.PressureBC(times, data)

Stores information about the tube internal pressure

Simple class to store tube pressure, assumed to be constant in space and just vary with time.

Parameters:
  • times (np.array) – times throughout load cycle

  • data (np.array) – pressure values

close(other)

Test method for comparing BCs

Parameters:

other (PressureBC) – other object

Returns:

true if the objects are sufficiently similar

Return type:

bool

classmethod load(fobj)

Load from an HDF5 file

Parameters:

fobj (h5py.Group) – h5py group to load from

property ntime

Number of time steps

Returns:

number of time steps in the pressure history definition

Return type:

int

pressure(t)

Return the pressure as a function of time

Parameters:

t (float) – time

Returns:

internal pressure at that time

Return type:

float

save(fobj)

Save to an HDF5 file

Parameters:

fobj (h5py.Group) – h5py group to save to

Superclass handing HDF storage dispatch for thermal boundary conditions

class srlife.receiver.ThermalBC

Superclass for thermal boundary conditions.

Currently just here to handle dispatch for HDF files

Thermal boundary conditions options are fixed flux (HeatFluxBC), fixed temperature (FixedTempBC), and convection (ConvectiveBC).

class srlife.receiver.HeatFluxBC(radius, height, nt, nz, times, data)

A net heat flux on the radius of a tube. Positive is heat input, negative is heat output.

These conditions are defined on the surface of a tube at fixed times given by a radius and a height. The radius is not used in defining the BC but is used to ensure the BC is consistent with the Tube object.

The heat flux is given on a regular grid of theta, z points each defined but a number of increments. This grid need not agree with the Tube solid grid.

Parameters:
  • radius (float) – boundary condition application radius

  • height (float) – tube height

  • nt (int) – number of circumferential increments

  • nz (int) – number of axial increments

  • times (np.array) – heat flux times

  • data (np.array) – heat flux data

class srlife.receiver.FixedTempBC(radius, height, nt, nz, times, data)

Fixed temperature BC.

These conditions are defined on the surface of a tube at fixed times given by a radius and a height. The radius is not used in defining the BC but is used to ensure the BC is consistent with the Tube object.

The heat flux is given on a regular grid of theta, z points each defined but a number of increments. This grid need not agree with the Tube solid grid.

Parameters:
  • radius (float) – boundary condition application radius

  • height (float) – tube height

  • nt (int) – number of circumferential increments

  • nz (int) – number of axial increments

  • times (np.array) – fixed temperature times

  • data (np.array) – fixed temperature data

HDF5 file

HDF5 provides a hierarchical data structure aimed at storing and transferring scientific data. srlife uses the format, through the h5py package, to serialize and store the definition of a complete receiver to file. A user could write an HDF5 file with the appropriate format to interface with srlife from an external program.

The interface uses HDF5 attributes, datasets, and groups to store the data. An attributes is metadata, a single string, bool, float, integer, etc. A dataset is a fixed-size array, essentially in the h5py package a numpy array. A group is a container that can hold attributes, datasets, or additional groups.

The format adopted here is then an exact mirror of the type structure defined above. The srlife.receiver.Receiver object’s metadata and data sits at the top of the HDF5 file (i.e. not contained in a group), and stores the srlife.receiver.Panel, srlife.receiver.Tube, srlife.receiver.PressureBC, and srlife.receiver.ThermalBC as groups and subgroups. The HDF5 file maintains the hierarchical structure of the python data structures, so the receiver stores the panels in a group, each panel stores its tubes in a group, and the thermal and pressure BCs are subgroups of the tubes.

The following summarizes the HDF5 format. Example HDF5 files are contained in the srlife/examples directory.

Receiver

This is the top-level of the HDF5 file.

Field

Type

Data type

Explanation

Notes

period

attribute

float

Daily cycle period

days

attribute

int

Number of cycle repetitions

stiffness

attribute

float/string

Panel interconnect stiffness

“disconnect”, “rigid”, or value of stiffness

panels

group

n/a

Each panel is a subgroup of this group

Default naming scheme: 0, 1, 2, …

Panel

Field

Type

Data type

Explanation

Notes

stiffness

attribute

float/string

Panel interconnect stiffness

“disconnect”, “rigid”, or value of stiffness

tubes

group

n/a

Each tube is a subgroup of this group

Default naming scheme: 0, 1, 2, …

Tube

When providing an HDF5 file as input the results and quadrature_results groups must exist but the user does not need to provide any pre-populated results fields (srlife will add these during the analysis).

Field

Type

Data type

Explanation

Notes

r

attribute

float

Tube inner radius

t

attribute

float

Tube thickness

h

attribute

float

Tube height

nr

attribute

int

Number of radial nodes

nt

attribute

int

Number of circumferential nodes

nz

attribute

int

Number of axial nodes

abstraction

attribute

string

Tube dimension

“1D”, “2D”, or “3D”

times

dataset

dim: (ntime,)

Discrete time points

results

group

n/a

Node point results

Each result field is a dataset

quadrature_results

group

n/a

Quadrature point results

Each result field is a dataset

outer_bc

group

n/a

Outer diameter thermal BC

See below

inner_bc

group

n/a

Inner diameter thermal BC

See below

pressure_bc

group

n/a

Internal pressure

See below

HeatFluxBC

The user must always provide the full flux information (i.e. over the full 3D tube).

Field

Type

Data type

Explanation

Notes

type

attribute

string

Thermal BC type

Must be “HeatFlux”

r

attribute

float

Radius of application

Must match tube inner or outer radius

h

attribute

float

Tube height

Must match tube height

nt

attribute

int

Number of circumferential nodes

nz

attribute

int

Number of axial nodes

times

dataset

dim: (ntime,)

Discrete times points

data

dataset

dim: (ntime, nt, nz)

Discrete flux data

Fixed array over tube inner/outer surface

PressureBC

Field

Type

Data type

Explanation

Notes

times

dataset

dim: (ntime,)

Discrete times points

data

dataset

dim: (ntime,)

Discrete pressure data