Skip to content

Enable parsing of 1D column data and interpolation in functional space using LookupTable object - #401

Draft
dutta-alankar wants to merge 5 commits into
idefix-code:developfrom
dutta-alankar:lookupTable_parse_1d_columns
Draft

Enable parsing of 1D column data and interpolation in functional space using LookupTable object#401
dutta-alankar wants to merge 5 commits into
idefix-code:developfrom
dutta-alankar:lookupTable_parse_1d_columns

Conversation

@dutta-alankar

@dutta-alankar dutta-alankar commented Aug 19, 2026

Copy link
Copy Markdown
Contributor

This PR is in preparation of using Tabulated optically thin radiative cooling on Idefix.
It is common in many codes to use cooling function where the first column is temperature in Kelvin and second is the cooling function $\Lambda$ at the tabulated temperature value.
In order to parse data of this type, I extended the functionality of LookupTable in 1D mode. In addition to this, power law interpolation is also very common, which corresponds to linear interpolation in log space. To achieve this, I introduced to LookupTable::Get function the ability to use linear interpolation in function space (usable from both host and device in all dimensions). log/exp pair is the default functional space combination with the possibility to have custom functional space (example in test/utils/lookupTable).
I ensured that LookupTable adheres to the original behavior as default to ensure that any previous usage of this utility is not broken.

The CSV constructor of LookupTable now accepts an optional readColumns
argument. When it is set to true (1D tables only), xinHost is read from
the first column of the ASCII file and dataHost from its second column,
instead of the first and second lines of the file. Both are then shared
on the device as before. The default behaviour (arrays read as lines)
and the parsing of 2D tables are left unchanged.

Also document the handling of comments and blank lines in CSV files, and
add a test of the new column layout in test/utils/lookupTable.
GetNeighbours and GetNeighboursIndx (and their Host counterparts) return
the elements of the table surrounding the requested coordinates: the two
coordinates bracketing the input along each dimension, the data on the
2^nDim vertices of the surrounding cell, and the corresponding indices in
the table. When the table is interpolated in function space, the returned
coordinates and data are transformed back with invFunc, so that they are
expressed in the original space of the table.

Get is left unchanged, and the neighbour search is shared by the new
methods through the GetIndices and GetDataIndex helpers.
Get (and GetHost) now accept a LookupTableNeighbours structure in which
they store the search they performed. Giving that same structure to
GetNeighbours or GetNeighboursIndx makes them reuse this search instead
of walking the table a second time, and they search it again as usual as
soon as different coordinates are requested.

The structure is held by the caller rather than by the lookup table, so
that it is thread-private when it is declared inside an idefix_for: a
lookup table is shared by all of the threads of a loop, and can hence not
cache anything itself. The existing Get is left untouched.
GetNeighbours and GetNeighboursIndx already search the table when they
are given a structure which does not hold the requested coordinates yet,
and Get reuses whatever search that structure holds, so the two orders
are equivalent. Add the tests which check it, on the host and on the
device, and document that the order of the calls is irrelevant.
@glesur

glesur commented Aug 19, 2026

Copy link
Copy Markdown
Contributor

@dutta-alankar : let us know when this PR is ready to go through the workflow, as we have a limited workflow capacity, and we can't possibly test each commit you're pushing.
Thanks

@glesur
glesur marked this pull request as draft August 19, 2026 13:46
@dutta-alankar

dutta-alankar commented Aug 19, 2026

Copy link
Copy Markdown
Contributor Author

@glesur I'm terribly sorry for the trouble. I think now this is finalized and ready and good to go.

@dutta-alankar

Copy link
Copy Markdown
Contributor Author

@glesur @svalat
Please review and suggest any changes if needed and I would be happy to incorporate them.

@glesur
glesur self-requested a review August 20, 2026 12:29
@glesur

glesur commented Aug 20, 2026

Copy link
Copy Markdown
Contributor

I’ve read your PR in details. While I understand the motivation for supporting specific 1D input, I’m not entirely convinced about the necessity of including the log/exp interpolator in the core codebase. In practice, if logarithmic interpolation is needed, users could simply provide a pre-computed log-scaled table and use the existing LookupTable class to interpolate, followed by any additional processing. This seems like functionality that could remain on the user side rather than being integrated into the main trunk.

Additionally, I’m curious about the intended use case for GetNeighbours and GetNeighboursIdx. Are these primarily for debugging? I’m struggling to see how they would be essential in a production environment. Could you clarify their purpose?

@dutta-alankar

dutta-alankar commented Aug 21, 2026

Copy link
Copy Markdown
Contributor Author

I’ve read your PR in details. While I understand the motivation for supporting specific 1D input, I’m not entirely convinced about the necessity of including the log/exp interpolator in the core codebase. In practice, if logarithmic interpolation is needed, users could simply provide a pre-computed log-scaled table and use the existing LookupTable class to interpolate, followed by any additional processing. This seems like functionality that could remain on the user side rather than being integrated into the main trunk.

Additionally, I’m curious about the intended use case for GetNeighbours and GetNeighboursIdx. Are these primarily for debugging? I’m struggling to see how they would be essential in a production environment. Could you clarify their purpose?

@glesur Thanks a lot for having a look at the PR. Let me expand on a few points to give better context for the choices I made.

Column-format input. Most standard radiative cooling tables (typically Cloudy-generated) used by codes such as the Athena variants, PLUTO, Quokka, FLASH, and AMRVAC are distributed in column format. Being able to parse
column-arranged data in Idefix means these tables can be reused as-is, without any preprocessing or conversion.

Log/exp interpolation. Broken power laws are a very common way to approximate cooling functions in the literature, and linear interpolation in log space naturally reproduces a power law between successive data points. A user could of course supply a pre-transformed table to LookupTable and write their own (host/device-compatible) functions to invert the transformation. But providing native support for the most common case -- while also allowing custom transformations and leaving the existing LookupTable semantics untouched (the linear interpolator remains the default) -- considerably reduces the effort needed to build Idefix modules that work with existing tables unmodified.

GetNeighbours and GetNeighboursIndx. These are needed for the radiative cooling module, not just for debugging. The Townsend exact-integration scheme requires more than the interpolated cooling rate at a cell's temperature: it also needs the local slope of the power-law segment, the temperature bounds of that segment, and the function value at one of those bounds -- all of which are constructed from the neighbouring table entries (see Eqs. 26, A5, and A7 of R. H. D. Townsend 2009 ApJS 181 391; An Exact Integration Scheme for Radiative Cooling in Hydrodynamical Simulations). My earlier PR that implemented radiative cooling (#349) carried its own interpolation routine and so did not need any of this. As @svalat suggested here -- and I agree that this is the cleaner structure -- the cooling function should be interpolated through LookupTable, which requires exposing the neighbour lookup.

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.

2 participants