-
Notifications
You must be signed in to change notification settings - Fork 4
Fix krypton calculation #31
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
25 commits
Select commit
Hold shift + click to select a range
e88952d
Use exact join on datasets
tbody-cfs 9031674
Add an option to run the full radas command in testing
tbody-cfs 2a3c7e5
Add option to use inner join for Krypton
tbody-cfs 1fee1f1
Tidy up Mavrin plots
tbody-cfs b3d5afb
Bump the version to 1!1.0.1
tbody-cfs 1ca5040
Remove ipdb from radas command test
tbody-cfs 9b2c730
Prevent ipdb from running without --debug.
tbody-cfs ac33da6
Test radas command with 3.12 and upload artifacts
tbody-cfs 1735a75
Record which year data file is from
tbody-cfs 82b25fa
Improve error handling for AlignmentErrors
tbody-cfs cd7877f
Ensure all data files come from the same year to resolve alignment error
tbody-cfs d955325
Fix missing matrix variable in Github actions
tbody-cfs 9d2cd13
Use nearest-neighbour if extrapolation needed
tbody-cfs 7a2c2f0
Remove optional interpolation of rates. Now required to align grids
tbody-cfs 54290f3
Implement interpolation to align data grids
tbody-cfs 4c5e21b
Revert config to use latest available data
tbody-cfs 2b35e7d
Run heavier elements first in parallel
tbody-cfs 8cac436
Improve documentation of rate reading and interpolation
tbody-cfs 74cfa82
Add new points for ne-tau
tbody-cfs 9270a1b
Tidy up legend for plots
tbody-cfs e1fd767
Add reference electron density and temp back to datasets
tbody-cfs 214f26d
Remove git hash from datasets
tbody-cfs 6454d91
Incorporate suggestions from @MishaVeldhoen
tbody-cfs b295b3f
Add a warning for off-grid extrapolation (switch on with --debug)
tbody-cfs 844560d
Incorporate comments from @MishaVeldhoen
tbody-cfs File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,78 +1,86 @@ | ||
| """Routines to interpolate a dataset of rate coefficients to higher resolution.""" | ||
| """Routines for log-log interpolation of rate coefficients with boundary clipping.""" | ||
| import xarray as xr | ||
| import numpy as np | ||
| from scipy.interpolate import RectBivariateSpline | ||
| from numpy.typing import NDArray | ||
| import warnings | ||
|
|
||
| def interpolate_array(array: xr.DataArray, new_electron_density: NDArray[np.floating], new_electron_temp: NDArray[np.floating]) -> xr.DataArray: | ||
| """Interpolate array onto new values for the electron density and electron temp. | ||
| def is_significantly_below(requested, limit): | ||
| return requested < limit and not np.isclose(requested, limit) | ||
|
|
||
| def is_significantly_above(requested, limit): | ||
| return requested > limit and not np.isclose(requested, limit) | ||
|
|
||
| def interpolate_array( | ||
| array: xr.DataArray, | ||
| new_electron_density: NDArray[np.floating], | ||
| new_electron_temp: NDArray[np.floating] | ||
| ) -> xr.DataArray: | ||
| """ | ||
| Interpolate rate coefficients onto a new density/temperature grid in log-log space. | ||
|
|
||
| The interpolation is performed for logarithmic values. | ||
| Uses nearest-neighbor extrapolation by clipping out-of-bounds coordinates to | ||
| the original grid edges. | ||
| """ | ||
| units = array.pint.units | ||
| array = array.pint.dequantify().squeeze() | ||
|
|
||
| # Handle zero-value edge cases (log of zero is undefined) | ||
| if np.allclose(array, 0.0, atol=0.0, rtol=1e-6): | ||
| # If all values of the array are zero, return a zero array. | ||
| return xr.DataArray(np.zeros((np.size(new_electron_temp), np.size(new_electron_density))), | ||
| return xr.DataArray( | ||
| np.zeros((np.size(new_electron_temp), np.size(new_electron_density))), | ||
| coords=dict(dim_electron_temp=new_electron_temp, dim_electron_density=new_electron_density) | ||
| ) * units | ||
| elif np.any(array <= 0.0): | ||
| # If only some of the values of the array are zero, raise an error. | ||
| raise NotImplementedError("Cannot handle zero-valued entries in non-zero rate coefficients.") | ||
|
|
||
| if np.any(array <= 0.0): | ||
| raise NotImplementedError("Cannot log-interpolate rate coefficients containing zeros.") | ||
|
|
||
| # Check if extrapolation is needed and raise a warning if this is the case. | ||
| out_of_bounds_msg = [] | ||
|
|
||
| req_dens_min, req_dens_max = new_electron_density.min(), new_electron_density.max() | ||
| grid_dens_min, grid_dens_max = array.dim_electron_density.min(), array.dim_electron_density.max() | ||
|
|
||
| if is_significantly_below(req_dens_min, grid_dens_min) or is_significantly_above(req_dens_max, grid_dens_max): | ||
| out_of_bounds_msg.append( | ||
| f"Density requested [{req_dens_min:.2e}, {req_dens_max:.2e}] " | ||
| f"exceeds grid [{grid_dens_min:.2e}, {grid_dens_max:.2e}]." | ||
| ) | ||
|
|
||
| # Check Temperature Bounds | ||
| req_temp_min, req_temp_max = new_electron_temp.min(), new_electron_temp.max() | ||
| grid_temp_min, grid_temp_max = array.dim_electron_temp.min(), array.dim_electron_temp.max() | ||
|
|
||
| if is_significantly_below(req_temp_min, grid_temp_min) or is_significantly_above(req_temp_max, grid_temp_max): | ||
| out_of_bounds_msg.append( | ||
| f"Temperature requested [{req_temp_min:.2e}, {req_temp_max:.2e}] " | ||
| f"exceeds grid [{grid_temp_min:.2e}, {grid_temp_max:.2e}]." | ||
| ) | ||
|
|
||
| if out_of_bounds_msg: | ||
| full_msg = "Nearest-neighbour extrapolation used for off-grid values: " + " ".join(out_of_bounds_msg) | ||
| warnings.warn(full_msg, RuntimeWarning) | ||
|
|
||
| # ------------------------------------ | ||
|
|
||
| # Prepare original grid and data in log10 space | ||
| x = np.log10(array.dim_electron_density) | ||
| y = np.log10(array.dim_electron_temp) | ||
| z = np.log10(array.transpose("dim_electron_density", "dim_electron_temp").pint.magnitude) | ||
|
|
||
| # Transform target coordinates to log10 | ||
| x_interp = np.log10(new_electron_density) | ||
| y_interp = np.log10(new_electron_temp) | ||
| z_interp = np.power(10, RectBivariateSpline(x, y, z)(x_interp, y_interp, grid=True).T) | ||
|
|
||
| return xr.DataArray(z_interp, | ||
| coords=dict(dim_electron_temp=new_electron_temp, dim_electron_density=new_electron_density) | ||
| ) * units | ||
|
|
||
| def interpolate_dataset(dataset: xr.Dataset, electron_density_resolution: int, electron_temp_resolution: int) -> xr.Dataset: | ||
| """Interpolate all rate coefficients in a dataset.""" | ||
| new_electron_density = np.logspace( | ||
| np.log10(dataset["dim_electron_density"].min().item()), | ||
| np.log10(dataset["dim_electron_density"].max().item()), | ||
| num = electron_density_resolution | ||
| ) | ||
| # Force nearest-neighbor extrapolation by clipping points to the grid domain | ||
| x_clipped = np.clip(x_interp, x.min().item(), x.max().item()) | ||
| y_clipped = np.clip(y_interp, y.min().item(), y.max().item()) | ||
|
|
||
| new_electron_temp = np.logspace( | ||
| np.log10(dataset["dim_electron_temp"].min().item()), | ||
| np.log10(dataset["dim_electron_temp"].max().item()), | ||
| num = electron_temp_resolution | ||
| ) | ||
| # Perform spline interpolation and revert from log space | ||
| z_interp_log = RectBivariateSpline(x, y, z)(x_clipped, y_clipped, grid=True) | ||
| z_interp = np.power(10, z_interp_log.T) | ||
|
|
||
| new_dataset = xr.Dataset().assign_attrs(dataset.attrs) | ||
|
|
||
| for key, array in dataset.items(): | ||
| if key in [ | ||
| "electron_density", | ||
| "electron_temp", | ||
| ]: | ||
| # Don't copy in the coordinate arrays which we'll interpolate | ||
| continue | ||
| elif key in [ | ||
| "ne_tau" | ||
| ]: | ||
| # Directly copy in the coordinate arrays which we'll leave unchanged | ||
| new_dataset[key] = array | ||
| elif array.ndim == 0: | ||
| # Directly copy in scalar arrays | ||
| new_dataset[key] = array | ||
| elif (("dim_electron_density" in array.coords) | ||
| and ("dim_electron_temp" in array.coords) | ||
| and ("dim_charge_state" in array.coords)): | ||
| # For each charge state, interpolate the rate coefficient | ||
| new_dataset[key] = array.groupby("dim_charge_state").map(interpolate_array, args=(new_electron_density, new_electron_temp)) | ||
| else: | ||
| raise NotImplementedError(f"Could not process array '{key}' with coords {array.coords}") | ||
|
|
||
| new_dataset["electron_density"] = xr.DataArray(new_electron_density, dims="dim_electron_density") * dataset["electron_density"].pint.units | ||
| new_dataset["electron_temp"] = xr.DataArray(new_electron_temp, dims="dim_electron_temp") * dataset["electron_temp"].pint.units | ||
|
|
||
| return new_dataset | ||
| return xr.DataArray( | ||
| z_interp, | ||
| coords=dict(dim_electron_temp=new_electron_temp, dim_electron_density=new_electron_density) | ||
|
MishaVeldhoen marked this conversation as resolved.
|
||
| ) * units | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.