grackle-project / grackle

The Grackle chemistry and cooling library for astrophysical simulations and models.
Other
26 stars 50 forks source link

WIP: Automatic Unit Handling #232

Open mabruzzo opened 2 months ago

mabruzzo commented 2 months ago

This PR provides a provides a proof-of-concept implementation for automatic unit-handling. (It hasn't been rigorously tested and the implementation could be a lot more efficient).

How to use Automatic Unit Handling

Currently, we have an opt-in system (if you don't opt-in, Grackle will use its existing behavior).

To specify that you want to use the automatic unit-handling you need to invoke the following[^1]

my_chemistry->unit_handling = GR_UNIT_HANDLING_AUTOMATIC;

When the user calls the [local]_calculate_* and [local]_solve_chemistry families of functions, Grackle will automatically and internally calculate the current code_units based on the "current_a_value" (we'll talk about how that is specified in a moment). An error is reported if the user passes in something other than a NULL pointer for the code_units argument of that in a moment.

The current value of the cosmological scale factor is specified by the newly created current_a_value data-member of the grackle_field_data struct. If a user doesn't modify the default value, Grackle assumes that you want to use the value that the code_units struct held when it was passed into initialize_chemistry_data or local_initialize_chemistry_data.

Additional ideas

Alternative mechanism for specifying current_a_value

An alternative to the current mechanism for specifying the current_a_value is to store the value inside the chemistry_data_storage object. This would probably be achieved by introducing a function with the signature

int gr_set_current_a_value(chemistry_data_storage*, double)

Making code_units unnecessary

Currently, the user still needs to pass code_units into initialize_chemistry_data or local_initialize_chemistry_data, even when they are using the automatic unit-handling. We could make this unnecessary by introducing the following new parameters to the chemistry_data struct.

And we could encode the information currently held by code_units::comoving_coordinates within the chemistry_data::unit_handling parameter.

I actually think this would be a good thing (and would generally make it simpler to use grackle). I also think it would be easier to implement this as part of this PR (rather than as 2 separate steps). With that said, I think it's important to make it very clear that once the user calls initialize_chemistry_data or local_initialize_chemistry_data, it would be disastrous to mutate any of these values.[^2]

[^1]: by opting in, users are promising that they will use the gr_initialize_field_data function to initialize the grackle_field_data struct. If they don't do that problems could arise (and we don't currently have any good way to check whether they use that initialization function).

[^2]: In general, I think we should always discourage people from mutating values after calling initialize_chemistry_data or local_initialize_chemistry_data (unless they really know all of the internals of grackle). But in this case, we would need to take a particularly strong stance.