From 7ee2e869959636d392dcdc169db80a1cb28f902e Mon Sep 17 00:00:00 2001 From: Tom Wagg Date: Sat, 30 May 2026 18:21:22 -0400 Subject: [PATCH 1/9] ensure files are only changes if content if different --- docs/create_settings_html.py | 16 +++++++-- docs/create_whats_new.py | 36 +++++++++++-------- docs/generate_default_bsedict.py | 61 +++++++++++++++++++------------- 3 files changed, 70 insertions(+), 43 deletions(-) diff --git a/docs/create_settings_html.py b/docs/create_settings_html.py index fba91f5bc..cd847e791 100644 --- a/docs/create_settings_html.py +++ b/docs/create_settings_html.py @@ -11,6 +11,7 @@ import json import pandas as pd from cosmic import __version__ as cosmic_version +from os.path import exists # how many versions in the past should we show as badges for when options were added? VERSION_CUTOFFS = { @@ -225,6 +226,15 @@ def version_is_recent(version_string): # append this group to the soup (guess who's a poet and didn't even know it) soup.select_one(".container-fluid").append(new_group) - # write the soup out to an HTML file for this category - with open(f"_generated/config_insert_{group['category']}.html", "w") as f: - f.write(str(soup)) + # write the soup out to an HTML file for this category (only if changed) + out_path = f"_generated/config_insert_{group['category']}.html" + content = str(soup) + if exists(out_path): + with open(out_path) as f: + if f.read() == content: + print(f" No changes to {out_path}, skipping write.") + continue + + print(f" Writing settings HTML for category '{group['category']}' to {out_path}...") + with open(out_path, "w") as f: + f.write(content) diff --git a/docs/create_whats_new.py b/docs/create_whats_new.py index 051afc213..76577c4ab 100644 --- a/docs/create_whats_new.py +++ b/docs/create_whats_new.py @@ -11,6 +11,7 @@ import re from pathlib import Path +from os.path import exists def parse_changelog(changelog_path): with open(changelog_path, 'r') as f: @@ -37,23 +38,30 @@ def parse_changelog(changelog_path): return parsed_sections def generate_rst(parsed_sections, output_path): - with open(output_path, 'w') as f: - f.write("What's New in COSMIC\n") - f.write("====================\n\n") + lines = ["What's New in COSMIC\n====================\n"] - for heading, features in parsed_sections: + for heading, features in parsed_sections: + lines.append(f"v{heading}\n{'-' * (len(heading) + 1)}\n") - f.write(f"v{heading}\n") - f.write(f"{'-' * (len(heading) + 1)}\n\n") + # Check if the heading is a version number (e.g., "4.1.0") + if re.match(r'^\d+\.\d+\.\d+$', heading): + github_link = f"https://github.com/COSMIC-PopSynth/COSMIC/releases/tag/v{heading}" + lines.append(f"`GitHub release <{github_link}>`_\n") - # Check if the heading is a version number (e.g., "4.1.0") - if re.match(r'^\d+\.\d+\.\d+$', heading): - github_link = f"https://github.com/COSMIC-PopSynth/COSMIC/releases/tag/v{heading}" - f.write(f"`GitHub release <{github_link}>`_\n\n") + for feature in features: + lines.append(feature) + lines.append("") - for feature in features: - f.write(feature + "\n") - f.write("\n") + content = "\n".join(lines) + if exists(output_path): + with open(output_path) as f: + if f.read() == content: + print(f" No changes to {output_path}, skipping write.") + return + + print(f" Writing 'What's New' content to {output_path}...") + with open(output_path, "w") as f: + f.write(content) if __name__ == "__main__": changelog_path = Path("../changelog.md") @@ -61,5 +69,3 @@ def generate_rst(parsed_sections, output_path): parsed_sections = parse_changelog(changelog_path) generate_rst(parsed_sections, output_path) - - print(f"Generated {output_path} from {changelog_path}") \ No newline at end of file diff --git a/docs/generate_default_bsedict.py b/docs/generate_default_bsedict.py index 310c00b12..33ac121d8 100644 --- a/docs/generate_default_bsedict.py +++ b/docs/generate_default_bsedict.py @@ -1,5 +1,6 @@ import json from pathlib import Path +from os.path import exists def get_default_BSE_settings(to_python=False): """Get a copy of the default BSE settings from the COSMIC settings JSON file""" @@ -45,33 +46,43 @@ def generate_rst_bsedict(MAX_LINE_LENGTH=80): indent_str = " " * 8 - with open("_generated/default_bsedict.rst", "w") as f: - lines = [ - ".. ipython:: python", - "", - " BSEDict = {", - ] - - first = True - current_line = indent_str - for k, v in defaults.items(): - entry = f'"{k}": {v}' - if not first: - entry = ", " + entry - first = False - - # check if adding this entry would exceed line length - if len(current_line) + len(entry) > MAX_LINE_LENGTH: - lines.append(current_line.rstrip() + ",") - current_line = indent_str + entry.lstrip(", ") - else: - current_line += entry + lines = [ + ".. ipython:: python", + "", + " BSEDict = {", + ] + + first = True + current_line = indent_str + for k, v in defaults.items(): + entry = f'"{k}": {v}' + if not first: + entry = ", " + entry + first = False + + # check if adding this entry would exceed line length + if len(current_line) + len(entry) > MAX_LINE_LENGTH: + lines.append(current_line.rstrip() + ",") + current_line = indent_str + entry.lstrip(", ") + else: + current_line += entry + + if current_line.strip(): + lines.append(current_line.rstrip()) + lines.append(" }") + + content = "\n".join(lines) + out_path = "_generated/default_bsedict.rst" - if current_line.strip(): - lines.append(current_line.rstrip()) - lines.append(" }") + if exists(out_path): + with open(out_path) as f: + if f.read() == content: + print(f" No changes to {out_path}, skipping write.") + return - f.write("\n".join(lines)) + with open(out_path, "w") as f: + print(f" Writing default BSE settings to {out_path}...") + f.write(content) if __name__ == "__main__": generate_rst_bsedict() \ No newline at end of file From 74c9776f59fedb43ef4c66fa769924354ba4dafc Mon Sep 17 00:00:00 2001 From: Tom Wagg Date: Sat, 30 May 2026 18:21:29 -0400 Subject: [PATCH 2/9] don't force api rebuild --- docs/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/Makefile b/docs/Makefile index 1fa18aba7..2ef3093fa 100644 --- a/docs/Makefile +++ b/docs/Makefile @@ -228,6 +228,6 @@ pseudoxml: .PHONY: apidoc apidoc: - sphinx-apidoc -o api/ ../src/cosmic ../src/cosmic/tests --no-toc --separate --no-headings --force + sphinx-apidoc -o api/ ../src/cosmic ../src/cosmic/tests --no-toc --separate --no-headings @echo @echo "APIdoc run is complete." From f91db52071fa632a61d687296e4c4228519d7603 Mon Sep 17 00:00:00 2001 From: Tom Wagg Date: Sat, 30 May 2026 18:21:41 -0400 Subject: [PATCH 3/9] image links are causing slow reloads --- docs/pages/evolve/interface.rst | 28 ++-------------------------- 1 file changed, 2 insertions(+), 26 deletions(-) diff --git a/docs/pages/evolve/interface.rst b/docs/pages/evolve/interface.rst index 30ea70f7c..332405e89 100644 --- a/docs/pages/evolve/interface.rst +++ b/docs/pages/evolve/interface.rst @@ -89,10 +89,6 @@ First, let's plot the initial mass distribution of the primary stars in our bina @savefig initial_mass_distribution.png plt.show() -.. image:: initial_mass_distribution.png - :alt: - :width: 100% - We could also compare this to the final mass distribution of the primary stars after evolution. .. ipython:: python @@ -103,10 +99,6 @@ We could also compare this to the final mass distribution of the primary stars a @savefig final_mass_distribution.png plt.show() -.. image:: final_mass_distribution.png - :alt: - :width: 100% - In addition to histograms, you can create scatter plots to visualize relationships between different parameters. .. ipython:: python @@ -120,14 +112,10 @@ In addition to histograms, you can create scatter plots to visualize relationshi ax.set_xscale("log") ax.set_yscale("log") ax.invert_xaxis() - + @savefig hrd.png plt.show() -.. image:: hrd.png - :alt: - :width: 100% - And we also can colour the points by the stellar type of the primary star at the end of evolution and get a custom colour map for these ones. @@ -141,14 +129,10 @@ colour map for these ones. ); ax.set_xscale("log") ax.set_yscale("log") - + @savefig m1_porb_kstar.png plt.show() -.. image:: m1_porb_kstar.png - :alt: - :width: 100% - Any column name from the ``bpp`` (or ``initC`` for initial conditions) DataFrames can be used for the x, y, and colour col names. Subselecting binaries @@ -204,10 +188,6 @@ Now clearly staring at the DataFrame isn't very helpful, so let's plot the evolu @savefig detailed_bh.png plt.show() -.. image:: detailed_bh.png - :alt: - :width: 100% - This shows the full evolution, but we can ignore any time a while after the binary forms a BH by setting a maximum time for the x-axis. @@ -223,10 +203,6 @@ by setting a maximum time for the x-axis. @savefig detailed_bh_limited.png plt.show() -.. image:: detailed_bh_limited.png - :alt: - :width: 100% - Re-running with new physics settings ==================================== From 4cb9860ca533627f286b350b2e40127749cfd2c2 Mon Sep 17 00:00:00 2001 From: Tom Wagg Date: Sat, 30 May 2026 19:25:07 -0400 Subject: [PATCH 4/9] move everything into organised folders --- docs/index.rst | 11 ++---- .../pages/{ => config_and_output}/inifile.rst | 0 .../{ => config_and_output}/output_info.rst | 0 docs/pages/examples.rst | 20 ---------- docs/pages/reference_material.rst | 4 +- docs/pages/tutorials.rst | 37 +++++++++++++++++++ docs/pages/tutorials/analysis.rst | 11 ++++++ .../analysis}/interface.rst | 2 +- docs/pages/tutorials/convergence.rst | 11 ++++++ .../convergence/cosmic_pop.rst} | 0 docs/pages/tutorials/evolve.rst | 15 ++++++++ .../{ => tutorials}/evolve/evolve_sample.rst | 2 +- docs/pages/{ => tutorials}/evolve/grid.rst | 2 +- .../pages/{ => tutorials}/evolve/multiple.rst | 2 +- docs/pages/{ => tutorials}/evolve/single.rst | 2 +- docs/pages/tutorials/misc.rst | 11 ++++++ .../{ => tutorials/misc}/multiprocessing.rst | 0 docs/pages/tutorials/rerun.rst | 12 ++++++ .../{evolve => tutorials/rerun}/rerun.rst | 2 +- .../{evolve => tutorials/rerun}/restart.rst | 2 +- .../{runpop.rst => tutorials/sample.rst} | 0 docs/pages/{ => tutorials}/sample/cluster.rst | 2 + .../{ => tutorials}/sample/independent.rst | 0 .../pages/{ => tutorials}/sample/multidim.rst | 2 + docs/pages/tutorials/timesteps.rst | 12 ++++++ docs/pages/tutorials/timesteps/modifiers.rst | 5 +++ .../timesteps}/resolution.rst | 2 +- 27 files changed, 132 insertions(+), 37 deletions(-) rename docs/pages/{ => config_and_output}/inifile.rst (100%) rename docs/pages/{ => config_and_output}/output_info.rst (100%) delete mode 100644 docs/pages/examples.rst create mode 100644 docs/pages/tutorials.rst create mode 100644 docs/pages/tutorials/analysis.rst rename docs/pages/{evolve => tutorials/analysis}/interface.rst (99%) create mode 100644 docs/pages/tutorials/convergence.rst rename docs/pages/{fixedpop.rst => tutorials/convergence/cosmic_pop.rst} (100%) create mode 100644 docs/pages/tutorials/evolve.rst rename docs/pages/{ => tutorials}/evolve/evolve_sample.rst (96%) rename docs/pages/{ => tutorials}/evolve/grid.rst (95%) rename docs/pages/{ => tutorials}/evolve/multiple.rst (97%) rename docs/pages/{ => tutorials}/evolve/single.rst (99%) create mode 100644 docs/pages/tutorials/misc.rst rename docs/pages/{ => tutorials/misc}/multiprocessing.rst (100%) create mode 100644 docs/pages/tutorials/rerun.rst rename docs/pages/{evolve => tutorials/rerun}/rerun.rst (99%) rename docs/pages/{evolve => tutorials/rerun}/restart.rst (98%) rename docs/pages/{runpop.rst => tutorials/sample.rst} (100%) rename docs/pages/{ => tutorials}/sample/cluster.rst (98%) rename docs/pages/{ => tutorials}/sample/independent.rst (100%) rename docs/pages/{ => tutorials}/sample/multidim.rst (99%) create mode 100644 docs/pages/tutorials/timesteps.rst create mode 100644 docs/pages/tutorials/timesteps/modifiers.rst rename docs/pages/{evolve => tutorials/timesteps}/resolution.rst (98%) diff --git a/docs/index.rst b/docs/index.rst index 7b432791f..fb96e73cb 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -23,17 +23,14 @@ Welcome to COSMIC! :alt: COSMIC logo .. toctree:: - :maxdepth: 2 + :maxdepth: 3 :hidden: pages/about pages/install pages/reference_material - pages/examples - pages/runpop - pages/fixedpop - pages/multiprocessing + pages/tutorials + pages/api pages/cite - pages/developers _generated/whats_new - pages/api + pages/developers diff --git a/docs/pages/inifile.rst b/docs/pages/config_and_output/inifile.rst similarity index 100% rename from docs/pages/inifile.rst rename to docs/pages/config_and_output/inifile.rst diff --git a/docs/pages/output_info.rst b/docs/pages/config_and_output/output_info.rst similarity index 100% rename from docs/pages/output_info.rst rename to docs/pages/config_and_output/output_info.rst diff --git a/docs/pages/examples.rst b/docs/pages/examples.rst deleted file mode 100644 index c35e30ff5..000000000 --- a/docs/pages/examples.rst +++ /dev/null @@ -1,20 +0,0 @@ -.. _examples: - -################# -Evolving binaries -################# - -COSMIC can evolve binaries for several different use cases. Go through the examples below to learn more about these capabilities. - -.. toctree:: - :maxdepth: 1 - - evolve/single - evolve/multiple - evolve/grid - evolve/evolve_sample - evolve/resolution - evolve/rerun - evolve/restart - evolve/interface - diff --git a/docs/pages/reference_material.rst b/docs/pages/reference_material.rst index 618385cfe..fc172f54d 100644 --- a/docs/pages/reference_material.rst +++ b/docs/pages/reference_material.rst @@ -14,7 +14,7 @@ Configuration and output .. toctree:: :maxdepth: 1 - inifile.rst + config_and_output/inifile.rst Instructions for creating configurations files and explanations of each option. @@ -25,7 +25,7 @@ Configuration and output .. toctree:: :maxdepth: 1 - output_info.rst + config_and_output/output_info.rst Descriptions of the output files generated by COSMIC simulations. diff --git a/docs/pages/tutorials.rst b/docs/pages/tutorials.rst new file mode 100644 index 000000000..840d2b3ca --- /dev/null +++ b/docs/pages/tutorials.rst @@ -0,0 +1,37 @@ +Tutorials +========= + +.. grid:: 1 1 2 2 + :gutter: 3 + + .. grid-item-card:: + + .. raw:: html + +
+
Evolving binaries
+ +
+ + .. grid-item-card:: + + Sampling binaries + + * :ref:`independent` + * :ref:`multidim` + * :ref:`cmc_sampling` + +.. toctree:: + :maxdepth: 2 + :hidden: + + tutorials/evolve + tutorials/sample + tutorials/convergence + tutorials/rerun + tutorials/timesteps + tutorials/analysis + tutorials/misc \ No newline at end of file diff --git a/docs/pages/tutorials/analysis.rst b/docs/pages/tutorials/analysis.rst new file mode 100644 index 000000000..bd5e370f1 --- /dev/null +++ b/docs/pages/tutorials/analysis.rst @@ -0,0 +1,11 @@ +############### +Output analysis +############### + +These tutorials will cover how to easily analyse your ``COSMIC`` output data with a simple interface that can mask all of the output tables together. + +.. toctree:: + :maxdepth: 2 + :hidden: + + analysis/interface \ No newline at end of file diff --git a/docs/pages/evolve/interface.rst b/docs/pages/tutorials/analysis/interface.rst similarity index 99% rename from docs/pages/evolve/interface.rst rename to docs/pages/tutorials/analysis/interface.rst index 332405e89..fd361d278 100644 --- a/docs/pages/evolve/interface.rst +++ b/docs/pages/tutorials/analysis/interface.rst @@ -26,7 +26,7 @@ samples ~100 binaries and evolving them. import matplotlib.pyplot as plt import numpy as np -.. include:: ../../_generated/default_bsedict.rst +.. include:: ../../../_generated/default_bsedict.rst .. ipython:: python diff --git a/docs/pages/tutorials/convergence.rst b/docs/pages/tutorials/convergence.rst new file mode 100644 index 000000000..6258f6b6c --- /dev/null +++ b/docs/pages/tutorials/convergence.rst @@ -0,0 +1,11 @@ +##################### +Converged populations +##################### + +``COSMIC`` provides utilities for creating a converged population of binaries. Follow the tutorials below to learn how to do this! + +.. toctree:: + :maxdepth: 2 + :hidden: + + convergence/cosmic_pop \ No newline at end of file diff --git a/docs/pages/fixedpop.rst b/docs/pages/tutorials/convergence/cosmic_pop.rst similarity index 100% rename from docs/pages/fixedpop.rst rename to docs/pages/tutorials/convergence/cosmic_pop.rst diff --git a/docs/pages/tutorials/evolve.rst b/docs/pages/tutorials/evolve.rst new file mode 100644 index 000000000..e58b5f6d4 --- /dev/null +++ b/docs/pages/tutorials/evolve.rst @@ -0,0 +1,15 @@ +.. _examples: + +Evolving binaries +================= + +``COSMIC`` can evolve binaries for several different use cases. Go through the examples below to learn more about these capabilities. + +.. toctree:: + :maxdepth: 2 + :hidden: + + evolve/single + evolve/multiple + evolve/grid + evolve/evolve_sample \ No newline at end of file diff --git a/docs/pages/evolve/evolve_sample.rst b/docs/pages/tutorials/evolve/evolve_sample.rst similarity index 96% rename from docs/pages/evolve/evolve_sample.rst rename to docs/pages/tutorials/evolve/evolve_sample.rst index 9c5766aae..be0aa1c7a 100644 --- a/docs/pages/evolve/evolve_sample.rst +++ b/docs/pages/tutorials/evolve/evolve_sample.rst @@ -34,7 +34,7 @@ about the independent sampler in the :ref:`independent` page. And finally, we can evolve the initial binary population using the Evolve class as we've done in the previous guides: -.. include:: ../../_generated/default_bsedict.rst +.. include:: ../../../_generated/default_bsedict.rst .. ipython:: python :okwarning: diff --git a/docs/pages/evolve/grid.rst b/docs/pages/tutorials/evolve/grid.rst similarity index 95% rename from docs/pages/evolve/grid.rst rename to docs/pages/tutorials/evolve/grid.rst index 8a0b8bb90..5665b1a4a 100644 --- a/docs/pages/evolve/grid.rst +++ b/docs/pages/tutorials/evolve/grid.rst @@ -12,7 +12,7 @@ setting up the BSEDict settings as we've done in the previous examples. from cosmic.evolve import Evolve -.. include:: ../../_generated/default_bsedict.rst +.. include:: ../../../_generated/default_bsedict.rst Here we evolve the same system that produces a GW150914-like binary, but run over several initial orbital diff --git a/docs/pages/evolve/multiple.rst b/docs/pages/tutorials/evolve/multiple.rst similarity index 97% rename from docs/pages/evolve/multiple.rst rename to docs/pages/tutorials/evolve/multiple.rst index 603b47a03..eb5ca51c2 100644 --- a/docs/pages/evolve/multiple.rst +++ b/docs/pages/tutorials/evolve/multiple.rst @@ -18,7 +18,7 @@ And use the same SSE and BSE dictionaries as before: SSEDict = {'stellar_engine': 'sse'} -.. include:: ../../_generated/default_bsedict.rst +.. include:: ../../../_generated/default_bsedict.rst Below is an example for systems that could form GW150914 and GW170817 - like binaries. diff --git a/docs/pages/evolve/single.rst b/docs/pages/tutorials/evolve/single.rst similarity index 99% rename from docs/pages/evolve/single.rst rename to docs/pages/tutorials/evolve/single.rst index e71fbe797..d7812a89e 100644 --- a/docs/pages/evolve/single.rst +++ b/docs/pages/tutorials/evolve/single.rst @@ -82,7 +82,7 @@ advised to run the defaults from the COSMIC install which are consistent with `Breivik+2020 `_, though we don't promise that these are the most up-to-date prescriptions. -.. include:: ../../_generated/default_bsedict.rst +.. include:: ../../../_generated/default_bsedict.rst Running a binary diff --git a/docs/pages/tutorials/misc.rst b/docs/pages/tutorials/misc.rst new file mode 100644 index 000000000..9762619c9 --- /dev/null +++ b/docs/pages/tutorials/misc.rst @@ -0,0 +1,11 @@ +############# +Miscellaneous +############# + +And finally, here's everything else that didn't fit into the other categories! + +.. toctree:: + :maxdepth: 2 + :hidden: + + misc/multiprocessing \ No newline at end of file diff --git a/docs/pages/multiprocessing.rst b/docs/pages/tutorials/misc/multiprocessing.rst similarity index 100% rename from docs/pages/multiprocessing.rst rename to docs/pages/tutorials/misc/multiprocessing.rst diff --git a/docs/pages/tutorials/rerun.rst b/docs/pages/tutorials/rerun.rst new file mode 100644 index 000000000..8c92f1fa1 --- /dev/null +++ b/docs/pages/tutorials/rerun.rst @@ -0,0 +1,12 @@ +################### +Re-running binaries +################### + +``COSMIC`` can re-run binaries that have already been evolved previously. This allows users to either re-run identical simulations from others, re-run those same initial conditions with modified settings, or restart a binary midway through its evolution. Follow the tutorials below to learn how to do this! + +.. toctree:: + :maxdepth: 2 + :hidden: + + rerun/rerun + rerun/restart \ No newline at end of file diff --git a/docs/pages/evolve/rerun.rst b/docs/pages/tutorials/rerun/rerun.rst similarity index 99% rename from docs/pages/evolve/rerun.rst rename to docs/pages/tutorials/rerun/rerun.rst index 6b1013c02..6dba61dd0 100644 --- a/docs/pages/evolve/rerun.rst +++ b/docs/pages/tutorials/rerun/rerun.rst @@ -20,7 +20,7 @@ First, let's evolve a binary and save the initC table. from cosmic.sample.initialbinarytable import InitialBinaryTable from cosmic.evolve import Evolve -.. include:: ../../_generated/default_bsedict.rst +.. include:: ../../../_generated/default_bsedict.rst .. ipython:: python diff --git a/docs/pages/evolve/restart.rst b/docs/pages/tutorials/rerun/restart.rst similarity index 98% rename from docs/pages/evolve/restart.rst rename to docs/pages/tutorials/rerun/restart.rst index f90431c51..5d72affd3 100644 --- a/docs/pages/evolve/restart.rst +++ b/docs/pages/tutorials/rerun/restart.rst @@ -27,7 +27,7 @@ started from the beginning and three different points in the evolution: SSEDict = {'stellar_engine': 'sse'} -.. include:: ../../_generated/default_bsedict.rst +.. include:: ../../../_generated/default_bsedict.rst .. ipython:: python :okwarning: diff --git a/docs/pages/runpop.rst b/docs/pages/tutorials/sample.rst similarity index 100% rename from docs/pages/runpop.rst rename to docs/pages/tutorials/sample.rst diff --git a/docs/pages/sample/cluster.rst b/docs/pages/tutorials/sample/cluster.rst similarity index 98% rename from docs/pages/sample/cluster.rst rename to docs/pages/tutorials/sample/cluster.rst index d175baf0b..f76e3bad6 100644 --- a/docs/pages/sample/cluster.rst +++ b/docs/pages/tutorials/sample/cluster.rst @@ -1,3 +1,5 @@ +.. _cmc_sampling: + ************************** ClusterMonteCarlo Sampling ************************** diff --git a/docs/pages/sample/independent.rst b/docs/pages/tutorials/sample/independent.rst similarity index 100% rename from docs/pages/sample/independent.rst rename to docs/pages/tutorials/sample/independent.rst diff --git a/docs/pages/sample/multidim.rst b/docs/pages/tutorials/sample/multidim.rst similarity index 99% rename from docs/pages/sample/multidim.rst rename to docs/pages/tutorials/sample/multidim.rst index a9e6f0651..fbe5999d9 100644 --- a/docs/pages/sample/multidim.rst +++ b/docs/pages/tutorials/sample/multidim.rst @@ -1,3 +1,5 @@ +.. _multidim: + ****************************** Multidimensional distributions ****************************** diff --git a/docs/pages/tutorials/timesteps.rst b/docs/pages/tutorials/timesteps.rst new file mode 100644 index 000000000..c22720c2f --- /dev/null +++ b/docs/pages/tutorials/timesteps.rst @@ -0,0 +1,12 @@ +######################## +Timesteps and resolution +######################## + +``COSMIC`` is flexible and allows users to modify both the internal timesteps used by the code, as well as the resolution of the output data. Follow the tutorials below to learn how to do this! + +.. toctree:: + :maxdepth: 2 + :hidden: + + timesteps/resolution + timesteps/modifiers \ No newline at end of file diff --git a/docs/pages/tutorials/timesteps/modifiers.rst b/docs/pages/tutorials/timesteps/modifiers.rst new file mode 100644 index 000000000..587612ed2 --- /dev/null +++ b/docs/pages/tutorials/timesteps/modifiers.rst @@ -0,0 +1,5 @@ +**************************** +Modifying internal timesteps +**************************** + +TODO \ No newline at end of file diff --git a/docs/pages/evolve/resolution.rst b/docs/pages/tutorials/timesteps/resolution.rst similarity index 98% rename from docs/pages/evolve/resolution.rst rename to docs/pages/tutorials/timesteps/resolution.rst index 4882ab865..d62832511 100644 --- a/docs/pages/evolve/resolution.rst +++ b/docs/pages/tutorials/timesteps/resolution.rst @@ -42,7 +42,7 @@ First, print all time steps during mass transfer SSEDict = {'stellar_engine': 'sse'} -.. include:: ../../_generated/default_bsedict.rst +.. include:: ../../../_generated/default_bsedict.rst .. ipython:: python :okwarning: From 9f43cb228a8a826cc7e5719eab6c915d4cbf1f0c Mon Sep 17 00:00:00 2001 From: Tom Wagg Date: Sat, 30 May 2026 19:40:08 -0400 Subject: [PATCH 5/9] add cards layout for tutorials --- docs/_static/cosmic-docs.css | 26 +++++ docs/pages/tutorials.rst | 106 ++++++++++++++++-- docs/pages/tutorials/analysis/interface.rst | 2 + docs/pages/tutorials/evolve/evolve_sample.rst | 3 + docs/pages/tutorials/evolve/grid.rst | 2 + docs/pages/tutorials/evolve/multiple.rst | 2 + docs/pages/tutorials/evolve/single.rst | 2 + docs/pages/tutorials/rerun/rerun.rst | 2 + docs/pages/tutorials/rerun/restart.rst | 2 + docs/pages/tutorials/timesteps/modifiers.rst | 2 + docs/pages/tutorials/timesteps/resolution.rst | 2 + 11 files changed, 139 insertions(+), 12 deletions(-) diff --git a/docs/_static/cosmic-docs.css b/docs/_static/cosmic-docs.css index d5e2d46c4..9171e88f8 100644 --- a/docs/_static/cosmic-docs.css +++ b/docs/_static/cosmic-docs.css @@ -552,4 +552,30 @@ select.form-control { .link-white { color: white!important; +} + +.tutorial-card { + text-align: center!important; +} + +.tutorial-card-title { + font-size: 2rem!important; + font-weight: bold!important; + margin-bottom: 0.5rem!important; +} + +.tutorial-card-link { + display: block; + padding: .25rem; + font-size: 1.2rem; + border-radius: 10px; + transition: 300ms; + margin: 0 !important; +} + +.tutorial-card-link:hover { + background-color: var(--color-brand-primary); +} +.tutorial-card-link:hover, .tutorial-card-link:hover a { + color: white!important; } \ No newline at end of file diff --git a/docs/pages/tutorials.rst b/docs/pages/tutorials.rst index 840d2b3ca..0d2fdcbeb 100644 --- a/docs/pages/tutorials.rst +++ b/docs/pages/tutorials.rst @@ -5,24 +5,106 @@ Tutorials :gutter: 3 .. grid-item-card:: + + .. container:: tutorial-card - .. raw:: html + .. rubric:: Evolving binaries + :class: tutorial-card-title -
-
Evolving binaries
- -
+ .. rst-class:: tutorial-card-link + + :ref:`evolve_single` + + .. rst-class:: tutorial-card-link + + :ref:`evolve_multiple` + + .. rst-class:: tutorial-card-link + + :ref:`evolve_grid` + + .. rst-class:: tutorial-card-link + + :ref:`evolve_sample` .. grid-item-card:: - Sampling binaries + .. container:: tutorial-card + + .. rubric:: Sampling binaries + :class: tutorial-card-title + + .. rst-class:: tutorial-card-link + + :ref:`independent` + + .. rst-class:: tutorial-card-link + + :ref:`multidim` + + .. rst-class:: tutorial-card-link + + :ref:`cmc_sampling` + + + .. grid-item-card:: + + .. container:: tutorial-card + + .. rubric:: Converged populations + :class: tutorial-card-title + + .. rst-class:: tutorial-card-link + + :ref:`fixedpop` + + .. grid-item-card:: + + .. container:: tutorial-card + + .. rubric:: Re-running simulations + :class: tutorial-card-title + + .. rst-class:: tutorial-card-link + + :ref:`rerun_rerun` + + .. grid-item-card:: + + .. container:: tutorial-card + + .. rubric:: Modifying timesteps + :class: tutorial-card-title + + .. rst-class:: tutorial-card-link + + :ref:`timesteps_resolution` + + .. rst-class:: tutorial-card-link + + :ref:`timesteps_modifiers` + + .. grid-item-card:: + + .. container:: tutorial-card + + .. rubric:: Analysing simulations + :class: tutorial-card-title + + .. rst-class:: tutorial-card-link + + :ref:`analysis_interface` + + .. grid-item-card:: + + .. container:: tutorial-card + + .. rubric:: Miscellaneous + :class: tutorial-card-title - * :ref:`independent` - * :ref:`multidim` - * :ref:`cmc_sampling` + .. rst-class:: tutorial-card-link + + :ref:`multiprocessing` .. toctree:: :maxdepth: 2 diff --git a/docs/pages/tutorials/analysis/interface.rst b/docs/pages/tutorials/analysis/interface.rst index fd361d278..e54a91db7 100644 --- a/docs/pages/tutorials/analysis/interface.rst +++ b/docs/pages/tutorials/analysis/interface.rst @@ -1,3 +1,5 @@ +.. _analysis_interface: + ************************** Analysing your simulations ************************** diff --git a/docs/pages/tutorials/evolve/evolve_sample.rst b/docs/pages/tutorials/evolve/evolve_sample.rst index be0aa1c7a..b995c84dd 100644 --- a/docs/pages/tutorials/evolve/evolve_sample.rst +++ b/docs/pages/tutorials/evolve/evolve_sample.rst @@ -1,6 +1,9 @@ +.. _evolve_sample: + ***************************************** Evolving a Monte-Carlo sampled population ***************************************** + Once an initial binary population is sampled, it can be evolved using the ``Evolve`` class just as we've done so far. You can read more about sampling initial binary populations in the :ref:`runpop` page. diff --git a/docs/pages/tutorials/evolve/grid.rst b/docs/pages/tutorials/evolve/grid.rst index 5665b1a4a..1538e5081 100644 --- a/docs/pages/tutorials/evolve/grid.rst +++ b/docs/pages/tutorials/evolve/grid.rst @@ -1,3 +1,5 @@ +.. _evolve_grid: + ********************************* Evolving a fixed grid of binaries ********************************* diff --git a/docs/pages/tutorials/evolve/multiple.rst b/docs/pages/tutorials/evolve/multiple.rst index eb5ca51c2..77739080c 100644 --- a/docs/pages/tutorials/evolve/multiple.rst +++ b/docs/pages/tutorials/evolve/multiple.rst @@ -1,3 +1,5 @@ +.. _evolve_multiple: + ************************** Evolving multiple binaries ************************** diff --git a/docs/pages/tutorials/evolve/single.rst b/docs/pages/tutorials/evolve/single.rst index d7812a89e..cd1961673 100644 --- a/docs/pages/tutorials/evolve/single.rst +++ b/docs/pages/tutorials/evolve/single.rst @@ -1,3 +1,5 @@ +.. _evolve_single: + ************************ Evolving a single binary ************************ diff --git a/docs/pages/tutorials/rerun/rerun.rst b/docs/pages/tutorials/rerun/rerun.rst index 6dba61dd0..441970ecb 100644 --- a/docs/pages/tutorials/rerun/rerun.rst +++ b/docs/pages/tutorials/rerun/rerun.rst @@ -1,3 +1,5 @@ +.. _rerun_rerun: + ******************* Re-running binaries ******************* diff --git a/docs/pages/tutorials/rerun/restart.rst b/docs/pages/tutorials/rerun/restart.rst index 5d72affd3..06944814a 100644 --- a/docs/pages/tutorials/rerun/restart.rst +++ b/docs/pages/tutorials/rerun/restart.rst @@ -1,3 +1,5 @@ +.. _rerun_restart: + ******************* Restarting a binary ******************* diff --git a/docs/pages/tutorials/timesteps/modifiers.rst b/docs/pages/tutorials/timesteps/modifiers.rst index 587612ed2..f2ecc5d54 100644 --- a/docs/pages/tutorials/timesteps/modifiers.rst +++ b/docs/pages/tutorials/timesteps/modifiers.rst @@ -1,3 +1,5 @@ +.. _timesteps_modifiers: + **************************** Modifying internal timesteps **************************** diff --git a/docs/pages/tutorials/timesteps/resolution.rst b/docs/pages/tutorials/timesteps/resolution.rst index d62832511..f5e565db5 100644 --- a/docs/pages/tutorials/timesteps/resolution.rst +++ b/docs/pages/tutorials/timesteps/resolution.rst @@ -1,3 +1,5 @@ +.. _timesteps_resolution: + *********************** Dynamic time resolution *********************** From 2e8290f7c42e56bffd163569f6ab6fb75191d752 Mon Sep 17 00:00:00 2001 From: Tom Wagg Date: Sat, 30 May 2026 19:59:24 -0400 Subject: [PATCH 6/9] unhide tocs --- docs/pages/tutorials/analysis.rst | 1 - docs/pages/tutorials/convergence.rst | 1 - docs/pages/tutorials/evolve.rst | 1 - docs/pages/tutorials/misc.rst | 1 - docs/pages/tutorials/rerun.rst | 7 +++---- docs/pages/tutorials/timesteps.rst | 1 - 6 files changed, 3 insertions(+), 9 deletions(-) diff --git a/docs/pages/tutorials/analysis.rst b/docs/pages/tutorials/analysis.rst index bd5e370f1..c57f5db69 100644 --- a/docs/pages/tutorials/analysis.rst +++ b/docs/pages/tutorials/analysis.rst @@ -6,6 +6,5 @@ These tutorials will cover how to easily analyse your ``COSMIC`` output data wit .. toctree:: :maxdepth: 2 - :hidden: analysis/interface \ No newline at end of file diff --git a/docs/pages/tutorials/convergence.rst b/docs/pages/tutorials/convergence.rst index 6258f6b6c..5fd0fc30a 100644 --- a/docs/pages/tutorials/convergence.rst +++ b/docs/pages/tutorials/convergence.rst @@ -6,6 +6,5 @@ Converged populations .. toctree:: :maxdepth: 2 - :hidden: convergence/cosmic_pop \ No newline at end of file diff --git a/docs/pages/tutorials/evolve.rst b/docs/pages/tutorials/evolve.rst index e58b5f6d4..323cf6d0c 100644 --- a/docs/pages/tutorials/evolve.rst +++ b/docs/pages/tutorials/evolve.rst @@ -7,7 +7,6 @@ Evolving binaries .. toctree:: :maxdepth: 2 - :hidden: evolve/single evolve/multiple diff --git a/docs/pages/tutorials/misc.rst b/docs/pages/tutorials/misc.rst index 9762619c9..5b96f7c25 100644 --- a/docs/pages/tutorials/misc.rst +++ b/docs/pages/tutorials/misc.rst @@ -6,6 +6,5 @@ And finally, here's everything else that didn't fit into the other categories! .. toctree:: :maxdepth: 2 - :hidden: misc/multiprocessing \ No newline at end of file diff --git a/docs/pages/tutorials/rerun.rst b/docs/pages/tutorials/rerun.rst index 8c92f1fa1..f3b51e7c1 100644 --- a/docs/pages/tutorials/rerun.rst +++ b/docs/pages/tutorials/rerun.rst @@ -1,12 +1,11 @@ -################### -Re-running binaries -################### +###################### +Re-running simulations +###################### ``COSMIC`` can re-run binaries that have already been evolved previously. This allows users to either re-run identical simulations from others, re-run those same initial conditions with modified settings, or restart a binary midway through its evolution. Follow the tutorials below to learn how to do this! .. toctree:: :maxdepth: 2 - :hidden: rerun/rerun rerun/restart \ No newline at end of file diff --git a/docs/pages/tutorials/timesteps.rst b/docs/pages/tutorials/timesteps.rst index c22720c2f..51e8e4c9c 100644 --- a/docs/pages/tutorials/timesteps.rst +++ b/docs/pages/tutorials/timesteps.rst @@ -6,7 +6,6 @@ Timesteps and resolution .. toctree:: :maxdepth: 2 - :hidden: timesteps/resolution timesteps/modifiers \ No newline at end of file From dba0515c04f34f41991e286db1e33b8867603607 Mon Sep 17 00:00:00 2001 From: Tom Wagg Date: Sat, 30 May 2026 19:59:41 -0400 Subject: [PATCH 7/9] style clean up --- docs/_static/cosmic-docs.css | 42 +++++++++++++++++++++++++----------- docs/pages/tutorials.rst | 10 +++++++++ 2 files changed, 40 insertions(+), 12 deletions(-) diff --git a/docs/_static/cosmic-docs.css b/docs/_static/cosmic-docs.css index 9171e88f8..991d958f4 100644 --- a/docs/_static/cosmic-docs.css +++ b/docs/_static/cosmic-docs.css @@ -88,17 +88,6 @@ html[data-theme="dark"] .sd-card { background-color: #e193ca; } -@media (max-width: 720px) { - .toms-nav-container { - width: 100%; - height: auto; - grid-template-columns: 100%; - grid-template-rows: auto; - grid-column-gap: 0; - grid-row-gap: 20px; - } -} - #installation h2 { font-size: 1.2rem; } @@ -554,6 +543,20 @@ select.form-control { color: white!important; } +.content:has(.tutorial-card) { + width: 100%; + padding: 0 7em; +} + +.content:has(.tutorial-card) h1 { + text-align: center; + margin-left: 100px; +} + +.center { + text-align: center; +} + .tutorial-card { text-align: center!important; } @@ -567,7 +570,7 @@ select.form-control { .tutorial-card-link { display: block; padding: .25rem; - font-size: 1.2rem; + font-size: 1rem; border-radius: 10px; transition: 300ms; margin: 0 !important; @@ -578,4 +581,19 @@ select.form-control { } .tutorial-card-link:hover, .tutorial-card-link:hover a { color: white!important; +} + +@media (max-width: 720px) { + .toms-nav-container { + width: 100%; + height: auto; + grid-template-columns: 100%; + grid-template-rows: auto; + grid-column-gap: 0; + grid-row-gap: 20px; + } + + .content:has(.tutorial-card) { + padding: 0 1em; + } } \ No newline at end of file diff --git a/docs/pages/tutorials.rst b/docs/pages/tutorials.rst index 0d2fdcbeb..5d1892b40 100644 --- a/docs/pages/tutorials.rst +++ b/docs/pages/tutorials.rst @@ -1,6 +1,12 @@ +:html_theme.sidebar_secondary.items: [] + Tutorials ========= +.. rst-class:: center + +This page contains of tutorials that show you how to use ``COSMIC`` and become an expert in its various features! The tutorials are split into different categories, which you can navigate to using the links below. + .. grid:: 1 1 2 2 :gutter: 3 @@ -69,6 +75,10 @@ Tutorials :ref:`rerun_rerun` + .. rst-class:: tutorial-card-link + + :ref:`rerun_restart` + .. grid-item-card:: .. container:: tutorial-card From ffa485fa651d263ce7863d7caf0757a29eec02ef Mon Sep 17 00:00:00 2001 From: Tom Wagg Date: Sat, 30 May 2026 19:59:45 -0400 Subject: [PATCH 8/9] add tom --- docs/conf.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/conf.py b/docs/conf.py index 90e373e09..58f301342 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -117,7 +117,7 @@ # General information about the project. project = u'cosmic' -copyright = u'2021, Katie Breivik' +copyright = u'2019-2026, Katie Breivik, Tom Wagg' author = u'Katie Breivik' # The version info for the project you're documenting, acts as replacement for From 32d7a72a5f87fb9412ee9b66fa8d957651957c24 Mon Sep 17 00:00:00 2001 From: Tom Wagg Date: Sat, 30 May 2026 20:39:05 -0400 Subject: [PATCH 9/9] document dt_mass_modifiers --- docs/conf.py | 3 + docs/pages/tutorials/timesteps/modifiers.rst | 190 ++++++++++++++++++- 2 files changed, 192 insertions(+), 1 deletion(-) diff --git a/docs/conf.py b/docs/conf.py index 58f301342..d20d1ef71 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -76,6 +76,9 @@ 'remove_config_comments': True, } +import matplotlib +matplotlib.rcParams["savefig.dpi"] = 300 + # -- autosummary -------------------------------- autosummary_generate = True diff --git a/docs/pages/tutorials/timesteps/modifiers.rst b/docs/pages/tutorials/timesteps/modifiers.rst index f2ecc5d54..ef468dd23 100644 --- a/docs/pages/tutorials/timesteps/modifiers.rst +++ b/docs/pages/tutorials/timesteps/modifiers.rst @@ -4,4 +4,192 @@ Modifying internal timesteps **************************** -TODO \ No newline at end of file +In addition to modifying the resolution of the output data, users can also modify the internal timesteps used by ``COSMIC``. + +Changing the default timesteps (not recommended) +------------------------------------------------ + +By default, ``COSMIC`` timesteps are set by the user-specified settings ``pts1``, ``pts2``, and ``pts3`` (see :ref:`inifile` for more details). These specify timesteps for different evolutionary phases of the binary. + +One could edit these directly in the BSEDict as we've seen in other tutorials. + +.. ipython:: python + + from cosmic.sample.initialbinarytable import InitialBinaryTable + from cosmic.evolve import Evolve + + single_binary = InitialBinaryTable.InitialBinaries( + m1=85.543645, m2=84.99784, porb=446.795757, + ecc=0.448872, tphysf=13700.0, + kstar1=1, kstar2=1, metallicity=0.002 + ) + + SSEDict = {'stellar_engine': 'sse'} + +.. include:: ../../../_generated/default_bsedict.rst + +.. ipython:: python + + bpp, bcm, initC, kick_info = Evolve.evolve( + initialbinarytable=single_binary, + BSEDict=BSEDict, + SSEDict=SSEDict + ) + + # take twice as large timesteps for all phases + BSEDict['pts1'] *= 2 + BSEDict['pts2'] *= 2 + BSEDict['pts3'] *= 2 + + bpp_mod, bcm_mod, initC_mod, kick_info_mod = Evolve.evolve( + initialbinarytable=single_binary, + BSEDict=BSEDict, + SSEDict=SSEDict + ) + +From inspection of the resulting tables, you may start to see strange behaviour if the timesteps are too large. + +Modifying timesteps as a function of mass (recommended) +------------------------------------------------------- + +Users can also specify additional modifiers to these timesteps that will be applied during the evolution. The original BSE timesteps can be modified for higher masses, where extrapolation beyond the original stellar grids can lead to unexpected behaviour. + +These modifiers are specified as ``dt_mass_modifiers`` in the :meth:`~cosmic.evolve.Evolve.evolve` function when performing evolution. They are written as a list of tuples of the form ``(min, max, modifier)``, where the fractional modifier is applied to the default timesteps for stars with masses between ``min`` and ``max``. + +For example, to take half as large timesteps for stars with masses between 50 and 100 solar masses, you can do: + +.. ipython:: python + + dt_mass_modifiers = [(50, 100, 0.5)] + + bpp_mod, bcm_mod, initC_mod, kick_info_mod = Evolve.evolve( + initialbinarytable=single_binary, + BSEDict=BSEDict, + SSEDict=SSEDict, + dt_mass_modifiers=dt_mass_modifiers + ) + +The default choice in ``COSMIC`` is to set ``dt_mass_modifiers = [(40, 70, 0.3), (70, np.inf, 0.1)]``, which we find leads to more numerically stable evolution for very massive stars. + +Example: BH masses +^^^^^^^^^^^^^^^^^^ + +Let's go through an example to see how these modifiers can affect the results of our simulations. Specifically, let's explore the relation between initial mass and BH mass for a high-mass grid. + +First, we can create a grid of 500 single stars with initial masses between 50 and 150 solar masses. + +.. ipython:: python + + import matplotlib.pyplot as plt + import numpy as np + + N_BINARIES = 500 + + # create an initial binary table of single stars + IBT_bh = InitialBinaryTable.InitialBinaries( + m1=np.linspace(50, 150, N_BINARIES), + m2=np.zeros(N_BINARIES), + porb=np.zeros(N_BINARIES), + ecc=np.zeros(N_BINARIES), + kstar1=[1] * N_BINARIES, + kstar2=[0] * N_BINARIES, + metallicity=[0.01] * N_BINARIES, + tphysf=[200] * N_BINARIES, + ) + +Now let's copy our BSEDict but turn of pair-instability supernovae (PISN) to simplify the top end of the plot and make sure any differences are just coming from timesteps. + +.. ipython:: python + + # switch off PISN to simplify the plot + no_PISN_BSEDict = BSEDict.copy() + no_PISN_BSEDict["pisn"] = 0 + + +We can set up 4 different choices of timesteps to compare: + +- The default choice in ``COSMIC``: ``dt_mass_modifiers = [(40, 70, 0.3), (70, np.inf, 0.1)]`` +- Half the default BSE timesteps: ``dt_mass_modifiers = [(0, np.inf, 0.5)]`` +- The default BSE timesteps: ``dt_mass_modifiers = []`` +- Double the default BSE timesteps: ``dt_mass_modifiers = [(0, np.inf, 2)]`` + +.. ipython:: python + + bpp_timesteps = [] + labels = ['Default dt_mass_modifiers', 'Half BSE', + 'BSE defaults', 'Double BSE'] + dt_mass_modifiers_vals = [ + [(40, 70, 0.3), (70, np.inf, 0.1)], + [(0, np.inf, 0.5)], + [], + [(0, np.inf, 2)] + ] + +Now let's use those to evolve our grid of single stars 4 different times and store the resulting BPPs. + +.. ipython:: python + + for dtmm in dt_mass_modifiers_vals: + bpp, _, _, _ = Evolve.evolve( + initialbinarytable=IBT_bh, + SSEDict=SSEDict, + BSEDict=BSEDict, + dt_mass_modifiers=dtmm, + ) + bpp_timesteps.append(bpp) + +With our evolution done, let's find the final BH mass and the corresponding initial mass in each grid for plotting. + +.. ipython:: python + + m_inits = [] + m_bhs = [] + + for bpp in bpp_timesteps: + bh = bpp.loc[bpp['kstar_1'] == 14].groupby(level=0).last() + init = IBT_bh.loc[bh.index, 'mass_1'] + m_init, m_bh = init.values, bh['mass_1'].values + m_inits.append(m_init) + m_bhs.append(m_bh) + +And finally, let's plot the results! + +.. ipython:: python + + plt.rc('font', family='serif') + plt.rcParams['text.usetex'] = False + fs = 24 + params = {'figure.figsize': (12, 8), + 'legend.fontsize': 0.7*fs, + 'legend.title_fontsize': 0.8*fs, + 'axes.labelsize': fs, + 'xtick.labelsize': 0.9 * fs, + 'ytick.labelsize': 0.9 * fs, + 'axes.linewidth': 1.1, + 'xtick.major.size': 7, + 'xtick.minor.size': 4, + 'ytick.major.size': 7, + 'ytick.minor.size': 4} + plt.rcParams.update(params) + + fig, axes = plt.subplots(2, 1, figsize=(14, 8), gridspec_kw={'height_ratios': [3, 1]}) + + for m_init, m_bh, label, zorder in zip(m_inits, m_bhs, labels, [100, 50, 25, 1]): + axes[0].plot(m_init, m_bh, zorder=zorder, label=label) + axes[0].legend(); + + for m_init, m_bh in zip(m_inits, m_bhs): + axes[1].plot(m_init, m_bh - m_bhs[0]) + axes[1].set_xlabel('Initial primary mass $M_1^\\mathrm{init}$ [$M_\\odot$]'); + + for ax in axes: + ax.grid(True, lw=0.4, alpha=0.4); + axes[0].set_ylabel('BH mass [$M_\\odot$]'); + axes[1].set_ylabel('Difference [$M_\\odot$]'); + + plt.tight_layout(); + + @savefig dt_mass_modifiers.png + plt.show() + +So we can see here that there are clear numerical artifacts in the relation between initial mass and BH mass when using the default BSE timesteps (and especially when they are larger!). This motivated our choice of the default ``dt_mass_modifiers`` in ``COSMIC`` to ensure more stable evolution for very massive stars. \ No newline at end of file