Skip to content

hallmd.data

The hallmd.data package contains a folder for each unique thruster. The experimental data for each thruster is further divided by folders for each individual paper or reference. The raw experimental data is contained within these folders in any supported format (currently only .csv). Any additional documentation for the datasets is encouraged (e.g. citations, descriptions, summaries, etc.) and can be included in the data folders.

Thrusters

SPT-100

Currently the only thruster with available data. Data for the SPT-100 comes from four sources:

  1. Diamant et al. 2014 - provides thrust and ion current density data as a function of chamber background pressure.
  2. Macdonald et al. 2019 - provides ion velocity profiles for varying chamber pressures.
  3. Sankovic et al. 1993 - provides thrust at varying operating conditions.
  4. Jorns and Byrne. 2021 - provides cathode coupling voltages at same conditions as Diamant et al. 2014.

Citations:

SPT-100.bib
@incollection{diamantEffectBackgroundPressure2014,
    title = {The {{Effect}} of {{Background Pressure}} on {{SPT-100 Hall
             Thruster Performance}}},
    booktitle = {50th {{AIAA}}/{{ASME}}/{{SAE}}/{{ASEE Joint Propulsion
                 Conference}}},
    author = {Diamant, Kevin D. and Liang, Raymond and Corey, Ron L.},
    date = {2014-07-25},
    series = {{{AIAA Propulsion}} and {{Energy Forum}}},
    publisher = {{American Institute of Aeronautics and Astronautics}},
    doi = {10.2514/6.2014-3710},
    year = {2014},
}

@article{macdonaldBackgroundPressureEffects2019,
    title = {Background {{Pressure Effects}} on {{Ion Velocity Distributions}}
             in an {{SPT-100 Hall Thruster}}},
    author = {Macdonald-Tenenbaum, Natalia and Pratt, Quinn and Nakles, Michael
              and Pilgram, Nickolas and Holmes, Michael and Hargus, William},
    date = {2019-01-11},
    journaltitle = {Journal of Propulsion and Power},
    shortjournal = {Journal of Propulsion and Power},
    volume = {35},
    pages = {1--10},
    doi = {10.2514/1.B37133},
}

@inproceedings{sankovicPerformanceEvaluationRussian1993,
    title = {Performance Evaluation of the {{Russian SPT-100}} Thruster at {{
             NASA LeRC}}},
    author = {Sankovic, J. and Hamley, J. and Haag, T.},
    date = {1993-09-13/1993-09-16},
    location = {{Seattle, WA, USA}},
    url = {
           https://www.semanticscholar.org/paper/Performance-evaluation-of-the-Russian-SPT-100-at-Sankovic-Hamley/81b7d985669b21aa1a8419277c52e7a879bf3b46
           },
    urldate = {2023-01-06},
    eventtitle = {23rd {{International Electric Propulsion Conference}}},
}

@article{jornsCathodeCoupling2021,
    title = {Model for the dependence of cathode voltage in a {H}all thruster on
             facility pressure},
    author = {Jorns, Benjamin A. and Byrne, Matthew P.},
    date = {2021-01-12},
    journaltitle = {Plasma Sources Science and Technology},
    volume = {30},
    number = {1},
    pages = {015012},
    publisher = {IOP Publishing},
    doi = {10.1088/1361-6595/abd3b6},
}

Data conventions

The data used in the PEM is expected to be in a standard format. This format may evolve over time to account for more data, but at present, when we read a CSV file, here is what we look for in the columns. Note that we treat columns case-insensitively, so Anode current (A) is treated the same as anode current (a).

Operating conditions

Data is imported into a dictionary that maps operating conditions to data. An Operating Condition (made concrete in the OperatingCondition class) consists of a unique set of an anode mass flow rate, a background pressure, and a discharge / anode voltage. These quantities are mandatory for each data file, but can be provided in a few ways. In cases where multiple options are allowed, the first matching column is chosen.

Background pressure

We expect a column named 'background pressure (torr)' (not case sensitive). We assume the pressure is in units of Torr.

Anode mass flow rate

We look for the following column names in order:

  1. A column named 'anode flow rate (mg/s)',
  2. A column named 'total flow rate (mg/s)' and a column named 'anode-cathode flow ratio',
  3. A column named 'total flow rate (mg/s)' and a column named 'cathode flow fraction'.

In all cases, the unit of the flow rate is expected to be mg/s. For option 2, the cathode flow fraction is expected as a fraction between zero and one. For option 3, the anode-cathode flow ratio is unitless and is expected to be greater than one.

Discharge voltage

We look for the following column names in order:

  1. 'discharge voltage (v)',
  2. 'anode voltage (v)'

In both cases, the unit of the voltage is expected to be Volts.

Data

The following data-fields are all optional. The ThrusterData struct will be populated only with what is provided. For each of these quantities, an uncertainty can be provided, either relative or absolute. The formats for uncertainties for a quantity of the form '{quantity} ({unit})' are 1. '{quantity} absolute uncertainty ({unit})' 2. '{quantity} relative uncertainty'

Relative uncertainties are fractions (so 0.2 == 20%) and absolute uncertainties are in the same units as the main quantity.

As an example, thrust of 100 mN and a relative uncertainty of 0.05 represents 100 +/- 5 mN. We assume the errors are normally distributed about the nominal value with the uncertainty representing two standard deviations. In this case, the distribution of the experimentally-measured thrust would be T ~ N(100, 2.5). If both relative and absolute uncertainties are provided, we use the absolute uncertainty. If an uncertainty is not provided, a relative uncertainty of 2% is assumed.

Thrust

We look for a column called 'thrust (mn)' or 'thrust (n)'. We then convert the thrust to Newtons internally.

Discharge current

We look for one of the following column names in order:

  1. 'discharge current (a)'
  2. 'anode current (a)'
Cathode coupling voltage

We look for a column called 'cathode coupling voltage (v)'.

Ion/beam current

We look for one of the following column names in order: 1. 'ion current (a)' 2. 'beam current (a)' 3. 'ion beam current (a)'

Ion current density

We look for three columns

  1. The radial distance from the thruster exit plane. Allowed keys: 'radial position from thruster exit (m)'

  2. The angle relative to thruster centerline Allowed keys: 'angular position from thruster centerline (deg)'

  3. The current density. Allowed keys: 'ion current density (ma/cm^2)' or 'ion current density (a/m^2)'

We do not look for uncertainties for the radius and angle. The current density is assumed to have units of mA / cm^2 or A / m^2, depending on the key. If one or two of these quantities is provided, we throw an error.

Ion velocity

We look for two columns:

  1. Axial position from anode Allowed keys: 'axial position from anode (m)'

  2. Ion velocity Allowed keys: 'ion velocity (m/s)'

We do not look for uncertainties for the axial position. The ion velocity is assumed to have units of m/s. If only one of these quantities is provided, we throw an error.

opcond_keys = {'p_b': 'background_pressure_torr', 'v_a': 'discharge_voltage_v', 'mdot_a': 'anode_mass_flow_rate_kg_s'} module-attribute

Forward mapping between operating condition short and long names.

CurrentDensitySweep(radius_m, angles_rad, current_density_A_m2) dataclass

Contains data for a single current density sweep.

ATTRIBUTE DESCRIPTION
radius_m

the radial distance (in m) from the thruster exit plane at which the sweep was obtained.

TYPE: float64

angles_rad

the angular measurement locations (in rad) from thruster centerline.

TYPE: Array

current_density_A_m2

the measured current density in (A/m^2) at all measurement locations.

TYPE: Measurement[Array]

IonVelocityData(axial_distance_m, velocity_m_s) dataclass

Contains measurements of axial ion velocity along with coordinates.

ATTRIBUTE DESCRIPTION
axial_distance_m

the axial channel distance (in m) from the anode where the measurements were taken.

TYPE: Array

velocity_m_s

the ion velocity measurements obtained from LIF (in m/s).

TYPE: Measurement[Array]

Measurement(mean, std) dataclass

Bases: Generic[T]

A measurement object that includes a mean and standard deviation. The mean is the best estimate of the quantity being measured, and the standard deviation is the uncertainty in the measurement. Can be used to specify a scalar measurement quantity or a field quantity (e.g. a profile) in the form of a numpy array.

OperatingCondition(background_pressure_torr, discharge_voltage_v, anode_mass_flow_rate_kg_s) dataclass

Operating conditions for a Hall thruster.

ATTRIBUTE DESCRIPTION
background_pressure_torr

the background pressure in Torr.

TYPE: float

discharge_voltage_v

the discharge voltage in Volts.

TYPE: float

anode_mass_flow_rate_kg_s

the anode mass flow rate in kg/s.

TYPE: float

ThrusterData(cathode_coupling_voltage_V=None, thrust_N=None, discharge_current_A=None, ion_current_A=None, efficiency_current=None, efficiency_mass=None, efficiency_voltage=None, efficiency_anode=None, ion_velocity=None, ion_current_sweeps=None) dataclass

Class for Hall thruster data. Contains fields for all relevant performance metrics and quantities of interest. All metrics are time-averaged unless otherwise noted. A ThrusterData instance can contain as many or as few fields as needed, depending on the available data.

ATTRIBUTE DESCRIPTION
cathode_coupling_voltage_V

the cathode coupling voltage (V)

TYPE: Optional[Measurement[float64]]

thrust_N

the thrust (N)

TYPE: Optional[Measurement[float64]]

discharge_current_A

the discharge current (A)

TYPE: Optional[Measurement[float64]]

efficiency_current

the current efficiency

TYPE: Optional[Measurement[float64]]

efficiency_mass

the mass efficiency

TYPE: Optional[Measurement[float64]]

efficiency_voltage

the voltage efficiency

TYPE: Optional[Measurement[float64]]

efficiency_anode

the anode efficiency

TYPE: Optional[Measurement[float64]]

ion_velocity

the axial ion velocity data

TYPE: Optional[IonVelocityData]

ion_current_sweeps

a list of current density sweeps

TYPE: Optional[list[CurrentDensitySweep]]

update(data1, data2) staticmethod

Return a new ThrusterData instance with merged fields from data1 and data2.

Source code in src/hallmd/data/__init__.py
@staticmethod
def update(data1: 'ThrusterData', data2: 'ThrusterData') -> 'ThrusterData':
    """Return a new `ThrusterData` instance with merged fields from `data1` and `data2`."""
    merged = {}
    for field in fields(ThrusterData):
        merged[field.name] = ThrusterData._merge_field(field.name, data1, data2)
    return ThrusterData(**merged)

ThrusterDataset

Bases: ABC

Abstract base class for thruster datasets. A thruster dataset provides paths to experimental data files for a specific thruster.

all_data() abstractmethod staticmethod

Return a list of paths to all datasets for this thruster.

Source code in src/hallmd/data/__init__.py
@staticmethod
@abstractmethod
def all_data() -> list[Path]:
    """Return a list of paths to all datasets for this thruster."""
    pass

datasets_from_names(dataset_names) abstractmethod staticmethod

Return a list of paths to the datasets with the given names.

Source code in src/hallmd/data/__init__.py
@staticmethod
@abstractmethod
def datasets_from_names(dataset_names: list[str]) -> list[Path]:
    """Return a list of paths to the datasets with the given names."""
    pass

get_thruster(name)

Return a thruster dataset object based on the given thruster name.

PARAMETER DESCRIPTION
name

the name of the thruster to get data for

TYPE: str

Source code in src/hallmd/data/__init__.py
def get_thruster(name: str) -> ThrusterDataset:
    """Return a thruster dataset object based on the given thruster name.

    :param name: the name of the thruster to get data for
    """
    if name.casefold() in {'h9'}:
        from .h9 import H9

        return H9
    elif name.casefold() in {'spt-100', 'spt100'}:
        from .spt100 import SPT100

        return SPT100
    else:
        raise ValueError(f"Invalid thruster name {name}.")

load(files)

Load all data from the given files into a dict map of OperatingCondition -> ThrusterData. Each thruster operating condition corresponds to one set of thruster measurements or quantities of interest (QoIs).

PARAMETER DESCRIPTION
files

A list of file paths or a single file path to load data from (only .csv supported).

TYPE: Sequence[PathLike] | PathLike

RETURNS DESCRIPTION
dict[OperatingCondition, ThrusterData]

A dict map of OperatingCondition -> ThrusterData objects.

Source code in src/hallmd/data/__init__.py
def load(files: Sequence[PathLike] | PathLike) -> dict[OperatingCondition, ThrusterData]:
    """Load all data from the given files into a dict map of `OperatingCondition` -> `ThrusterData`.
    Each thruster operating condition corresponds to one set of thruster measurements or quantities of interest (QoIs).

    :param files: A list of file paths or a single file path to load data from (only .csv supported).
    :return: A dict map of `OperatingCondition` -> `ThrusterData` objects.
    """
    data: dict[OperatingCondition, ThrusterData] = {}
    if isinstance(files, list):
        # Recursively load resources in this list (possibly list of lists)
        for file in files:
            new_data = load(file)
            data = _update_data(data, new_data)
    else:
        new_data = _load_single_file(files)
        data = _update_data(data, new_data)

    return data

pem_to_thrusterdata(operating_conditions, outputs, sweep_radii, use_corrected_thrust=True)

Given a list of operating conditions and an outputs dict from amisc, construct a dict mapping the operating conditions to ThrusterData objects. Note: we assume that the amisc outputs are ordered based on the input operating conditions.

PARAMETER DESCRIPTION
operating_conditions

A list of OperatingConditions at which the pem was run.

TYPE: list[OperatingCondition]

outputs

the amisc output dict from the run

TYPE: dict

sweep_radii

an array of radii at which ion current density data was taken

TYPE: Array

use_corrected_thrust

Whether to use the base thrust from HallThruster.jl or the thrust corrected by the divergence angle computed in the plume model.

TYPE: bool DEFAULT: True

Source code in src/hallmd/data/__init__.py
def pem_to_thrusterdata(
    operating_conditions: list[OperatingCondition], outputs: dict, sweep_radii: Array, use_corrected_thrust: bool = True
) -> Optional[dict[OperatingCondition, ThrusterData]]:
    """Given a list of operating conditions and an `outputs` dict from amisc,
    construct a `dict` mapping the operating conditions to `ThrusterData` objects.
    Note: we assume that the amisc outputs are ordered based on the input operating conditions.

    :param operating_conditions: A list of `OperatingConditions` at which the pem was run.
    :param outputs: the amisc output dict from the run
    :param sweep_radii: an array of radii at which ion current density data was taken
    :param use_corrected_thrust: Whether to use the base thrust from HallThruster.jl or the thrust corrected by the
           divergence angle computed in the plume model.
    """  # noqa: E501

    # Check to make sure all keys that we expect to be there are there
    if not _amisc_output_is_valid(outputs, len(operating_conditions)):
        return None

    output_dict = {
        opcond: _single_opcond_to_thrusterdata(i, outputs, sweep_radii, use_corrected_thrust)
        for (i, opcond) in enumerate(operating_conditions)
    }

    return output_dict