Skip to content

Conversation

The9Cat
Copy link
Member

@The9Cat The9Cat commented Sep 20, 2025

Summary

  • Unit class provides the three fields (name as char[16], unit as char[16], value as float).
  • We need fixed strings for HDF5 compound types.
  • The Coefs base class maintains a std::vector<Unit> container, written to coefficient files as an HDF5 dataset
  • This can be read and written by h5py as an array of dtype([('name', 'S16'), ('unit', 'S16'), ('value', '<f4')])

EXP integration

  • The Unit instance ("G", "none", 1.0f) is the default. Applications can call the setUnit(name, unit, value) member function to add units. The intent is that the unit field is one of the standard astronomically common units, e.g. as used by astropy. However, Unit does no checking. I suggest the standard name fields Length, Time, Mass, Velocity and G but there is no name checking.
  • Calling setUnit will check for the name in the array and replace units and values. The matching is case insensitive. One call is needed for each unit.
  • The Coefs class will populate the Unit array on read.
  • The Coefs class provides a getUnits() member which returns a vector of tuples as <std::string, std::string, float> and a getGravConstant() member that returns the value of the gravitational constant only

pyEXP integration

  • The members setUnit(), getUnits() and getGravConstant() are bound to pyEXP.coefs.Coefs interface
  • In addition, the field quantities returned by pyEXP::Basis will scale potential and force quantities with the current value of the gravitational constant
  • Users creating coefficient files from pyEXP will be warned/encouraged to provide unit data if no units have been set.

Gala integration strategy

Now that I understand the Gala/astropy units concept, we should be able to use both UnitSystem and SimulationUnitSystem depending on the user's need. One might be begin by using the pyEXP.Coefs.getUnits() to pull vector of tuples that describe the user's units. There are two clear-cut cases:

  1. The user stipulates G=1 with a supplied Mass and Length unit. In that case, Gala can create a SimulationUnitSystem object.
  2. The user specifies G!=1 with either Mass, Length, and Velocity or Mass, Length, and Time. In that case, Gala can create a UnitSystem and the value of G will be handled correctly by pyEXP. There is an obvious internal check: the implied value of G by the three supplied physical units should match (with some tolerance) the supplied value of G. Note: G is a required field in exp in the current implementation. So this should be unambiguous; e.g. the user can not specify Mass, Length, and Time and not specify G. Alternatively, I could attempt to do the unit parsing on the pyEXP side. But that seems like inappropriate duplication of existing code.

Checks

  • The code compiles
  • The Unit vector is correctly created by Coefs
  • The Unit vector is correctly serialized into HDF5
  • The Units dataset is correctly read by h5py and EXP
  • The Units are correctly reread when the coefficient dataset is extended during an exp simulation
  • Gala builds on branch and runs for G=1 on existing examples for Spherical and Cylindrical
  • Non unit values of G are correctly handed by the pyEXP.basis.Basis classes
  • Add appropriate documentation for the final version

Martin D. Weinberg added 4 commits September 18, 2025 20:27
- The Unit class is a vector of tuples of name (ascii), unit type (ascii),
  and value (float).
- This vector is serialized in HDF5 coefficient files as a list of tuples
- Manipulators and accessors are provided as part of Python bindings to C++
  member functions
- The gravitational constant is set on read from a Coefs instance and
  used to set the gravitational constant in BiorthBasis.
- The value of G=1 by default (exp).  The user is responsible for setting
  the units in a Coefs instance using the setUnit() call, one for each
  physical unit including the gravitational constant.
Copy link
Contributor

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR adds a Unit class to the EXP coefficient system to provide unit information for gravitational simulations. The main goal is to track physical units and the gravitational constant for proper scaling of potential and force calculations in both EXP and pyEXP.

Key changes:

  • Introduces a Unit struct to store unit metadata (name, unit string, value) in HDF5-compatible format
  • Implements unit management methods in the Coefs base class for setting, reading, and writing units
  • Integrates gravitational constant scaling throughout the basis evaluation functions

Reviewed Changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 11 comments.

Show a summary per file
File Description
pyEXP/CoefWrappers.cc Adds Python bindings for unit management and warns users to set units before writing HDF5 files
expui/Coefficients.cc Implements core unit functionality including HDF5 serialization and gravitational constant retrieval
expui/Coefficients.H Defines the Unit struct and declares unit management methods in the Coefs class
expui/CoefStruct.H Adds gravitational constant field to coefficient structures
expui/BiorthBasis.cc Integrates gravitational constant scaling in all basis evaluation methods
expui/BasisFactory.H Adds gravitational constant member to basis factory

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant