crimsons 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.
Files changed (87) hide show
  1. crimsons-0.1.0/.github/workflows/ci.yml +22 -0
  2. crimsons-0.1.0/.gitignore +18 -0
  3. crimsons-0.1.0/.readthedocs.yml +22 -0
  4. crimsons-0.1.0/CITATION.cff +11 -0
  5. crimsons-0.1.0/LICENSE +21 -0
  6. crimsons-0.1.0/PKG-INFO +86 -0
  7. crimsons-0.1.0/README.md +52 -0
  8. crimsons-0.1.0/TODO.md +25 -0
  9. crimsons-0.1.0/docs/api/core.md +25 -0
  10. crimsons-0.1.0/docs/api/enrichment.md +12 -0
  11. crimsons-0.1.0/docs/api/imf.md +31 -0
  12. crimsons-0.1.0/docs/api/index.md +40 -0
  13. crimsons-0.1.0/docs/api/io.md +14 -0
  14. crimsons-0.1.0/docs/api/simulation.md +10 -0
  15. crimsons-0.1.0/docs/api/stars.md +9 -0
  16. crimsons-0.1.0/docs/api/yields.md +25 -0
  17. crimsons-0.1.0/docs/assets/logo.png +0 -0
  18. crimsons-0.1.0/docs/changelog.md +20 -0
  19. crimsons-0.1.0/docs/contributing.md +10 -0
  20. crimsons-0.1.0/docs/customize/channels.md +141 -0
  21. crimsons-0.1.0/docs/customize/imf.md +75 -0
  22. crimsons-0.1.0/docs/customize/index.md +60 -0
  23. crimsons-0.1.0/docs/customize/lifetimes.md +83 -0
  24. crimsons-0.1.0/docs/customize/metallicity.md +93 -0
  25. crimsons-0.1.0/docs/customize/sampling.md +78 -0
  26. crimsons-0.1.0/docs/examples/basic-simulation.md +82 -0
  27. crimsons-0.1.0/docs/examples/caching-results.md +69 -0
  28. crimsons-0.1.0/docs/examples/custom-imf.md +129 -0
  29. crimsons-0.1.0/docs/examples/output-interaction.md +178 -0
  30. crimsons-0.1.0/docs/examples/yield-models.md +187 -0
  31. crimsons-0.1.0/docs/getting-started/installation.md +41 -0
  32. crimsons-0.1.0/docs/getting-started/quickstart.md +119 -0
  33. crimsons-0.1.0/docs/index.md +76 -0
  34. crimsons-0.1.0/docs/javascripts/mathjax.js +19 -0
  35. crimsons-0.1.0/docs/requirements.txt +10 -0
  36. crimsons-0.1.0/docs/stylesheets/extra.css +26 -0
  37. crimsons-0.1.0/example/Examplees_BasicSimulation.py +39 -0
  38. crimsons-0.1.0/example/Ltest.py +81 -0
  39. crimsons-0.1.0/example/QuickStart_full_example.py +18 -0
  40. crimsons-0.1.0/example/SNIa_inspection.py +116 -0
  41. crimsons-0.1.0/example/cfe_vs_feh.png +0 -0
  42. crimsons-0.1.0/example/channels_comparison.py +103 -0
  43. crimsons-0.1.0/example/data_access.py +142 -0
  44. crimsons-0.1.0/example/events_inspection.py +120 -0
  45. crimsons-0.1.0/example/imf_comparison.py +69 -0
  46. crimsons-0.1.0/example/lifetime_comparison.py +52 -0
  47. crimsons-0.1.0/example/quickStart.py +157 -0
  48. crimsons-0.1.0/mkdocs.yml +177 -0
  49. crimsons-0.1.0/pyproject.toml +67 -0
  50. crimsons-0.1.0/scripts/generate_placeholder_data.py +62 -0
  51. crimsons-0.1.0/src/crimsons/__init__.py +50 -0
  52. crimsons-0.1.0/src/crimsons/chemistry.py +274 -0
  53. crimsons-0.1.0/src/crimsons/config.py +34 -0
  54. crimsons-0.1.0/src/crimsons/data/solar_abundances_asplund2009.csv +45 -0
  55. crimsons-0.1.0/src/crimsons/enrichment/__init__.py +0 -0
  56. crimsons-0.1.0/src/crimsons/enrichment/engine.py +207 -0
  57. crimsons-0.1.0/src/crimsons/imf/__init__.py +0 -0
  58. crimsons-0.1.0/src/crimsons/imf/base.py +121 -0
  59. crimsons-0.1.0/src/crimsons/imf/defaults.py +37 -0
  60. crimsons-0.1.0/src/crimsons/imf/functional.py +118 -0
  61. crimsons-0.1.0/src/crimsons/imf/mass_range.py +32 -0
  62. crimsons-0.1.0/src/crimsons/imf/standard.py +229 -0
  63. crimsons-0.1.0/src/crimsons/io/__init__.py +0 -0
  64. crimsons-0.1.0/src/crimsons/io/cache.py +21 -0
  65. crimsons-0.1.0/src/crimsons/io/hdf5.py +96 -0
  66. crimsons-0.1.0/src/crimsons/results.py +354 -0
  67. crimsons-0.1.0/src/crimsons/simulation/__init__.py +0 -0
  68. crimsons-0.1.0/src/crimsons/simulation/ensemble.py +349 -0
  69. crimsons-0.1.0/src/crimsons/stars/__init__.py +0 -0
  70. crimsons-0.1.0/src/crimsons/stars/lifetimes.py +101 -0
  71. crimsons-0.1.0/src/crimsons/yields/__init__.py +0 -0
  72. crimsons-0.1.0/src/crimsons/yields/base.py +325 -0
  73. crimsons-0.1.0/src/crimsons/yields/channels.py +443 -0
  74. crimsons-0.1.0/src/crimsons/yields/data/stellar_yields.h5 +0 -0
  75. crimsons-0.1.0/src/crimsons/yields/io.py +270 -0
  76. crimsons-0.1.0/src/crimsons/yields/manifest.yaml +20 -0
  77. crimsons-0.1.0/tests/integration/test_simulation_roundtrip.py +106 -0
  78. crimsons-0.1.0/tests/unit/test_chemical_indexing.py +727 -0
  79. crimsons-0.1.0/tests/unit/test_engine.py +136 -0
  80. crimsons-0.1.0/tests/unit/test_functional_imf.py +61 -0
  81. crimsons-0.1.0/tests/unit/test_imf.py +34 -0
  82. crimsons-0.1.0/tests/unit/test_lifetimes.py +26 -0
  83. crimsons-0.1.0/tests/unit/test_mass_range.py +56 -0
  84. crimsons-0.1.0/tests/unit/test_parallelization.py +255 -0
  85. crimsons-0.1.0/tests/unit/test_snia.py +189 -0
  86. crimsons-0.1.0/tests/unit/test_tqdm.py +32 -0
  87. crimsons-0.1.0/tests/unit/test_yields_hdf5.py +209 -0
@@ -0,0 +1,22 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+
8
+ jobs:
9
+ test:
10
+ runs-on: ${{ matrix.os }}
11
+ strategy:
12
+ matrix:
13
+ os: [ubuntu-latest, macos-latest, windows-latest]
14
+ python-version: ["3.10", "3.11", "3.12", "3.13"]
15
+ steps:
16
+ - uses: actions/checkout@v4
17
+ - uses: actions/setup-python@v5
18
+ with:
19
+ python-version: ${{ matrix.python-version }}
20
+ - run: pip install -e ".[dev]"
21
+ - run: pytest -q
22
+ - run: ruff check src tests
@@ -0,0 +1,18 @@
1
+ __pycache__/
2
+ *.py[cod]
3
+ *.egg-info/
4
+ .eggs/
5
+ build/
6
+ dist/
7
+ .pytest_cache/
8
+ .ruff_cache/
9
+ .venv/
10
+ venv/
11
+
12
+ yields_data/
13
+
14
+ # example/run artifacts
15
+ /cache/
16
+ *.h5
17
+ *.csv
18
+ !tests/**/*.h5
@@ -0,0 +1,22 @@
1
+ version: 2
2
+
3
+ build:
4
+ os: ubuntu-22.04
5
+ tools:
6
+ python: "3.11"
7
+
8
+ python:
9
+ install:
10
+ # Doc-build dependencies (mkdocs-material, mkdocstrings, ...)
11
+ - requirements: docs/requirements.txt
12
+ # The package itself, so mkdocstrings can import `crimsons` and pull
13
+ # live docstrings/signatures for the API reference. Adjust the path
14
+ # if your pyproject.toml / setup.py lives somewhere other than the
15
+ # repository root.
16
+ - method: pip
17
+ path: .
18
+ extra_requirements:
19
+ - docs
20
+
21
+ mkdocs:
22
+ configuration: mkdocs.yml
@@ -0,0 +1,11 @@
1
+ cff-version: 1.2.0
2
+ message: "If you use this software, please cite it as below."
3
+ title: "crimsons: stochastic chemical enrichment of stellar populations"
4
+ version: 0.1.0
5
+ date-released: 2026-07-31
6
+ authors:
7
+ - family-names: "Your Last Name"
8
+ given-names: "Your First Name"
9
+ affiliation: "Your Institution"
10
+ repository-code: "https://github.com/yourusername/crimsons"
11
+ license: MIT
crimsons-0.1.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Lapo Querci
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.
@@ -0,0 +1,86 @@
1
+ Metadata-Version: 2.5
2
+ Name: crimsons
3
+ Version: 0.1.0
4
+ Summary: Stochastic chemical enrichment of stellar populations (SNII, SNIa, AGB) from a sampled IMF.
5
+ Project-URL: Homepage, https://github.com/lquerci/crimsons
6
+ Project-URL: Issues, https://github.com/lquerci/crimsons/issues
7
+ Author-email: Lapo Querci <lapo.querci@unifi.it>
8
+ License: MIT
9
+ License-File: LICENSE
10
+ Classifier: Intended Audience :: Science/Research
11
+ Classifier: License :: OSI Approved :: MIT License
12
+ Classifier: Operating System :: OS Independent
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Topic :: Scientific/Engineering :: Astronomy
15
+ Requires-Python: >=3.10
16
+ Requires-Dist: h5py>=3.8
17
+ Requires-Dist: numpy>=1.24
18
+ Requires-Dist: scipy>=1.10
19
+ Requires-Dist: tqdm>=4.70
20
+ Provides-Extra: dev
21
+ Requires-Dist: pytest>=7.0; extra == 'dev'
22
+ Requires-Dist: ruff; extra == 'dev'
23
+ Provides-Extra: docs
24
+ Requires-Dist: mkdocs-git-revision-date-localized-plugin>=1.2; extra == 'docs'
25
+ Requires-Dist: mkdocs-material>=9.5; extra == 'docs'
26
+ Requires-Dist: mkdocs>=1.5; extra == 'docs'
27
+ Requires-Dist: mkdocstrings[python]>=0.24; extra == 'docs'
28
+ Requires-Dist: pymdown-extensions>=10.9; extra == 'docs'
29
+ Provides-Extra: parallel
30
+ Requires-Dist: joblib; extra == 'parallel'
31
+ Provides-Extra: plot
32
+ Requires-Dist: matplotlib; extra == 'plot'
33
+ Description-Content-Type: text/markdown
34
+
35
+ # CRIMSONS
36
+
37
+ Chemical evolution with the Random sampling of the Initial Mass function: Studying the Origin of Nucleosynthetic Stellar products
38
+
39
+ This python package performs the stochastic chemical-enrichment simulations of stellar populations: sample
40
+ an initial mass function, evolve it through core-collapse supernovae, AGB
41
+ winds, Type Ia supernovae and (optionally) pair-instability supernovae,
42
+ and get back the time-resolved abundances of 30 elements released to the
43
+ interstellar medium.
44
+
45
+ > **Status:** first public version
46
+
47
+ ## Install
48
+
49
+ ```bash
50
+ pip install crimsons
51
+ ```
52
+
53
+ or from source
54
+
55
+ ```bash
56
+ git clone https://github.com/lquerci/crimsons.git
57
+ cd crimsons
58
+ pip install .
59
+ ```
60
+
61
+
62
+ ## Quickstart
63
+
64
+ ```python
65
+ from crimsons import Kroupa2001, Simulation
66
+
67
+ sim = Simulation(
68
+ imf=Kroupa2001(),
69
+ mass_formed=1e6,
70
+ metallicity=0.0142,
71
+ n_realizations=20,
72
+ seed=42,
73
+ )
74
+ result = sim.run()
75
+ mean_fe = result["Fe"].mean()
76
+ ```
77
+
78
+ ## Documentation
79
+
80
+ Full documentation -- installation, examples, the physics behind each
81
+ piece, and the complete API reference -- lives at
82
+ `https://crimsons.readthedocs.io`.
83
+
84
+ ## License
85
+
86
+ MIT -- see [LICENSE](LICENSE).
@@ -0,0 +1,52 @@
1
+ # CRIMSONS
2
+
3
+ Chemical evolution with the Random sampling of the Initial Mass function: Studying the Origin of Nucleosynthetic Stellar products
4
+
5
+ This python package performs the stochastic chemical-enrichment simulations of stellar populations: sample
6
+ an initial mass function, evolve it through core-collapse supernovae, AGB
7
+ winds, Type Ia supernovae and (optionally) pair-instability supernovae,
8
+ and get back the time-resolved abundances of 30 elements released to the
9
+ interstellar medium.
10
+
11
+ > **Status:** first public version
12
+
13
+ ## Install
14
+
15
+ ```bash
16
+ pip install crimsons
17
+ ```
18
+
19
+ or from source
20
+
21
+ ```bash
22
+ git clone https://github.com/lquerci/crimsons.git
23
+ cd crimsons
24
+ pip install .
25
+ ```
26
+
27
+
28
+ ## Quickstart
29
+
30
+ ```python
31
+ from crimsons import Kroupa2001, Simulation
32
+
33
+ sim = Simulation(
34
+ imf=Kroupa2001(),
35
+ mass_formed=1e6,
36
+ metallicity=0.0142,
37
+ n_realizations=20,
38
+ seed=42,
39
+ )
40
+ result = sim.run()
41
+ mean_fe = result["Fe"].mean()
42
+ ```
43
+
44
+ ## Documentation
45
+
46
+ Full documentation -- installation, examples, the physics behind each
47
+ piece, and the complete API reference -- lives at
48
+ `https://crimsons.readthedocs.io`.
49
+
50
+ ## License
51
+
52
+ MIT -- see [LICENSE](LICENSE).
crimsons-0.1.0/TODO.md ADDED
@@ -0,0 +1,25 @@
1
+ # Project
2
+
3
+ Project Description
4
+
5
+ <em>[TODO.md spec & Kanban Board](https://bit.ly/3fCwKfM)</em>
6
+
7
+ ### Todo
8
+
9
+ - [ ] README.md
10
+ - [ ] publish on PyPi
11
+ - [ ] Check all function comments
12
+ - [ ] Add IMF weighted chem enrich
13
+ - [ ] Check SNIa model
14
+
15
+ ### In Progress
16
+
17
+ - [ ] Finish documentation
18
+
19
+ ### Done ✓
20
+
21
+ - [x] divide explosion energy in the output
22
+ - [x] Fiducial model as default
23
+ - [x] Parallelize
24
+ - [x] Add logic to switch to rolled enrichemnt and not rolled
25
+
@@ -0,0 +1,25 @@
1
+ # Results & Config (`crimsons.results`, `crimsons.config`, `crimsons.chemistry`)
2
+
3
+ The data returned by a run (`EnrichmentResult`), the configuration that
4
+ produced it (`RunConfig`, also the basis for cache keys -- see
5
+ [Caching & Persistence](../examples/caching-results.md)), and the
6
+ tracked-element / solar-metallicity constants shared across the package.
7
+
8
+ ## Results
9
+
10
+ ::: crimsons.results
11
+ options:
12
+ members_order: source
13
+
14
+ ## Run configuration
15
+
16
+ ::: crimsons.config
17
+ options:
18
+ members_order: source
19
+
20
+ ## Chemistry constants
21
+
22
+ ::: crimsons.chemistry
23
+ options:
24
+ members_order: source
25
+ show_source: true
@@ -0,0 +1,12 @@
1
+ # Enrichment Engine (`crimsons.enrichment`)
2
+
3
+ The per-realization loop `Simulation.run()` calls once per realization:
4
+ sample the IMF into log-mass bins, route each bin (or the population as a
5
+ whole, for `SNIa`) through the configured channels, and bin the resulting
6
+ events onto a shared time grid. See
7
+ [Stochastic Sampling](../customize/sampling.md) for the binned Monte Carlo
8
+ approach this implements.
9
+
10
+ ::: crimsons.enrichment.engine
11
+ options:
12
+ members_order: source
@@ -0,0 +1,31 @@
1
+ # Initial Mass Functions (`crimsons.imf`)
2
+
3
+ Base class, exact broken-power-law implementations, and a general
4
+ numerical implementation for arbitrary shapes. See
5
+ [Customize: Initial Mass Function](../customize/imf.md) for the underlying
6
+ model and [Custom IMF Shapes](../examples/custom-imf.md) for usage
7
+ examples.
8
+
9
+ ## Base class
10
+
11
+ ::: crimsons.imf.base
12
+ options:
13
+ members_order: source
14
+
15
+ ## Metallicity-adaptive default mass range
16
+
17
+ ::: crimsons.imf.mass_range
18
+ options:
19
+ members_order: source
20
+
21
+ ## Broken power laws (Salpeter, Kroupa, Flat)
22
+
23
+ ::: crimsons.imf.standard
24
+ options:
25
+ members_order: source
26
+
27
+ ## Arbitrary shapes
28
+
29
+ ::: crimsons.imf.functional
30
+ options:
31
+ members_order: source
@@ -0,0 +1,40 @@
1
+ # API Reference
2
+
3
+ This section is generated directly from docstrings in `src/crimsons` by
4
+ [mkdocstrings](https://mkdocstrings.github.io/) -- every page's "Source
5
+ code" toggle shows the real implementation alongside its documentation,
6
+ so it never drifts out of sync with what's actually shipped.
7
+
8
+ ## Package layout
9
+
10
+ | Page | Module(s) | Covers |
11
+ |---|---|---|
12
+ | [Simulation](simulation.md) | `crimsons.simulation.ensemble` | The `Simulation` class -- ties everything below together into an ensemble run. |
13
+ | [Initial Mass Functions](imf.md) | `crimsons.imf.*` | `IMF` base class, `Salpeter1955`/`Kroupa2001`/`FlatIMF`/`BrokenPowerLawIMF`, `FunctionalIMF`, and the metallicity-adaptive mass-range policy. |
14
+ | [Stellar Lifetimes](stars.md) | `crimsons.stars.lifetimes` | `LifetimeFunction` base class and the bundled `StellarLifetime` model. |
15
+ | [Yields & Channels](yields.md) | `crimsons.yields.*` | `Channel`/`MassRangeChannel`/`PopulationChannel`, `YieldTable`/`StochasticYieldTable`, the bundled `SNII`/`AGB`/`PISN`/`SNIa` channels, and yield-table I/O. |
16
+ | [Enrichment Engine](enrichment.md) | `crimsons.enrichment.engine` | The per-realization sampling/enrichment loop `Simulation` drives. |
17
+ | [Results & Config](core.md) | `crimsons.results`, `crimsons.config`, `crimsons.chemistry` | `EnrichmentResult`, `RunConfig`, and the tracked-element/metallicity constants. |
18
+ | [I/O & Caching](io.md) | `crimsons.io.*` | HDF5 read/write for `EnrichmentResult`, and the config-hash-based run cache. |
19
+
20
+ ## Top-level imports
21
+
22
+ Everything most users need is re-exported from the `crimsons` package
23
+ itself:
24
+
25
+ ```python
26
+ from crimsons import (
27
+ AGB, PISN, SNII, SNIa, # channels
28
+ ELEMENTS, ZSUN, # constants
29
+ EnrichmentResult,
30
+ FunctionalIMF, Kroupa2001, Salpeter1955, # IMFs
31
+ Simulation,
32
+ StellarLifetime,
33
+ default_channels, describe_available_model, list_available_models,
34
+ )
35
+ ```
36
+
37
+ `FlatIMF`, `BrokenPowerLawIMF`, and the individual `Channel`/`YieldTable`
38
+ base classes aren't re-exported at the top level -- import them from their
39
+ own submodule (e.g. `from crimsons.imf.standard import BrokenPowerLawIMF`)
40
+ when subclassing or introspecting directly.
@@ -0,0 +1,14 @@
1
+ # I/O & Caching (`crimsons.io`)
2
+
3
+ HDF5 serialization for `EnrichmentResult`, and the config-hash-based run
4
+ cache that `Simulation.run(cache_dir=...)` uses. See
5
+ [Caching & Persistence](../examples/caching-results.md) for usage
6
+ examples.
7
+
8
+ ::: crimsons.io.hdf5
9
+ options:
10
+ members_order: source
11
+
12
+ ::: crimsons.io.cache
13
+ options:
14
+ members_order: source
@@ -0,0 +1,10 @@
1
+ # Simulation (`crimsons.simulation`)
2
+
3
+ The top-level entry point: ties an IMF, a lifetime function, and a set of
4
+ channels together into an ensemble of Monte Carlo realizations. See
5
+ [Quickstart](../getting-started/quickstart.md) for a walkthrough and
6
+ [Physics Overview](../customize/index.md) for what happens inside `run()`.
7
+
8
+ ::: crimsons.simulation.ensemble
9
+ options:
10
+ members_order: source
@@ -0,0 +1,9 @@
1
+ # Stellar Lifetimes (`crimsons.stars`)
2
+
3
+ Maps stellar mass and metallicity to a main-sequence(-ish) lifetime in Myr.
4
+ See [Stellar Lifetimes](../customize/lifetimes.md) for the
5
+ underlying fits.
6
+
7
+ ::: crimsons.stars.lifetimes
8
+ options:
9
+ members_order: source
@@ -0,0 +1,25 @@
1
+ # Yields & Channels (`crimsons.yields`)
2
+
3
+ Yield-table data structures, the `Channel` interface, the bundled
4
+ SNII/AGB/PISN/SNIa channels, and HDF5/CSV table loading. See
5
+ [Enrichment Channels](../customize/channels.md) for the underlying
6
+ model and [Selecting Yield Models](../examples/yield-models.md) for usage
7
+ examples.
8
+
9
+ ## Channels & yield-table data structures
10
+
11
+ ::: crimsons.yields.base
12
+ options:
13
+ members_order: source
14
+
15
+ ## Bundled channels (SNII, AGB, PISN, SNIa)
16
+
17
+ ::: crimsons.yields.channels
18
+ options:
19
+ members_order: source
20
+
21
+ ## Loading yield tables
22
+
23
+ ::: crimsons.yields.io
24
+ options:
25
+ members_order: source
Binary file
@@ -0,0 +1,20 @@
1
+ # Changelog
2
+
3
+ All notable changes to CRIMSONS are documented here, following the spirit
4
+ of [Keep a Changelog](https://keepachangelog.com/en/1.1.0/){: target="_blank" } and
5
+ [Semantic Versioning](https://semver.org/){: target="_blank" }.
6
+
7
+ ## [0.1.0]
8
+
9
+ Initial development release.
10
+
11
+ - Core simulation loop (`Simulation`, `EnrichmentResult`, `RunConfig`).
12
+ - IMFs: `Salpeter1955`, `Kroupa2001`, `FlatIMF`, `FunctionalIMF`, `Chabrier2003`.
13
+ - Channels: `SNII`, `AGB`, `PISN`, `SNIa` (DTD and single-burst modes).
14
+ - `StellarLifetime` (Raiteri et al. 1996 / Schaerer et al. 2002).
15
+ - HDF5-backed yield-table loading with fixed and stochastic model
16
+ parameters.
17
+ - Result caching keyed on a hashed `RunConfig`.
18
+
19
+ [Unreleased]: https://github.com/your-org/crimsons/compare/v0.1.0...HEAD
20
+ [0.1.0]: https://github.com/your-org/crimsons/releases/tag/v0.1.0
@@ -0,0 +1,10 @@
1
+ # Contributing
2
+
3
+ All efforts to improve CRIMSONS are wellcomed. We ask any contributor to follow the simple four steps below:
4
+
5
+ 1. Fork and branch from `main`.
6
+ 2. Keep changes focused; add/update tests and docs alongside code changes.
7
+ 3. Make sure `pytest` and `mkdocs build --strict` both pass locally.
8
+ 4. Open a PR describing what changed and why.
9
+
10
+ For any questions, bugs or issue, please contact: lapo.querci1@unifi.it
@@ -0,0 +1,141 @@
1
+ # Enrichment Channels
2
+
3
+ A **channel** decides which stars enrich the ISM, when their enrichment
4
+ arrives, and how much of each element they release. CRIMSONS has two kinds:
5
+
6
+ - **`MassRangeChannel`** -- triggered purely by a star's initial mass;
7
+ enrichment arrives at the end of that star's life (`SNII`, `AGB`,
8
+ `PISN`).
9
+ - **`PopulationChannel`** -- driven by the population as a whole rather
10
+ than any single star's mass (`SNIa`, via a delay-time distribution).
11
+
12
+ `default_channels()` returns `SNII() + AGB() + SNIa()`. Add `PISN()`
13
+ yourself for Population III / extremely metal-poor runs.
14
+
15
+ ## What it is
16
+
17
+ ### Mass-triggered channels
18
+
19
+ | Channel | Default mass window | Physical picture |
20
+ |---|---|---|
21
+ | `AGB` | $2$–$8\,M_\odot$ | Low/intermediate-mass stars enriching via stellar winds; primary $s$-process and light elements (C, N, F). |
22
+ | `SNII` | $8$–$40\,M_\odot$ | Core-collapse supernovae; hydrostatic burning up to iron-group elements plus explosive nucleosynthesis. |
23
+ | `PISN` | $140$–$260\,M_\odot$ | Pair-instability supernovae: complete disruption, no compact remnant, of very massive, metal-free/extremely metal-poor stars. Effectively Population III only. |
24
+
25
+ A star contributes to a channel if its mass falls in `[mass_min,
26
+ mass_max]`; its delay time is simply its stellar lifetime (see
27
+ [Stellar Lifetimes](lifetimes.md)); and its yield comes from that
28
+ channel's yield table (see [Selecting Yield Models](../examples/yield-models.md)),
29
+ evaluated at its mass and the population's metallicity.
30
+
31
+ ### SN Ia: a delay-time distribution over the population
32
+
33
+ SN Ia doesn't select individual progenitor stars by mass -- it treats the
34
+ whole population's eventual SN Ia rate as a population-level statistic.
35
+ Explosions follow a delay-time distribution (DTD) which is normalized to
36
+ integrate to 1 over the run's `time_grid` and is scaled by `rate_per_msun`
37
+ (SN Ia per $M_\odot$ of stars formed) to give an absolute expected number
38
+ of explosions per time bin:
39
+
40
+ $$
41
+ \dot N_{\rm Ia}(t) \propto \Psi(\tau)
42
+ $$
43
+
44
+ Two shapes are available for $\Psi(\tau)$ ($\tau$ in Myr):
45
+
46
+ === "Maoz+12 (default)"
47
+
48
+ A power law, with support bounded below by `min_time`:
49
+
50
+ $$
51
+ \Psi(\tau) \propto \left(\frac{\tau}{\tau_{\min}}\right)^{-1.12}, \quad \tau > \tau_{\min}
52
+ $$
53
+
54
+ Default literature rate: `rate_per_msun = 0.0013`.
55
+
56
+ === "Mannucci+06 / Matteucci+06"
57
+
58
+ A double-Gaussian-in-log-time shape, split at $t_0 = 10^{7.93}\,\mathrm{yr}$
59
+ into a "prompt" and a "delayed" component:
60
+
61
+ $$
62
+ \log_{10}\Psi(\tau) =
63
+ \begin{cases}
64
+ 1.4 - 50\,(\log_{10}t + 7.7)^2 & t \le t_0 \\
65
+ -0.8 - 0.9\,(\log_{10}t - 8.7)^2 & t > t_0
66
+ \end{cases}
67
+ \quad (t = \tau\ \text{in yr})
68
+ $$
69
+
70
+ Default literature rate: `rate_per_msun = 0.0025`.
71
+
72
+ Either shape's support is bounded by the progenitor mass range's
73
+ (default $3$–$8\,M_\odot$) lifetimes: the most massive progenitor sets
74
+ $\tau_{\min}$, the least massive sets $\tau_{\max}$, both evaluated through
75
+ whichever `lifetime_fn` the `Simulation` uses. The (generally fractional)
76
+ expected explosion count per time bin is converted to an integer count via
77
+ **deterministic remainder carry-over** -- each bin's leftover fraction
78
+ rolls into the next bin's expected count -- rather than a random (e.g.
79
+ Poisson) draw.
80
+
81
+ !!! note "SN Ia is deterministic across realizations, by default"
82
+ Because neither the DTD shape, its normalization, nor the
83
+ integerization step involves the realization's random number
84
+ generator, every realization in an ensemble gets an **identical**
85
+ SN Ia contribution (same `mass_formed`, `metallicity`, and
86
+ `time_grid` in, same result out) -- unless you configure a yield
87
+ table with a stochastic model parameter (see
88
+ [Selecting Yield Models](../examples/yield-models.md)). The
89
+ realization-to-realization *scatter* you see in an
90
+ `EnrichmentResult` comes from the stochastic IMF sampling behind
91
+ `SNII`/`AGB`/`PISN`, not from `SNIa`.
92
+
93
+ ## Customizing
94
+
95
+ ### Changing a channel's mass window
96
+
97
+ The mass windows in the table above are constructor defaults, not
98
+ physical constants -- pass `mass_min=`/`mass_max=` to any of the three
99
+ mass-triggered channels to change the window (e.g. for a different
100
+ progenitor model or literature convention):
101
+
102
+ ```python
103
+ from crimsons import SNII
104
+
105
+ snii = SNII(mass_min=10.0, mass_max=25.0)
106
+ ```
107
+
108
+ ### Choosing SN Ia's shape and mode
109
+
110
+ `SNIa` supports `dtd_shape="maoz"` (default) or `dtd_shape="mannucci"`
111
+ for the two formulas above, plus a `mode="single_burst"` alternative --
112
+ the discretized limit of a delta-function DTD, where every eligible SN Ia
113
+ explodes at one fixed delay (`burst_delay_myr`) after formation instead of
114
+ following a distribution:
115
+
116
+ ```python
117
+ from crimsons import SNIa
118
+
119
+ snia = SNIa(dtd_shape="mannucci")
120
+ snia = SNIa(mode="single_burst", burst_delay_myr=1000.0, rate_per_msun=0.001)
121
+ ```
122
+
123
+ See [Selecting Yield Models](../examples/yield-models.md#sn-ia-delay-time-distribution-vs-single-burst)
124
+ for the additional parameter walkthrough.
125
+
126
+ ### Choosing a yield model
127
+
128
+ Each channel also takes `model=`/`model_params=` to select *which*
129
+ tabulated nucleosynthesis calculation it draws yields from (independent
130
+ of the mass window above) -- see
131
+ [Selecting Yield Models](../examples/yield-models.md) for the full
132
+ walkthrough, including stochastic (per-star) model parameters and
133
+ supplying your own yield tables entirely.
134
+
135
+ ### Writing your own channel
136
+
137
+ Subclass `MassRangeChannel` for another mass-triggered channel, or
138
+ `Channel`/`PopulationChannel` directly for something that doesn't fit
139
+ either existing pattern -- see
140
+ [`Channel`][crimsons.yields.base.Channel] in the API reference for the
141
+ methods a channel must implement.