rm-tables 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- rm_tables-0.1.0/LICENSE +21 -0
- rm_tables-0.1.0/PKG-INFO +208 -0
- rm_tables-0.1.0/README.md +176 -0
- rm_tables-0.1.0/pyproject.toml +52 -0
- rm_tables-0.1.0/rm_tables/__init__.py +25 -0
- rm_tables-0.1.0/rm_tables/coverage.py +216 -0
- rm_tables-0.1.0/rm_tables/data/ferguson_f05_g93.npz +0 -0
- rm_tables-0.1.0/rm_tables/data/kR_h2001.dat +722 -0
- rm_tables-0.1.0/rm_tables/data/opal_type1.npz +0 -0
- rm_tables-0.1.0/rm_tables/defaults.py +93 -0
- rm_tables-0.1.0/rm_tables/io.py +265 -0
- rm_tables-0.1.0/rm_tables/lookup.py +323 -0
- rm_tables-0.1.0/rm_tables/sources/__init__.py +9 -0
- rm_tables-0.1.0/rm_tables/sources/_compiled.py +219 -0
- rm_tables-0.1.0/rm_tables/sources/_composition.py +114 -0
- rm_tables-0.1.0/rm_tables/sources/_semenov_fit.py +163 -0
- rm_tables-0.1.0/rm_tables/sources/ferguson.py +154 -0
- rm_tables-0.1.0/rm_tables/sources/opal.py +240 -0
- rm_tables-0.1.0/rm_tables/sources/semenov.py +130 -0
- rm_tables-0.1.0/rm_tables/tables.py +528 -0
- rm_tables-0.1.0/rm_tables.egg-info/PKG-INFO +208 -0
- rm_tables-0.1.0/rm_tables.egg-info/SOURCES.txt +40 -0
- rm_tables-0.1.0/rm_tables.egg-info/dependency_links.txt +1 -0
- rm_tables-0.1.0/rm_tables.egg-info/requires.txt +9 -0
- rm_tables-0.1.0/rm_tables.egg-info/top_level.txt +1 -0
- rm_tables-0.1.0/setup.cfg +4 -0
- rm_tables-0.1.0/tests/test_break_findings.py +247 -0
- rm_tables-0.1.0/tests/test_build.py +140 -0
- rm_tables-0.1.0/tests/test_compiled.py +92 -0
- rm_tables-0.1.0/tests/test_compiled_entry.py +71 -0
- rm_tables-0.1.0/tests/test_composition.py +79 -0
- rm_tables-0.1.0/tests/test_coverage.py +93 -0
- rm_tables-0.1.0/tests/test_defaults.py +70 -0
- rm_tables-0.1.0/tests/test_edges.py +80 -0
- rm_tables-0.1.0/tests/test_examples.py +97 -0
- rm_tables-0.1.0/tests/test_ferguson.py +119 -0
- rm_tables-0.1.0/tests/test_io.py +112 -0
- rm_tables-0.1.0/tests/test_lookup.py +91 -0
- rm_tables-0.1.0/tests/test_no_zeros.py +74 -0
- rm_tables-0.1.0/tests/test_opal.py +129 -0
- rm_tables-0.1.0/tests/test_opal_sets.py +81 -0
- rm_tables-0.1.0/tests/test_semenov.py +50 -0
rm_tables-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Shmuel Gilbaum
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
rm_tables-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: rm-tables
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Rosseland mean opacity tables for gas and dust, at any composition
|
|
5
|
+
Author: Shmuel Gilbaum
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/Shmuel-Gilbaum/Rosseland-mean-Opacity-Tables
|
|
8
|
+
Project-URL: Repository, https://github.com/Shmuel-Gilbaum/Rosseland-mean-Opacity-Tables
|
|
9
|
+
Project-URL: Usage, https://github.com/Shmuel-Gilbaum/Rosseland-mean-Opacity-Tables/blob/main/USAGE.md
|
|
10
|
+
Keywords: opacity,Rosseland mean,OPAL,Semenov,Ferguson,dust,radiative transfer,accretion disk,accretion disc,protoplanetary disk,protoplanetary disc,stellar interior,astrophysics
|
|
11
|
+
Classifier: Development Status :: 4 - Beta
|
|
12
|
+
Classifier: Intended Audience :: Science/Research
|
|
13
|
+
Classifier: Topic :: Scientific/Engineering :: Astronomy
|
|
14
|
+
Classifier: Topic :: Scientific/Engineering :: Physics
|
|
15
|
+
Classifier: Operating System :: OS Independent
|
|
16
|
+
Classifier: Programming Language :: Python :: 3
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
21
|
+
Requires-Python: >=3.10
|
|
22
|
+
Description-Content-Type: text/markdown
|
|
23
|
+
License-File: LICENSE
|
|
24
|
+
Requires-Dist: numpy>=1.22
|
|
25
|
+
Requires-Dist: numba>=0.57
|
|
26
|
+
Provides-Extra: hdf5
|
|
27
|
+
Requires-Dist: h5py>=3; extra == "hdf5"
|
|
28
|
+
Provides-Extra: test
|
|
29
|
+
Requires-Dist: pytest>=7; extra == "test"
|
|
30
|
+
Requires-Dist: h5py>=3; extra == "test"
|
|
31
|
+
Dynamic: license-file
|
|
32
|
+
|
|
33
|
+
# Rosseland mean Opacity Tables
|
|
34
|
+
|
|
35
|
+
Rosseland mean opacity from published data, at a requested composition, as a
|
|
36
|
+
callable or as a built table. The default covers temperatures from 5 K to 12.6
|
|
37
|
+
million K and densities from 1e-24 to 2e4 g/cm^3. At the cold end the opacity
|
|
38
|
+
comes from dust grains, at the hot end from ionised gas.
|
|
39
|
+
|
|
40
|
+
Semenov et al. 2003 and Ferguson et al. 2005 tabulate dust and molecular gas at
|
|
41
|
+
the cold end. OPAL tabulates the ionised gas from 5623 K up. The three sit on
|
|
42
|
+
different grids and at different compositions, and the two cold ones disagree
|
|
43
|
+
about the temperature at which grains survive.
|
|
44
|
+
|
|
45
|
+
This package reads them, interpolates in hydrogen and metal mass fraction, and
|
|
46
|
+
joins a cold source to OPAL across the temperature range where both hold
|
|
47
|
+
values. Nothing is refitted. A request outside their coverage raises an error
|
|
48
|
+
naming the corner and the source that would answer it.
|
|
49
|
+
|
|
50
|
+
The data ships inside the package, so nothing is downloaded at run time.
|
|
51
|
+
|
|
52
|
+
## The data
|
|
53
|
+
|
|
54
|
+
| source | reference | range | supplies |
|
|
55
|
+
| --- | --- | --- | --- |
|
|
56
|
+
| OPAL | Iglesias & Rogers 1996, ApJ 464, 943 | 5623 K to 5e8 K | ionised gas |
|
|
57
|
+
| Semenov | Semenov et al. 2003, A&A 410, 611 | 5 K to 10,000 K | dust and molecular gas |
|
|
58
|
+
| Ferguson | Ferguson et al. 2005, ApJ 623, 585 | 501 K to 31,600 K | dust and molecular gas |
|
|
59
|
+
|
|
60
|
+
The caller chooses one of Semenov or Ferguson for the cold end.
|
|
61
|
+
|
|
62
|
+
**OPAL** ships as all 77 published Type-1 files, 6766 tables between them, on a
|
|
63
|
+
grid of hydrogen and metal mass fraction. The default is `GN93hz`, at Grevesse
|
|
64
|
+
& Noels 1993 metal ratios. Obtained from Arnold Boothroyd's public mirror at
|
|
65
|
+
the Canadian Institute for Theoretical Astrophysics.
|
|
66
|
+
|
|
67
|
+
**Semenov** ships as a Python translation of the published `opacity.f`, dust
|
|
68
|
+
model `nrm/h/s`: normal iron content, homogeneous, spherical. Its dust opacity
|
|
69
|
+
is a fifth-degree polynomial per temperature region, so no Fortran compiler is
|
|
70
|
+
involved. The translation matches the compiled original to 1.776e-05 relative,
|
|
71
|
+
which is that program's own printed precision. Its gas table ships unchanged.
|
|
72
|
+
|
|
73
|
+
Any result that uses these tables should cite the papers above.
|
|
74
|
+
|
|
75
|
+
## Install
|
|
76
|
+
|
|
77
|
+
pip install rm-tables
|
|
78
|
+
|
|
79
|
+
Requires NumPy and Numba. `h5py` is needed only to read and write HDF5 files.
|
|
80
|
+
|
|
81
|
+
## Usage
|
|
82
|
+
|
|
83
|
+
A temperature in K and a density in g/cm^3 give an opacity in cm^2/g. Every
|
|
84
|
+
argument below is optional and is written at its default, so `rm_tables.opacity()`
|
|
85
|
+
is the same call.
|
|
86
|
+
|
|
87
|
+
```python
|
|
88
|
+
import numpy as np
|
|
89
|
+
import rm_tables
|
|
90
|
+
|
|
91
|
+
kappa = rm_tables.opacity(X=0.7381, Z=0.0134, cold="semenov",
|
|
92
|
+
dataset="GN93hz", dXc=0.0, dXo=0.0)
|
|
93
|
+
print(kappa(3000.0, 1e-14)) # -> 6.635618312601376e-05
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
`X` and `Z` are the hydrogen and metal mass fractions and helium is the
|
|
97
|
+
remainder, so `X + Z` cannot exceed 1. `cold` picks the cold source, `dataset`
|
|
98
|
+
picks which of OPAL's 77 published files supplies the hot end, and `dXc` and
|
|
99
|
+
`dXo` add carbon and oxygen beyond what `Z` carries.
|
|
100
|
+
|
|
101
|
+
A composition outside what the chosen set tabulates raises rather than
|
|
102
|
+
extrapolating.
|
|
103
|
+
|
|
104
|
+
```python
|
|
105
|
+
try:
|
|
106
|
+
rm_tables.opacity(X=0.0, Z=0.5)
|
|
107
|
+
except ValueError as e:
|
|
108
|
+
print(e) # -> set 'GN93hz' tabulates metals up to 0.1, and Z=0.5 was ...
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
Arrays broadcast against each other and the result takes the broadcast shape.
|
|
112
|
+
|
|
113
|
+
```python
|
|
114
|
+
T = np.array([500.0, 3000.0, 1e5])
|
|
115
|
+
rho = np.array([1.25e-19, 1e-14, 1e-16])
|
|
116
|
+
print(kappa(T, rho)) # -> [1.7535...e+00 6.6356...e-05 4.4602...e-01]
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
A compiled solver cannot call the object, because numba refuses a Python
|
|
120
|
+
object holding Python arrays. `compiled` returns the same opacity as a numba
|
|
121
|
+
function, at 157 ns a point.
|
|
122
|
+
|
|
123
|
+
```python
|
|
124
|
+
from numba import njit
|
|
125
|
+
|
|
126
|
+
fast = rm_tables.opacity().compiled()
|
|
127
|
+
|
|
128
|
+
@njit
|
|
129
|
+
def optical_depth(T, rho, height):
|
|
130
|
+
return fast(T, rho) * rho * height
|
|
131
|
+
|
|
132
|
+
print(optical_depth(3000.0, 1e-14, 1e13)) # -> 6.6356...e-06
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
`build` returns tabulated grids instead, for fitting an interpolant or writing
|
|
136
|
+
a file. `cold` carries the cold source ramped into OPAL. `hot` carries OPAL
|
|
137
|
+
alone and reaches a higher density.
|
|
138
|
+
|
|
139
|
+
```python
|
|
140
|
+
t = rm_tables.build(X=0.7381, Z=0.0134)
|
|
141
|
+
print(t.cold.shape, t.hot.shape) # -> (200, 500) (200, 500)
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
`build` takes the same six arguments and seven more, all optional, for the
|
|
145
|
+
range, the resolution and how the pair is split. The ranges are in `log10`, and
|
|
146
|
+
`log10 R` is `rho / (T / 1e6)**3` in g/cm^3.
|
|
147
|
+
|
|
148
|
+
```python
|
|
149
|
+
t2 = rm_tables.build(log_T_range=(2.0, 6.0), log_R_range=(-8.0, -2.0),
|
|
150
|
+
n_T=300, n_R=400)
|
|
151
|
+
print(t2.cold.shape, t2.cold_log_T[0], t2.cold_log_R[-1]) # -> (300, 400) 2.0 -2.0
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
`rm_tables.defaults` holds the value each argument falls back to, with the
|
|
155
|
+
measurement that set it.
|
|
156
|
+
|
|
157
|
+
## The rest of the interface
|
|
158
|
+
|
|
159
|
+
- **Composition.** Hydrogen and metals are arguments and helium is the
|
|
160
|
+
remainder. Metallicity scales the dust exactly and leaves the gas alone.
|
|
161
|
+
- **The cold source.** Semenov tabulates where grains evaporate, Ferguson
|
|
162
|
+
where they condense. Heating material suits Semenov, cooling material suits
|
|
163
|
+
Ferguson.
|
|
164
|
+
- **The metal mixture.** All 77 OPAL sets are selectable, and so are the
|
|
165
|
+
carbon and oxygen enhanced grids inside them.
|
|
166
|
+
- **Range and resolution.** Both are arguments, and every table records what
|
|
167
|
+
it was built at.
|
|
168
|
+
- **Saving.** Compressed NumPy, plain text or HDF5, chosen by the file
|
|
169
|
+
extension, each carrying the provenance beside the numbers.
|
|
170
|
+
- **Compiled code.** `opacity(...).compiled()` is callable from inside numba,
|
|
171
|
+
and a fitted spline over a built table is the route where the solver needs
|
|
172
|
+
smooth derivatives.
|
|
173
|
+
|
|
174
|
+
Full guide with runnable examples for all of it:
|
|
175
|
+
[USAGE.md](https://github.com/Shmuel-Gilbaum/Rosseland-mean-Opacity-Tables/blob/main/USAGE.md).
|
|
176
|
+
|
|
177
|
+
## Limits
|
|
178
|
+
|
|
179
|
+
- **Resolution.** Semenov's dust destruction spans 192 K, which is two and a
|
|
180
|
+
half cells at the default grid, so the tabulated cliff is gentler than the
|
|
181
|
+
model's own. Two tables built at different resolutions are not comparable.
|
|
182
|
+
- **Semenov's density floor.** The evaporation temperatures that set where
|
|
183
|
+
dust survives are tabulated from 1e-18 g/cm^3 up. The cold table's lowest
|
|
184
|
+
density column falls below that under 464 K, where the evaporation
|
|
185
|
+
temperature is a linear extrapolation of the first tabulated interval.
|
|
186
|
+
- **OPAL's blank corners.** The published tables stop short in the cool dilute
|
|
187
|
+
corner and the hot dense one, and the nearest tabulated value is held across
|
|
188
|
+
them. At solar composition the blanks begin at 15.8 million K, above the
|
|
189
|
+
default ceiling of 12.6 million K.
|
|
190
|
+
- **A temperature no source reaches.** The call raises rather than holding.
|
|
191
|
+
Holding across a temperature edge would return a dust opacity for an ionised
|
|
192
|
+
gas.
|
|
193
|
+
- **The compiled routines.** They are cached next to the installed package.
|
|
194
|
+
Where that location is not writable they recompile each session, about 1.3 s,
|
|
195
|
+
and `NUMBA_CACHE_DIR` points them somewhere writable.
|
|
196
|
+
|
|
197
|
+
## Licence
|
|
198
|
+
|
|
199
|
+
This package is MIT licensed. See `LICENSE`.
|
|
200
|
+
|
|
201
|
+
The data it redistributes carries its own terms.
|
|
202
|
+
|
|
203
|
+
Semenov's source grants free use, modification and redistribution, quoted at the
|
|
204
|
+
top of `rm_tables/sources/_semenov_fit.py` with its copyright line.
|
|
205
|
+
|
|
206
|
+
No licence statement was found for the OPAL data. It is distributed publicly and
|
|
207
|
+
without registration, and this package redistributes its Type-1 tables. Anyone
|
|
208
|
+
republishing that data should confirm the terms independently.
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
# Rosseland mean Opacity Tables
|
|
2
|
+
|
|
3
|
+
Rosseland mean opacity from published data, at a requested composition, as a
|
|
4
|
+
callable or as a built table. The default covers temperatures from 5 K to 12.6
|
|
5
|
+
million K and densities from 1e-24 to 2e4 g/cm^3. At the cold end the opacity
|
|
6
|
+
comes from dust grains, at the hot end from ionised gas.
|
|
7
|
+
|
|
8
|
+
Semenov et al. 2003 and Ferguson et al. 2005 tabulate dust and molecular gas at
|
|
9
|
+
the cold end. OPAL tabulates the ionised gas from 5623 K up. The three sit on
|
|
10
|
+
different grids and at different compositions, and the two cold ones disagree
|
|
11
|
+
about the temperature at which grains survive.
|
|
12
|
+
|
|
13
|
+
This package reads them, interpolates in hydrogen and metal mass fraction, and
|
|
14
|
+
joins a cold source to OPAL across the temperature range where both hold
|
|
15
|
+
values. Nothing is refitted. A request outside their coverage raises an error
|
|
16
|
+
naming the corner and the source that would answer it.
|
|
17
|
+
|
|
18
|
+
The data ships inside the package, so nothing is downloaded at run time.
|
|
19
|
+
|
|
20
|
+
## The data
|
|
21
|
+
|
|
22
|
+
| source | reference | range | supplies |
|
|
23
|
+
| --- | --- | --- | --- |
|
|
24
|
+
| OPAL | Iglesias & Rogers 1996, ApJ 464, 943 | 5623 K to 5e8 K | ionised gas |
|
|
25
|
+
| Semenov | Semenov et al. 2003, A&A 410, 611 | 5 K to 10,000 K | dust and molecular gas |
|
|
26
|
+
| Ferguson | Ferguson et al. 2005, ApJ 623, 585 | 501 K to 31,600 K | dust and molecular gas |
|
|
27
|
+
|
|
28
|
+
The caller chooses one of Semenov or Ferguson for the cold end.
|
|
29
|
+
|
|
30
|
+
**OPAL** ships as all 77 published Type-1 files, 6766 tables between them, on a
|
|
31
|
+
grid of hydrogen and metal mass fraction. The default is `GN93hz`, at Grevesse
|
|
32
|
+
& Noels 1993 metal ratios. Obtained from Arnold Boothroyd's public mirror at
|
|
33
|
+
the Canadian Institute for Theoretical Astrophysics.
|
|
34
|
+
|
|
35
|
+
**Semenov** ships as a Python translation of the published `opacity.f`, dust
|
|
36
|
+
model `nrm/h/s`: normal iron content, homogeneous, spherical. Its dust opacity
|
|
37
|
+
is a fifth-degree polynomial per temperature region, so no Fortran compiler is
|
|
38
|
+
involved. The translation matches the compiled original to 1.776e-05 relative,
|
|
39
|
+
which is that program's own printed precision. Its gas table ships unchanged.
|
|
40
|
+
|
|
41
|
+
Any result that uses these tables should cite the papers above.
|
|
42
|
+
|
|
43
|
+
## Install
|
|
44
|
+
|
|
45
|
+
pip install rm-tables
|
|
46
|
+
|
|
47
|
+
Requires NumPy and Numba. `h5py` is needed only to read and write HDF5 files.
|
|
48
|
+
|
|
49
|
+
## Usage
|
|
50
|
+
|
|
51
|
+
A temperature in K and a density in g/cm^3 give an opacity in cm^2/g. Every
|
|
52
|
+
argument below is optional and is written at its default, so `rm_tables.opacity()`
|
|
53
|
+
is the same call.
|
|
54
|
+
|
|
55
|
+
```python
|
|
56
|
+
import numpy as np
|
|
57
|
+
import rm_tables
|
|
58
|
+
|
|
59
|
+
kappa = rm_tables.opacity(X=0.7381, Z=0.0134, cold="semenov",
|
|
60
|
+
dataset="GN93hz", dXc=0.0, dXo=0.0)
|
|
61
|
+
print(kappa(3000.0, 1e-14)) # -> 6.635618312601376e-05
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
`X` and `Z` are the hydrogen and metal mass fractions and helium is the
|
|
65
|
+
remainder, so `X + Z` cannot exceed 1. `cold` picks the cold source, `dataset`
|
|
66
|
+
picks which of OPAL's 77 published files supplies the hot end, and `dXc` and
|
|
67
|
+
`dXo` add carbon and oxygen beyond what `Z` carries.
|
|
68
|
+
|
|
69
|
+
A composition outside what the chosen set tabulates raises rather than
|
|
70
|
+
extrapolating.
|
|
71
|
+
|
|
72
|
+
```python
|
|
73
|
+
try:
|
|
74
|
+
rm_tables.opacity(X=0.0, Z=0.5)
|
|
75
|
+
except ValueError as e:
|
|
76
|
+
print(e) # -> set 'GN93hz' tabulates metals up to 0.1, and Z=0.5 was ...
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
Arrays broadcast against each other and the result takes the broadcast shape.
|
|
80
|
+
|
|
81
|
+
```python
|
|
82
|
+
T = np.array([500.0, 3000.0, 1e5])
|
|
83
|
+
rho = np.array([1.25e-19, 1e-14, 1e-16])
|
|
84
|
+
print(kappa(T, rho)) # -> [1.7535...e+00 6.6356...e-05 4.4602...e-01]
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
A compiled solver cannot call the object, because numba refuses a Python
|
|
88
|
+
object holding Python arrays. `compiled` returns the same opacity as a numba
|
|
89
|
+
function, at 157 ns a point.
|
|
90
|
+
|
|
91
|
+
```python
|
|
92
|
+
from numba import njit
|
|
93
|
+
|
|
94
|
+
fast = rm_tables.opacity().compiled()
|
|
95
|
+
|
|
96
|
+
@njit
|
|
97
|
+
def optical_depth(T, rho, height):
|
|
98
|
+
return fast(T, rho) * rho * height
|
|
99
|
+
|
|
100
|
+
print(optical_depth(3000.0, 1e-14, 1e13)) # -> 6.6356...e-06
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
`build` returns tabulated grids instead, for fitting an interpolant or writing
|
|
104
|
+
a file. `cold` carries the cold source ramped into OPAL. `hot` carries OPAL
|
|
105
|
+
alone and reaches a higher density.
|
|
106
|
+
|
|
107
|
+
```python
|
|
108
|
+
t = rm_tables.build(X=0.7381, Z=0.0134)
|
|
109
|
+
print(t.cold.shape, t.hot.shape) # -> (200, 500) (200, 500)
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
`build` takes the same six arguments and seven more, all optional, for the
|
|
113
|
+
range, the resolution and how the pair is split. The ranges are in `log10`, and
|
|
114
|
+
`log10 R` is `rho / (T / 1e6)**3` in g/cm^3.
|
|
115
|
+
|
|
116
|
+
```python
|
|
117
|
+
t2 = rm_tables.build(log_T_range=(2.0, 6.0), log_R_range=(-8.0, -2.0),
|
|
118
|
+
n_T=300, n_R=400)
|
|
119
|
+
print(t2.cold.shape, t2.cold_log_T[0], t2.cold_log_R[-1]) # -> (300, 400) 2.0 -2.0
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
`rm_tables.defaults` holds the value each argument falls back to, with the
|
|
123
|
+
measurement that set it.
|
|
124
|
+
|
|
125
|
+
## The rest of the interface
|
|
126
|
+
|
|
127
|
+
- **Composition.** Hydrogen and metals are arguments and helium is the
|
|
128
|
+
remainder. Metallicity scales the dust exactly and leaves the gas alone.
|
|
129
|
+
- **The cold source.** Semenov tabulates where grains evaporate, Ferguson
|
|
130
|
+
where they condense. Heating material suits Semenov, cooling material suits
|
|
131
|
+
Ferguson.
|
|
132
|
+
- **The metal mixture.** All 77 OPAL sets are selectable, and so are the
|
|
133
|
+
carbon and oxygen enhanced grids inside them.
|
|
134
|
+
- **Range and resolution.** Both are arguments, and every table records what
|
|
135
|
+
it was built at.
|
|
136
|
+
- **Saving.** Compressed NumPy, plain text or HDF5, chosen by the file
|
|
137
|
+
extension, each carrying the provenance beside the numbers.
|
|
138
|
+
- **Compiled code.** `opacity(...).compiled()` is callable from inside numba,
|
|
139
|
+
and a fitted spline over a built table is the route where the solver needs
|
|
140
|
+
smooth derivatives.
|
|
141
|
+
|
|
142
|
+
Full guide with runnable examples for all of it:
|
|
143
|
+
[USAGE.md](https://github.com/Shmuel-Gilbaum/Rosseland-mean-Opacity-Tables/blob/main/USAGE.md).
|
|
144
|
+
|
|
145
|
+
## Limits
|
|
146
|
+
|
|
147
|
+
- **Resolution.** Semenov's dust destruction spans 192 K, which is two and a
|
|
148
|
+
half cells at the default grid, so the tabulated cliff is gentler than the
|
|
149
|
+
model's own. Two tables built at different resolutions are not comparable.
|
|
150
|
+
- **Semenov's density floor.** The evaporation temperatures that set where
|
|
151
|
+
dust survives are tabulated from 1e-18 g/cm^3 up. The cold table's lowest
|
|
152
|
+
density column falls below that under 464 K, where the evaporation
|
|
153
|
+
temperature is a linear extrapolation of the first tabulated interval.
|
|
154
|
+
- **OPAL's blank corners.** The published tables stop short in the cool dilute
|
|
155
|
+
corner and the hot dense one, and the nearest tabulated value is held across
|
|
156
|
+
them. At solar composition the blanks begin at 15.8 million K, above the
|
|
157
|
+
default ceiling of 12.6 million K.
|
|
158
|
+
- **A temperature no source reaches.** The call raises rather than holding.
|
|
159
|
+
Holding across a temperature edge would return a dust opacity for an ionised
|
|
160
|
+
gas.
|
|
161
|
+
- **The compiled routines.** They are cached next to the installed package.
|
|
162
|
+
Where that location is not writable they recompile each session, about 1.3 s,
|
|
163
|
+
and `NUMBA_CACHE_DIR` points them somewhere writable.
|
|
164
|
+
|
|
165
|
+
## Licence
|
|
166
|
+
|
|
167
|
+
This package is MIT licensed. See `LICENSE`.
|
|
168
|
+
|
|
169
|
+
The data it redistributes carries its own terms.
|
|
170
|
+
|
|
171
|
+
Semenov's source grants free use, modification and redistribution, quoted at the
|
|
172
|
+
top of `rm_tables/sources/_semenov_fit.py` with its copyright line.
|
|
173
|
+
|
|
174
|
+
No licence statement was found for the OPAL data. It is distributed publicly and
|
|
175
|
+
without registration, and this package redistributes its Type-1 tables. Anyone
|
|
176
|
+
republishing that data should confirm the terms independently.
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=77"] # 77 is where license = "MIT" became valid
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "rm-tables"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "Rosseland mean opacity tables for gas and dust, at any composition"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
license = "MIT"
|
|
11
|
+
license-files = ["LICENSE"]
|
|
12
|
+
requires-python = ">=3.10"
|
|
13
|
+
dependencies = ["numpy>=1.22", "numba>=0.57"]
|
|
14
|
+
authors = [{name = "Shmuel Gilbaum"}]
|
|
15
|
+
keywords = ["opacity", "Rosseland mean", "OPAL", "Semenov", "Ferguson",
|
|
16
|
+
"dust", "radiative transfer", "accretion disk", "accretion disc",
|
|
17
|
+
"protoplanetary disk", "protoplanetary disc", "stellar interior",
|
|
18
|
+
"astrophysics"]
|
|
19
|
+
classifiers = [
|
|
20
|
+
"Development Status :: 4 - Beta",
|
|
21
|
+
"Intended Audience :: Science/Research",
|
|
22
|
+
"Topic :: Scientific/Engineering :: Astronomy",
|
|
23
|
+
"Topic :: Scientific/Engineering :: Physics",
|
|
24
|
+
"Operating System :: OS Independent",
|
|
25
|
+
"Programming Language :: Python :: 3",
|
|
26
|
+
"Programming Language :: Python :: 3.10",
|
|
27
|
+
"Programming Language :: Python :: 3.11",
|
|
28
|
+
"Programming Language :: Python :: 3.12",
|
|
29
|
+
"Programming Language :: Python :: 3.13",
|
|
30
|
+
]
|
|
31
|
+
|
|
32
|
+
[project.urls]
|
|
33
|
+
Homepage = "https://github.com/Shmuel-Gilbaum/Rosseland-mean-Opacity-Tables"
|
|
34
|
+
Repository = "https://github.com/Shmuel-Gilbaum/Rosseland-mean-Opacity-Tables"
|
|
35
|
+
Usage = "https://github.com/Shmuel-Gilbaum/Rosseland-mean-Opacity-Tables/blob/main/USAGE.md"
|
|
36
|
+
|
|
37
|
+
[project.optional-dependencies]
|
|
38
|
+
hdf5 = ["h5py>=3"]
|
|
39
|
+
test = ["pytest>=7", "h5py>=3"]
|
|
40
|
+
|
|
41
|
+
[tool.setuptools.packages.find]
|
|
42
|
+
include = ["rm_tables*"]
|
|
43
|
+
|
|
44
|
+
[tool.setuptools.package-data]
|
|
45
|
+
rm_tables = ["data/*.npz", "data/*.dat"]
|
|
46
|
+
|
|
47
|
+
[tool.pytest.ini_options]
|
|
48
|
+
testpaths = ["tests", "rm_tables"]
|
|
49
|
+
addopts = "--doctest-modules"
|
|
50
|
+
# Lets an example show the call a reader would write and elide the trailing
|
|
51
|
+
# digits, which vary by platform and carry no meaning.
|
|
52
|
+
doctest_optionflags = "ELLIPSIS NORMALIZE_WHITESPACE"
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"""Rosseland mean opacity for gas and dust, at any composition.
|
|
2
|
+
|
|
3
|
+
Two ways in. `opacity` returns a callable and builds no table: it evaluates the
|
|
4
|
+
sources at the point requested. `build` returns a tabulated grid for anyone who
|
|
5
|
+
wants to fit their own interpolant or write the result to a file.
|
|
6
|
+
|
|
7
|
+
Sources are used as their authors published them. OPAL supplies the ionised gas
|
|
8
|
+
above 5623 K; either Semenov 2003 or Ferguson 2005 supplies dust and molecules
|
|
9
|
+
below. The two cold sources are alternatives and are never combined; the README
|
|
10
|
+
says which to choose. Both entry points take a `dataset` naming the OPAL file,
|
|
11
|
+
which sets the metal mixture, and the excess carbon and oxygen that file
|
|
12
|
+
tabulates.
|
|
13
|
+
|
|
14
|
+
`build` raises `rm_tables.coverage.CoverageError` for a range the chosen sources
|
|
15
|
+
do not hold. A callable from `opacity` raises it for a temperature no source
|
|
16
|
+
reaches, and holds the nearest value it has in density. `CoverageError`
|
|
17
|
+
subclasses `ValueError`.
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
from . import coverage, defaults
|
|
21
|
+
from .lookup import opacity
|
|
22
|
+
from .tables import build, load
|
|
23
|
+
|
|
24
|
+
__all__ = ["opacity", "build", "load"]
|
|
25
|
+
__version__ = "0.1.0"
|