From c5a4ce186fbb9bb61eac366ff290340314234ea2 Mon Sep 17 00:00:00 2001 From: Elizabeth Teng <41969755+elizabethteng@users.noreply.github.com> Date: Thu, 18 Dec 2025 07:52:22 -0600 Subject: [PATCH 01/91] Create validate_binaries.sh --- dev-tools/validate_binaries.sh | 1 + 1 file changed, 1 insertion(+) create mode 100644 dev-tools/validate_binaries.sh diff --git a/dev-tools/validate_binaries.sh b/dev-tools/validate_binaries.sh new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/dev-tools/validate_binaries.sh @@ -0,0 +1 @@ + From b692409ae09bd78a686d25f72dc4f57a6507ca2d Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Thu, 18 Dec 2025 13:52:47 +0000 Subject: [PATCH 02/91] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- dev-tools/validate_binaries.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/dev-tools/validate_binaries.sh b/dev-tools/validate_binaries.sh index 8b13789179..e69de29bb2 100644 --- a/dev-tools/validate_binaries.sh +++ b/dev-tools/validate_binaries.sh @@ -1 +0,0 @@ - From 27d3195673dd11ab6fd87913e12c57e81627e16d Mon Sep 17 00:00:00 2001 From: Elizabeth Teng <41969755+elizabethteng@users.noreply.github.com> Date: Thu, 18 Dec 2025 08:10:24 -0600 Subject: [PATCH 03/91] Create dummy file baseline.h5 --- dev-tools/outputs/baseline.h5 | 1 + 1 file changed, 1 insertion(+) create mode 100644 dev-tools/outputs/baseline.h5 diff --git a/dev-tools/outputs/baseline.h5 b/dev-tools/outputs/baseline.h5 new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/dev-tools/outputs/baseline.h5 @@ -0,0 +1 @@ + From b90303facc10503c7766b5575a5fefc7590a5ea1 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Thu, 18 Dec 2025 14:10:32 +0000 Subject: [PATCH 04/91] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- dev-tools/outputs/baseline.h5 | 1 - 1 file changed, 1 deletion(-) diff --git a/dev-tools/outputs/baseline.h5 b/dev-tools/outputs/baseline.h5 index 8b13789179..e69de29bb2 100644 --- a/dev-tools/outputs/baseline.h5 +++ b/dev-tools/outputs/baseline.h5 @@ -1 +0,0 @@ - From 6d4253414ae88e41022a1a780a8fe86eaed93bb6 Mon Sep 17 00:00:00 2001 From: Elizabeth Teng <41969755+elizabethteng@users.noreply.github.com> Date: Thu, 18 Dec 2025 08:20:43 -0600 Subject: [PATCH 05/91] outline script --- dev-tools/validate_binaries.sh | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/dev-tools/validate_binaries.sh b/dev-tools/validate_binaries.sh index e69de29bb2..436b55647c 100644 --- a/dev-tools/validate_binaries.sh +++ b/dev-tools/validate_binaries.sh @@ -0,0 +1,29 @@ +#!/bin/bash + +# A script for validating the outputs of 100 binaries, +# which can be compared to a baseline to monitor changes to the code. + +# script usage: ./validate_binaries.sh --branch candidate-branch + +# run candidate binaries and save to file +# ./evolve_binaries.sh +# save to file + +# evaluate tolerance for quantitative values + +# evaluate qualitative differences + +# warnings and error tracking + +# structured output + +# compare +# python compare_runs.py baseline.json candidate.json + + + + + +# outputs/baseline.h5 +# outputs/candidate_branchname.h5 +# outputs/comparison_branchname.txt From b689460e0f674e60ad1cce9e1da6fde386cd79ef Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Thu, 18 Dec 2025 14:20:52 +0000 Subject: [PATCH 06/91] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- dev-tools/validate_binaries.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev-tools/validate_binaries.sh b/dev-tools/validate_binaries.sh index 436b55647c..31b7c6d72a 100644 --- a/dev-tools/validate_binaries.sh +++ b/dev-tools/validate_binaries.sh @@ -1,6 +1,6 @@ #!/bin/bash -# A script for validating the outputs of 100 binaries, +# A script for validating the outputs of 100 binaries, # which can be compared to a baseline to monitor changes to the code. # script usage: ./validate_binaries.sh --branch candidate-branch From b662a751118f1261ab8cd13029b6c8f02f86c8f6 Mon Sep 17 00:00:00 2001 From: Elizabeth Teng <41969755+elizabethteng@users.noreply.github.com> Date: Thu, 18 Dec 2025 08:28:17 -0600 Subject: [PATCH 07/91] Modify evolve_binaries.sh for saved output and logs in folder outputs --- dev-tools/evolve_binaries.sh | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/dev-tools/evolve_binaries.sh b/dev-tools/evolve_binaries.sh index fc7a20fb3b..051dafcd13 100755 --- a/dev-tools/evolve_binaries.sh +++ b/dev-tools/evolve_binaries.sh @@ -28,6 +28,15 @@ mkdir -p "$WORK_DIR" FULL_PATH="$(realpath "$WORK_DIR")" CLONE_DIR="$FULL_PATH/POSYDON" +OUTPUT_DIR="$FULL_PATH/outputs" +LOG_DIR="$FULL_PATH/logs" + +SAFE_BRANCH="${BRANCH//\//_}" +OUTPUT_FILE="$OUTPUT_DIR/candidate_${SAFE_BRANCH}.h5" +LOG_FILE="$LOG_DIR/evolve_${SAFE_BRANCH}.log" + +mkdir -p "$OUTPUT_DIR" "$LOG_DIR" + echo "šŸ“‹ Copying script_data folder" # copy the script_data folder cp -r "./script_data" "$WORK_DIR" @@ -79,6 +88,11 @@ pip install -e "$CLONE_DIR" -q 2>&1 | sed 's/^/ /' echo "šŸš€ Running evolve_binaries.py" # # Run the Python script and capture output (stdout and stderr) -python script_data/1Zsun_binaries_suite.py > $FULL_PATH/evolve_binaries_$BRANCH.out 2>&1 +python script_data/1Zsun_binaries_suite.py --output "$OUTPUT_FILE" > "$LOG_FILE" 2>&1 + +if [ ! -f "$OUTPUT_FILE" ]; then + echo "ERROR: Results file was not created: $OUTPUT_FILE" + exit 2 +fi -echo -e "āœ… Script completed. Output saved to \n$FULL_PATH/evolve_binaries_$BRANCH.out" +echo -e "āœ… Script completed. Output saved to \n$OUTPUT_FILE" From 2aed3772ebfbe14068ac3d6a6ff40bb5984e8c5a Mon Sep 17 00:00:00 2001 From: Elizabeth Teng <41969755+elizabethteng@users.noreply.github.com> Date: Thu, 18 Dec 2025 08:57:20 -0600 Subject: [PATCH 08/91] Modify evolve_binary for HDF5 output and error handling --- dev-tools/script_data/1Zsun_binaries_suite.py | 63 ++++++++++++------- 1 file changed, 39 insertions(+), 24 deletions(-) diff --git a/dev-tools/script_data/1Zsun_binaries_suite.py b/dev-tools/script_data/1Zsun_binaries_suite.py index 5b2c416c3c..43bb667851 100644 --- a/dev-tools/script_data/1Zsun_binaries_suite.py +++ b/dev-tools/script_data/1Zsun_binaries_suite.py @@ -116,7 +116,15 @@ def print_failed_binary(binary,e, max_error_lines=3): print("-" * line_length) -def evolve_binary(binary): +def evolve_binary(binary,h5file,binary_id): + """ + Evolves a single binary, prints its evolution, and saves to HDF5. + + Args: + binary: BinaryStar object + h5file: open h5py.File object for writing + binary_id: unique identifier for this binary + """ # Capture warnings during evolution captured_warnings = [] @@ -137,44 +145,49 @@ def warning_handler(message, category, filename, lineno, file=None, line=None): binary.evolve() # Display the evolution summary for successful evolution write_binary_to_screen(binary) - - # Show warnings if any were captured - if captured_warnings: - print(f"āš ļø {len(captured_warnings)} warning(s) raised during evolution:") - for i, warning in enumerate(captured_warnings[:3], 1): # Show max 3 warnings - print(f" {i}. {warning['category']}: {warning['message']}") - if len(captured_warnings) > 3: - print(f" ... and {len(captured_warnings) - 3} more warning(s)") - elif len(captured_warnings) <= 3: - for i in range(4-len(captured_warnings)): - print("") - else: - print(f"No warning(s) raised during evolution\n\n\n\n") - print("=" * line_length) + + # Save to HDF5 + df = binary.to_df(**{'extra_columns':{'step_names':'str'}}) + grp = h5file.create_group(f"binary_{binary_id}") + for col in df.columns: + grp.create_dataset(col, data=df[col].values) except Exception as e: - # turn off binary alarm in case of exception signal.alarm(0) print_failed_binary(binary, e) - # Show warnings if any were captured before the exception + err_grp = h5file.require_group(f"binary_{binary_id}/errors") + err_grp.attrs['exception_type'] = type(e).__name__ + err_grp.attrs['exception_message'] = str(e) + + finally: + # Always turn off binary alarm and restore warning handler + signal.alarm(0) + warnings.showwarning = old_showwarning + + # ensure binary group exists + grp = h5file.require_group(f"binary_{binary_id}") + + # Save warnings to h5 file if captured_warnings: - print(f"\nāš ļø {len(captured_warnings)} warning(s) raised before failure:") + warn_grp = grp.create_group("warnings") + for i, warning in enumerate(captured_warnings): + warn_subgrp = warn_grp.create_group(f"warning_{i}") + warn_subgrp.attrs['category'] = warning['category'] + warn_subgrp.attrs['message'] = warning['message'] + warn_subgrp.attrs['filename'] = warning['filename'] + warn_subgrp.attrs['lineno'] = warning['lineno'] + + print(f"āš ļø {len(captured_warnings)} warning(s) raised during evolution:") for i, warning in enumerate(captured_warnings[:3], 1): # Show max 3 warnings print(f" {i}. {warning['category']}: {warning['message']}") if len(captured_warnings) > 3: print(f" ... and {len(captured_warnings) - 3} more warning(s)") else: print(f"No warning(s) raised during evolution\n\n\n\n") - print("=" * line_length) - finally: - # Always turn off binary alarm and restore warning handler - signal.alarm(0) - warnings.showwarning = old_showwarning - def evolve_binaries(verbose): """Evolves a few binaries to validate their output @@ -763,6 +776,8 @@ def evolve_binaries(verbose): parser = argparse.ArgumentParser(description='Evolve binaries for validation.') parser.add_argument('--verbose', '-v', action='store_true', default=False, help='Enable verbose output (default: False)') + parser.add_argument("--output", type=str, required=True, + help="Path to save HDF5 output") args = parser.parse_args() evolve_binaries(verbose=args.verbose) From 493af0f0603efa5ef3604aaf0d77919dcb36b1c3 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Thu, 18 Dec 2025 14:57:38 +0000 Subject: [PATCH 09/91] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- dev-tools/script_data/1Zsun_binaries_suite.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/dev-tools/script_data/1Zsun_binaries_suite.py b/dev-tools/script_data/1Zsun_binaries_suite.py index 43bb667851..e1b347bbe4 100644 --- a/dev-tools/script_data/1Zsun_binaries_suite.py +++ b/dev-tools/script_data/1Zsun_binaries_suite.py @@ -145,7 +145,7 @@ def warning_handler(message, category, filename, lineno, file=None, line=None): binary.evolve() # Display the evolution summary for successful evolution write_binary_to_screen(binary) - + # Save to HDF5 df = binary.to_df(**{'extra_columns':{'step_names':'str'}}) grp = h5file.create_group(f"binary_{binary_id}") @@ -166,10 +166,10 @@ def warning_handler(message, category, filename, lineno, file=None, line=None): # Always turn off binary alarm and restore warning handler signal.alarm(0) warnings.showwarning = old_showwarning - + # ensure binary group exists grp = h5file.require_group(f"binary_{binary_id}") - + # Save warnings to h5 file if captured_warnings: warn_grp = grp.create_group("warnings") @@ -179,7 +179,7 @@ def warning_handler(message, category, filename, lineno, file=None, line=None): warn_subgrp.attrs['message'] = warning['message'] warn_subgrp.attrs['filename'] = warning['filename'] warn_subgrp.attrs['lineno'] = warning['lineno'] - + print(f"āš ļø {len(captured_warnings)} warning(s) raised during evolution:") for i, warning in enumerate(captured_warnings[:3], 1): # Show max 3 warnings print(f" {i}. {warning['category']}: {warning['message']}") @@ -776,7 +776,7 @@ def evolve_binaries(verbose): parser = argparse.ArgumentParser(description='Evolve binaries for validation.') parser.add_argument('--verbose', '-v', action='store_true', default=False, help='Enable verbose output (default: False)') - parser.add_argument("--output", type=str, required=True, + parser.add_argument("--output", type=str, required=True, help="Path to save HDF5 output") args = parser.parse_args() From 91c3d5f9d873b57bf47bfa1bcdb6ddc2a38ba547 Mon Sep 17 00:00:00 2001 From: Elizabeth Teng <41969755+elizabethteng@users.noreply.github.com> Date: Thu, 18 Dec 2025 09:18:58 -0600 Subject: [PATCH 10/91] Update 1Zsun_binaries_suite.py to fix args in function calls --- dev-tools/script_data/1Zsun_binaries_suite.py | 1174 +++++++++-------- 1 file changed, 605 insertions(+), 569 deletions(-) diff --git a/dev-tools/script_data/1Zsun_binaries_suite.py b/dev-tools/script_data/1Zsun_binaries_suite.py index e1b347bbe4..c632db2b34 100644 --- a/dev-tools/script_data/1Zsun_binaries_suite.py +++ b/dev-tools/script_data/1Zsun_binaries_suite.py @@ -116,7 +116,7 @@ def print_failed_binary(binary,e, max_error_lines=3): print("-" * line_length) -def evolve_binary(binary,h5file,binary_id): +def evolve_binary(binary, h5file, binary_id): """ Evolves a single binary, prints its evolution, and saves to HDF5. @@ -189,588 +189,624 @@ def warning_handler(message, category, filename, lineno, file=None, line=None): print(f"No warning(s) raised during evolution\n\n\n\n") print("=" * line_length) -def evolve_binaries(verbose): +def evolve_binaries(verbose,output_path): """Evolves a few binaries to validate their output """ sim_prop = load_inlist(verbose) - ######################################## - # Failing binary in matching - ######################################## - star_1 = SingleStar(**{'mass': 11.948472796094759, 'state': 'H-rich_Core_H_burning','metallicity':1, - 'natal_kick_array': [231.97383621190582, 5.927334890264575, 1.5990566013567014, 6.137994236518587]}) - star_2 = SingleStar(**{'mass': 7.636958434479617, 'state': 'H-rich_Core_H_burning','metallicity':1, - 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) - binary = BinaryStar(star_1, star_2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', - 'orbital_period': 190925.99636740884,'eccentricity': 0.0}, properties = sim_prop) - evolve_binary(binary) - ######################################## - # Failing binary in matching - ######################################## - star_1 = SingleStar(**{'mass': 30.169861921689556, 'state': 'H-rich_Core_H_burning','metallicity':1, - 'natal_kick_array': [77.96834852144123, 0.05021460132555987, 2.3146518208348152, 1.733054979982291]}) - star_2 = SingleStar(**{'mass': 10.972734402996027, 'state': 'H-rich_Core_H_burning','metallicity':1, - 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) - binary = BinaryStar(star_1, star_2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', - 'orbital_period': 20479.71919353725,'eccentricity': 0.0}, properties = sim_prop) - evolve_binary(binary) - ######################################## - # flipped S1 and S2 ? - ######################################## - star_1 = SingleStar(**{'mass': 9.474917413943635, 'state': 'H-rich_Core_H_burning','metallicity':1, - 'natal_kick_array': [133.5713935237759, 4.398754864537542, 2.703102872841114, 1.4633904612711142]}) - star_2 = SingleStar(**{'mass': 9.311073918196263, 'state': 'H-rich_Core_H_burning','metallicity':1, - 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) - binary = BinaryStar(star_1, star_2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', - 'orbital_period': 18.605997832086413,'eccentricity': 0.0}, properties = sim_prop) - - evolve_binary(binary) - ######################################## - # flipped S1 and S2 - ######################################## - star_1 = SingleStar(**{'mass': 10.438541, 'state': 'H-rich_Core_H_burning','metallicity':1, - 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) - star_2 = SingleStar(**{'mass': 1.400713, 'state': 'H-rich_Core_H_burning','metallicity':1, - 'natal_kick_array': [0.0, 4.190728383757787, 1.1521129697118118, 5.015343794234789]}) - binary = BinaryStar(star_1, star_2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', - 'orbital_period': 9.824025,'eccentricity': 0.0}, properties = sim_prop) - evolve_binary(binary) - ######################################## - # flipped S1 and S2 - ######################################## - star_1= SingleStar(**{'mass': 9.845907 , 'state': 'H-rich_Core_H_burning','metallicity':1, - 'natal_kick_array': [0.0, 4.190728383757787, 1.1521129697118118, 5.015343794234789]}) - star_2 = SingleStar(**{'mass': 9.611029, 'state': 'H-rich_Core_H_burning','metallicity':1, - 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) - binary = BinaryStar(star_1, star_2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', - 'orbital_period': 3.820571,'eccentricity': 0.0}, properties = sim_prop) - evolve_binary(binary) - ######################################## - # Normal binary evolution - ######################################## - star_1= SingleStar(**{'mass': 30.845907 , 'state': 'H-rich_Core_H_burning','metallicity':1, - 'natal_kick_array': [0.0, 4.190728383757787, 1.1521129697118118, 5.015343794234789]}) - star_2 = SingleStar(**{'mass': 30.611029, 'state': 'H-rich_Core_H_burning','metallicity':1, - 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) - binary = BinaryStar(star_1, star_2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', - 'orbital_period': 30.820571,'eccentricity': 0.0}, properties = sim_prop) - evolve_binary(binary) - ######################################## - # Normal binary - ######################################## - star_1= SingleStar(**{'mass': 9.213534679594247 , 'state': 'H-rich_Core_H_burning','metallicity':1, - 'natal_kick_array': [327.5906384501521, 1.7707176050073297, 1.573225822966838, 1.6757313876001914]}) - star_2 = SingleStar(**{'mass': 7.209878522799272, 'state': 'H-rich_Core_H_burning','metallicity':1, - 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) - binary = BinaryStar(star_1, star_2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', - 'orbital_period': 63123.74544474666,'eccentricity': 0.0}, properties = sim_prop) - evolve_binary(binary) - ######################################## - # Normal binary - ######################################## - star_1= SingleStar(**{'mass': 9.561158487732602 , 'state': 'H-rich_Core_H_burning','metallicity':1, - 'natal_kick_array': [317.5423844462847, 2.9095984678057603, 1.754121288652108, 2.3693917842468784]}) - star_2 = SingleStar(**{'mass': 9.382732464319286, 'state': 'H-rich_Core_H_burning','metallicity':1, - 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) - binary = BinaryStar(star_1, star_2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', - 'orbital_period': 27.77657038557851,'eccentricity': 0.0}, properties = sim_prop) - evolve_binary(binary) - ######################################## - # Normal binary - ######################################## - star1 = SingleStar(**{'mass': 7.552858,#29829485, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array': [40.91509926587841, 2.6295454150818256, 1.6718337470964977, 6.0408769315244895]}) - star2 = SingleStar(**{'mass': 6.742063, #481560266, - 'state': 'H-rich_Core_H_burning', + with h5py.File(output_path,'w') as h5file: + binary_id=0 + + ######################################## + # Failing binary in matching + ######################################## + star_1 = SingleStar(**{'mass': 11.948472796094759, 'state': 'H-rich_Core_H_burning','metallicity':1, + 'natal_kick_array': [231.97383621190582, 5.927334890264575, 1.5990566013567014, 6.137994236518587]}) + star_2 = SingleStar(**{'mass': 7.636958434479617, 'state': 'H-rich_Core_H_burning','metallicity':1, 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) - binary = BinaryStar(star1, star2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', - 'orbital_period': 17.957531550841225, 'eccentricity': 0.0,}, - properties=sim_prop) - evolve_binary(binary) - ######################################## - # High BH spin options - ######################################## - star_1 = SingleStar(**{'mass': 31.616785, 'state': 'H-rich_Core_H_burning', - 'natal_kick_array': [10, 4.190728383757787, 1.1521129697118118, 5.015343794234789]}) - star_2 = SingleStar(**{'mass': 26.874267, 'state': 'H-rich_Core_H_burning', - 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) - binary = BinaryStar(star_1, star_2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', - 'orbital_period': 501.99252706449792,'eccentricity': 0.0}, properties = sim_prop) - evolve_binary(binary) - ######################################## - # Original a>1 spin error - ######################################## - star_1 = SingleStar(**{'mass': 18.107506844123645, 'state': 'H-rich_Core_H_burning', - 'natal_kick_array': [528.2970725443025, 4.190728383757787, 1.1521129697118118, 5.015343794234789]}) - star_2 = SingleStar(**{'mass': 15.641392951875442, 'state': 'H-rich_Core_H_burning', - 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) - binary = BinaryStar(star_1, star_2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', - 'orbital_period': 151.99252706449792,'eccentricity': 0.0}, properties = sim_prop) - ######################################## - # FIXED disrupted crash - ######################################## - STAR1 = SingleStar(**{'mass': 52.967313, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) - STAR2 = SingleStar(**{'mass': 36.306444, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) - BINARY = BinaryStar(STAR1, STAR2, - **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':12.877004, 'eccentricity': 0.0}, - properties = sim_prop) - evolve_binary(BINARY) - ######################################## - # FIXED error with SN type - ######################################## - STAR1 = SingleStar(**{'mass': 17.782576, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) - STAR2 = SingleStar(**{'mass':3.273864, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) - BINARY = BinaryStar(STAR1, STAR2, - **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':4513.150157, 'eccentricity': 0.0}, - properties = sim_prop) - evolve_binary(BINARY) - ######################################## - # FIXED oRLO2 looping - ######################################## - STAR1 = SingleStar(**{'mass': 170.638207, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array': [4.921294, 4.31745, 1.777768, 3.509656]}) - STAR2 = SingleStar(**{'mass':37.917852, - 'state': 'H-rich_Core_H_burning', + binary = BinaryStar(star_1, star_2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', + 'orbital_period': 190925.99636740884,'eccentricity': 0.0}, properties = sim_prop) + evolve_binary(binary, h5file, binary_id) + binary_id+=1 + ######################################## + # Failing binary in matching + ######################################## + star_1 = SingleStar(**{'mass': 30.169861921689556, 'state': 'H-rich_Core_H_burning','metallicity':1, + 'natal_kick_array': [77.96834852144123, 0.05021460132555987, 2.3146518208348152, 1.733054979982291]}) + star_2 = SingleStar(**{'mass': 10.972734402996027, 'state': 'H-rich_Core_H_burning','metallicity':1, 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) - - BINARY = BinaryStar(STAR1, STAR2, - **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':113.352736, 'eccentricity': 0.0}, - properties = sim_prop) - evolve_binary(BINARY) - ######################################## - # Redirect to step_CO_HeMS (H-rich non-burning?) - ######################################## - star_1 = SingleStar(**{'mass': 8.333579, 'state': 'H-rich_Core_H_burning',\ - 'natal_kick_array': [17.125568, 4.101834, 0.917541, 3.961291]}) - star_2 = SingleStar(**{'mass' : 8.208376, 'state' : 'H-rich_Core_H_burning', - 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - binary = BinaryStar(star_1, star_2, - **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period': 66.870417, 'eccentricity': 0.0}, - properties = sim_prop) - evolve_binary(binary) - ######################################## - # FIXED oRLO2 looping - ######################################## - star_1 = SingleStar(**{'mass': 16.921378, 'state': 'H-rich_Core_H_burning',\ - 'natal_kick_array': [268.837139, 5.773527, 2.568105, 2.519068]}) - star_2 = SingleStar(**{'mass' : 16.286318, 'state' : 'H-rich_Core_H_burning', - 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - binary = BinaryStar(star_1, star_2, - **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period': 37.958768, 'eccentricity': 0.0}, - properties = sim_prop) - evolve_binary(binary) - ######################################## - # FIXED? step_detached failure - ######################################## - STAR1 = SingleStar(**{'mass': 19.787769, 'state': 'H-rich_Core_H_burning', - 'natal_kick_array': [24.464803, 0.666314, 1.954698, 5.598975]}) - STAR2 = SingleStar(**{'mass': 7.638741, 'state': 'H-rich_Core_H_burning', - 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - BINARY = BinaryStar(STAR1, STAR2, - **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':3007.865561, 'eccentricity': 0.0}, - properties = sim_prop) - evolve_binary(BINARY) - ######################################## - # Disrupted binary - ######################################## - star_1 = SingleStar(**{'mass': 16.921378, 'state': 'H-rich_Core_H_burning',\ - 'natal_kick_array': [268.837139, 5.773527, 2.568105, 2.519068]}) - star_2 = SingleStar(**{'mass' : 16.286318, 'state' : 'H-rich_Core_H_burning', - 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - - BINARY = BinaryStar(star_1, star_2, - **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':3007.865561, 'eccentricity': 0.0}, - properties = sim_prop) - evolve_binary(BINARY) - ######################################## - # FIXED Detached binary failure (low mass) - ######################################## - STAR1 = SingleStar(**{'mass': 9, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - STAR2 = SingleStar(**{'mass':0.8, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - - BINARY = BinaryStar(STAR1, STAR2, - **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':4513.150157, 'eccentricity': 0.0}, - properties = sim_prop) - evolve_binary(BINARY) - ######################################## - # FIXED SN_TYPE = None crash - ######################################## - STAR1 = SingleStar(**{'mass': 17.782576, + binary = BinaryStar(star_1, star_2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', + 'orbital_period': 20479.71919353725,'eccentricity': 0.0}, properties = sim_prop) + evolve_binary(binary, h5file, binary_id) + binary_id+=1 + ######################################## + # flipped S1 and S2 ? + ######################################## + star_1 = SingleStar(**{'mass': 9.474917413943635, 'state': 'H-rich_Core_H_burning','metallicity':1, + 'natal_kick_array': [133.5713935237759, 4.398754864537542, 2.703102872841114, 1.4633904612711142]}) + star_2 = SingleStar(**{'mass': 9.311073918196263, 'state': 'H-rich_Core_H_burning','metallicity':1, + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) + binary = BinaryStar(star_1, star_2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', + 'orbital_period': 18.605997832086413,'eccentricity': 0.0}, properties = sim_prop) + + evolve_binary(binary, h5file, binary_id) + binary_id+=1 + ######################################## + # flipped S1 and S2 + ######################################## + star_1 = SingleStar(**{'mass': 10.438541, 'state': 'H-rich_Core_H_burning','metallicity':1, + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) + star_2 = SingleStar(**{'mass': 1.400713, 'state': 'H-rich_Core_H_burning','metallicity':1, + 'natal_kick_array': [0.0, 4.190728383757787, 1.1521129697118118, 5.015343794234789]}) + binary = BinaryStar(star_1, star_2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', + 'orbital_period': 9.824025,'eccentricity': 0.0}, properties = sim_prop) + evolve_binary(binary, h5file, binary_id) + binary_id+=1 + ######################################## + # flipped S1 and S2 + ######################################## + star_1= SingleStar(**{'mass': 9.845907 , 'state': 'H-rich_Core_H_burning','metallicity':1, + 'natal_kick_array': [0.0, 4.190728383757787, 1.1521129697118118, 5.015343794234789]}) + star_2 = SingleStar(**{'mass': 9.611029, 'state': 'H-rich_Core_H_burning','metallicity':1, + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) + binary = BinaryStar(star_1, star_2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', + 'orbital_period': 3.820571,'eccentricity': 0.0}, properties = sim_prop) + evolve_binary(binary, h5file, binary_id) + binary_id+=1 + ######################################## + # Normal binary evolution + ######################################## + star_1= SingleStar(**{'mass': 30.845907 , 'state': 'H-rich_Core_H_burning','metallicity':1, + 'natal_kick_array': [0.0, 4.190728383757787, 1.1521129697118118, 5.015343794234789]}) + star_2 = SingleStar(**{'mass': 30.611029, 'state': 'H-rich_Core_H_burning','metallicity':1, + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) + binary = BinaryStar(star_1, star_2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', + 'orbital_period': 30.820571,'eccentricity': 0.0}, properties = sim_prop) + evolve_binary(binary, h5file, binary_id) + binary_id+=1 + ######################################## + # Normal binary + ######################################## + star_1= SingleStar(**{'mass': 9.213534679594247 , 'state': 'H-rich_Core_H_burning','metallicity':1, + 'natal_kick_array': [327.5906384501521, 1.7707176050073297, 1.573225822966838, 1.6757313876001914]}) + star_2 = SingleStar(**{'mass': 7.209878522799272, 'state': 'H-rich_Core_H_burning','metallicity':1, + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) + binary = BinaryStar(star_1, star_2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', + 'orbital_period': 63123.74544474666,'eccentricity': 0.0}, properties = sim_prop) + evolve_binary(binary, h5file, binary_id) + binary_id+=1 + ######################################## + # Normal binary + ######################################## + star_1= SingleStar(**{'mass': 9.561158487732602 , 'state': 'H-rich_Core_H_burning','metallicity':1, + 'natal_kick_array': [317.5423844462847, 2.9095984678057603, 1.754121288652108, 2.3693917842468784]}) + star_2 = SingleStar(**{'mass': 9.382732464319286, 'state': 'H-rich_Core_H_burning','metallicity':1, + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) + binary = BinaryStar(star_1, star_2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', + 'orbital_period': 27.77657038557851,'eccentricity': 0.0}, properties = sim_prop) + evolve_binary(binary, h5file, binary_id) + binary_id+=1 + ######################################## + # Normal binary + ######################################## + star1 = SingleStar(**{'mass': 7.552858,#29829485, + 'state': 'H-rich_Core_H_burning', + 'natal_kick_array': [40.91509926587841, 2.6295454150818256, 1.6718337470964977, 6.0408769315244895]}) + star2 = SingleStar(**{'mass': 6.742063, #481560266, + 'state': 'H-rich_Core_H_burning', + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) + binary = BinaryStar(star1, star2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', + 'orbital_period': 17.957531550841225, 'eccentricity': 0.0,}, + properties=sim_prop) + evolve_binary(binary, h5file, binary_id) + binary_id+=1 + ######################################## + # High BH spin options + ######################################## + star_1 = SingleStar(**{'mass': 31.616785, 'state': 'H-rich_Core_H_burning', + 'natal_kick_array': [10, 4.190728383757787, 1.1521129697118118, 5.015343794234789]}) + star_2 = SingleStar(**{'mass': 26.874267, 'state': 'H-rich_Core_H_burning', + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) + binary = BinaryStar(star_1, star_2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', + 'orbital_period': 501.99252706449792,'eccentricity': 0.0}, properties = sim_prop) + evolve_binary(binary, h5file, binary_id) + binary_id+=1 + ######################################## + # Original a>1 spin error + ######################################## + star_1 = SingleStar(**{'mass': 18.107506844123645, 'state': 'H-rich_Core_H_burning', + 'natal_kick_array': [528.2970725443025, 4.190728383757787, 1.1521129697118118, 5.015343794234789]}) + star_2 = SingleStar(**{'mass': 15.641392951875442, 'state': 'H-rich_Core_H_burning', + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) + binary = BinaryStar(star_1, star_2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', + 'orbital_period': 151.99252706449792,'eccentricity': 0.0}, properties = sim_prop) + evolve_binary(binary, h5file, binary_id) + binary_id+=1 + ######################################## + # FIXED disrupted crash + ######################################## + star1 = SingleStar(**{'mass': 52.967313, + 'state': 'H-rich_Core_H_burning', + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) + star2 = SingleStar(**{'mass': 36.306444, + 'state': 'H-rich_Core_H_burning', + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) + binary = BinaryStar(star1, star2, + **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':12.877004, 'eccentricity': 0.0}, + properties = sim_prop) + evolve_binary(binary, h5file, binary_id) + binary_id+=1 + ######################################## + # FIXED error with SN type + ######################################## + star1 = SingleStar(**{'mass': 17.782576, 'state': 'H-rich_Core_H_burning', - 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - STAR2 = SingleStar(**{'mass':3.273864, + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) + star2 = SingleStar(**{'mass':3.273864, 'state': 'H-rich_Core_H_burning', - 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - - BINARY = BinaryStar(STAR1, STAR2, + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) + binary = BinaryStar(star1, star2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':4513.150157, 'eccentricity': 0.0}, properties = sim_prop) - evolve_binary(BINARY) - ######################################## - # FIXED SN_TYPE errors - ######################################## - STAR1 = SingleStar(**{'mass': 6.782576, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - STAR2 = SingleStar(**{'mass':3.273864, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - - BINARY = BinaryStar(STAR1, STAR2, - **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':4513.150157, 'eccentricity': 0.0}, - properties = sim_prop) - evolve_binary(BINARY) - ######################################## - # FIXED SN_TYPE errors - ######################################## - STAR1 = SingleStar(**{'mass': 40.638207, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array': [30.921294, 4.31745, 1.777768, 3.509656]}) - STAR2 = SingleStar(**{'mass':37.917852, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - - BINARY = BinaryStar(STAR1, STAR2, - **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':2113.352736, 'eccentricity': 0.0}, - properties = sim_prop) - evolve_binary(BINARY) - ######################################## - # FIXED ECSN errors? - ######################################## - STAR1 = SingleStar(**{'mass': 12.376778, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array': [80, 4.31745, 1.777768, 3.509656]}) - STAR2 = SingleStar(**{'mass': 9.711216, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - - - BINARY = BinaryStar(STAR1, STAR2, - **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':79.83702, 'eccentricity': 0.0}, - properties = sim_prop) - evolve_binary(BINARY) - ######################################## - # Interpolator masses?? - ######################################## - STAR1 = SingleStar(**{'mass': 7.592921, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - STAR2 = SingleStar(**{'mass':5.038679 , - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - - BINARY = BinaryStar(STAR1, STAR2, - **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':5.537807, 'eccentricity': 0.0}, - properties = sim_prop) - evolve_binary(BINARY) - ######################################## - # Interpolator masses? - ######################################## - star_1 = SingleStar(**{'mass': 38.741115, - 'state': 'H-rich_Core_H_burning',\ - 'natal_kick_array': [21.113771, 2.060135, 2.224789, 4.089729]}) - star_2 = SingleStar(**{'mass': 27.776178, - 'state': 'H-rich_Core_H_burning',\ - 'natal_kick_array': [282.712103, 0.296252, 1.628433, 5.623812]}) - - BINARY = BinaryStar(star_1, star_2, - **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period': 93.387072, 'eccentricity': 0.0}, - properties = sim_prop) - evolve_binary(BINARY) - ######################################## - # FIXED NaN spin - ######################################## - STAR1 = SingleStar(**{'mass': 70.066924, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array':[0.0, 0.0, 0.0, 0.0], - 'metallicity':1}) - STAR2 = SingleStar(**{'mass': 34.183110, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array':[0.0, 0.0, 0.0, 0.0], - 'metallicity':1}) - BINARY = BinaryStar(STAR1, STAR2, - **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':5.931492e+03, - 'separation': orbital_separation_from_period(5.931492e+03, STAR1.mass, STAR2.mass), - 'eccentricity': 0.0}, - properties = sim_prop) - evolve_binary(BINARY) - ######################################## - # FIXED NaN spin - ######################################## - STAR1 = SingleStar(**{'mass': 28.837286, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - STAR2 = SingleStar(**{'mass': 6.874867, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - - BINARY = BinaryStar(STAR1, STAR2, - **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':35.609894, - 'separation': orbital_separation_from_period(35.609894, STAR1.mass, STAR2.mass), - 'eccentricity': 0.0}, - properties = sim_prop) - evolve_binary(BINARY) - ######################################## - # oRLO2 issue - ######################################## - STAR1 = SingleStar(**{'mass':29.580210, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - STAR2 = SingleStar(**{'mass': 28.814626, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - - BINARY = BinaryStar(STAR1, STAR2, - **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':40.437993, 'eccentricity': 0.0}, - properties = sim_prop) - evolve_binary(BINARY) - - ######################################## - # oRLO2 issue - ######################################## - STAR1 = SingleStar(**{'mass':67.126795, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - STAR2 = SingleStar(**{'mass': 19.622908, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - - BINARY = BinaryStar(STAR1, STAR2, - **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':1484.768582, 'eccentricity': 0.0}, - properties = sim_prop) - evolve_binary(BINARY) - - ######################################## - # oRLO2 issue - ######################################## - STAR1 = SingleStar(**{'mass': 58.947503, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - STAR2 = SingleStar(**{'mass': 56.660506, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - - BINARY = BinaryStar(STAR1, STAR2, - **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':2011.300659, 'eccentricity': 0.0}, - properties = sim_prop) - evolve_binary(BINARY) - - ######################################## - # oRLO2 issue - ######################################## - STAR1 = SingleStar(**{'mass': 170.638207, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array':[47.979957374424956, 5.317304576107798, 2.7259013166068145, 4.700929589520818]}) - STAR2 = SingleStar(**{'mass': 37.917852, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - - BINARY = BinaryStar(STAR1, STAR2, - **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':113.352736, 'eccentricity': 0.0}, - properties = sim_prop) - evolve_binary(BINARY) - - ######################################## - # oRLO2 issue - ######################################## - STAR1 = SingleStar(**{'mass': 109.540207, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - STAR2 = SingleStar(**{'mass': 84.344530, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - - BINARY = BinaryStar(STAR1, STAR2, - **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':5.651896, 'eccentricity': 0.0}, + evolve_binary(binary, h5file, binary_id) + binary_id+=1 + ######################################## + # FIXED oRLO2 looping + ######################################## + star1 = SingleStar(**{'mass': 170.638207, + 'state': 'H-rich_Core_H_burning', + 'natal_kick_array': [4.921294, 4.31745, 1.777768, 3.509656]}) + star2 = SingleStar(**{'mass':37.917852, + 'state': 'H-rich_Core_H_burning', + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) + + binary = BinaryStar(star1, star2, + **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':113.352736, 'eccentricity': 0.0}, + properties = sim_prop) + evolve_binary(binary, h5file, binary_id) + binary_id+=1 + ######################################## + # Redirect to step_CO_HeMS (H-rich non-burning?) + ######################################## + star_1 = SingleStar(**{'mass': 8.333579, 'state': 'H-rich_Core_H_burning',\ + 'natal_kick_array': [17.125568, 4.101834, 0.917541, 3.961291]}) + star_2 = SingleStar(**{'mass' : 8.208376, 'state' : 'H-rich_Core_H_burning', + 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) + binary = BinaryStar(star_1, star_2, + **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period': 66.870417, 'eccentricity': 0.0}, + properties = sim_prop) + evolve_binary(binary, h5file, binary_id) + binary_id+=1 + ######################################## + # FIXED oRLO2 looping + ######################################## + star_1 = SingleStar(**{'mass': 16.921378, 'state': 'H-rich_Core_H_burning',\ + 'natal_kick_array': [268.837139, 5.773527, 2.568105, 2.519068]}) + star_2 = SingleStar(**{'mass' : 16.286318, 'state' : 'H-rich_Core_H_burning', + 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) + binary = BinaryStar(star_1, star_2, + **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period': 37.958768, 'eccentricity': 0.0}, + properties = sim_prop) + evolve_binary(binary, h5file, binary_id) + binary_id+=1 + ######################################## + # FIXED? step_detached failure + ######################################## + star1 = SingleStar(**{'mass': 19.787769, 'state': 'H-rich_Core_H_burning', + 'natal_kick_array': [24.464803, 0.666314, 1.954698, 5.598975]}) + star2 = SingleStar(**{'mass': 7.638741, 'state': 'H-rich_Core_H_burning', + 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) + binary = BinaryStar(star1, star2, + **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':3007.865561, 'eccentricity': 0.0}, properties = sim_prop) - evolve_binary(BINARY) - - ######################################## - # redirect - ######################################## - STAR1 = SingleStar(**{'mass': 13.889634, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - STAR2 = SingleStar(**{'mass':0.490231, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - - BINARY = BinaryStar(STAR1, STAR2, - **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':14513.150157, 'eccentricity': 0.0}, + evolve_binary(binary, h5file, binary_id) + binary_id+=1 + ######################################## + # Disrupted binary + ######################################## + star_1 = SingleStar(**{'mass': 16.921378, 'state': 'H-rich_Core_H_burning',\ + 'natal_kick_array': [268.837139, 5.773527, 2.568105, 2.519068]}) + star_2 = SingleStar(**{'mass' : 16.286318, 'state' : 'H-rich_Core_H_burning', + 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) + + binary = BinaryStar(star_1, star_2, + **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':3007.865561, 'eccentricity': 0.0}, properties = sim_prop) - evolve_binary(BINARY) - ######################################## - # redirect - ######################################## - STAR1 = SingleStar(**{'mass': 9, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - STAR2 = SingleStar(**{'mass':0.8, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - - BINARY = BinaryStar(STAR1, STAR2, + evolve_binary(binary, h5file, binary_id) + binary_id+=1 + ######################################## + # FIXED Detached binary failure (low mass) + ######################################## + star1 = SingleStar(**{'mass': 9, + 'state': 'H-rich_Core_H_burning', + 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) + star2 = SingleStar(**{'mass':0.8, + 'state': 'H-rich_Core_H_burning', + 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) + + binary = BinaryStar(star1, star2, + **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':4513.150157, 'eccentricity': 0.0}, + properties = sim_prop) + evolve_binary(binary, h5file, binary_id) + binary_id+=1 + ######################################## + # FIXED SN_TYPE = None crash + ######################################## + star1 = SingleStar(**{'mass': 17.782576, + 'state': 'H-rich_Core_H_burning', + 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) + star2 = SingleStar(**{'mass':3.273864, + 'state': 'H-rich_Core_H_burning', + 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) + + binary = BinaryStar(star1, star2, + **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':4513.150157, 'eccentricity': 0.0}, + properties = sim_prop) + evolve_binary(binary, h5file, binary_id) + binary_id+=1 + ######################################## + # FIXED SN_TYPE errors + ######################################## + star1 = SingleStar(**{'mass': 6.782576, + 'state': 'H-rich_Core_H_burning', + 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) + star2 = SingleStar(**{'mass':3.273864, + 'state': 'H-rich_Core_H_burning', + 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) + + binary = BinaryStar(star1, star2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':4513.150157, 'eccentricity': 0.0}, properties = sim_prop) - evolve_binary(BINARY) - ######################################## - # Max time - ######################################## - star_1 = SingleStar(**{'mass': 103.07996766780799, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array': [0.0, 0.2965418610971261, 2.0789170290719117, 3.207488023705968]}) - star_2 = SingleStar(**{'mass': 83.66522615073987, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) - binary = BinaryStar(star_1, star_2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', - 'orbital_period': 1449.1101985875678,'eccentricity': 0.0}, properties = sim_prop) - evolve_binary(binary) - ######################################## - # Max time - ######################################## - star_1 = SingleStar(**{'mass': 8.860934140643465, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array': [11.818027275431337, 2.812412688633058, 0.4998731824233789, 2.9272630485628643]}) - star_2 = SingleStar(**{'mass': 8.584716012668551, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) - binary = BinaryStar(star_1, star_2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', - 'orbital_period': 20.82030114750744,'eccentricity': 0.0}, properties = sim_prop) - evolve_binary(binary) - ######################################## - # PR421 - ######################################## - STAR1 = SingleStar(**{'mass': 24.035366, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - STAR2 = SingleStar(**{'mass': 23.187355, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - - BINARY = BinaryStar(STAR1, STAR2, - **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':18.865029, 'eccentricity': 0.0}, - properties = sim_prop) - evolve_binary(BINARY) - - ######################################## - # CE class - ######################################## - STAR1 = SingleStar(**{'mass':33.964274, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - STAR2 = SingleStar(**{'mass': 28.98149, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - - BINARY = BinaryStar(STAR1, STAR2, - **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':82.370989, 'eccentricity': 0.0}, - properties = sim_prop) - evolve_binary(BINARY) - - ######################################## - # PR574 - stepCE fix - ######################################## - STAR1 = SingleStar(**{'mass':29.580210, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - STAR2 = SingleStar(**{'mass': 28.814626*0.4, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - - BINARY = BinaryStar(STAR1, STAR2, - **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':300.437993, 'eccentricity': 0.0}, - properties = sim_prop) - evolve_binary(BINARY) - - ######################################## - # e_ZAMS error - ######################################## - star1 = SingleStar(**{'mass': 8.161885721822461, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) - star2 = SingleStar(**{'mass': 3.5907829421526154, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) - - binary = BinaryStar(star1, star2, - **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period': 36.873457164644144, 'eccentricity': 0.0}, - properties = sim_prop) - evolve_binary(binary) - - ######################################## - # e_ZAMS error - ######################################## - star1 = SingleStar(**{'mass': 35.24755025317775, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array': [19.755993125895806, 0.37149222852233904, 1.6588846085306563, - 1.434617029858906]}) - star2 = SingleStar(**{'mass': 30.000450298072902, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) - - binary = BinaryStar(star1, star2, - **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period': 24060.02101364665, 'eccentricity': 0.8085077857996965}, - properties = sim_prop) - evolve_binary(binary) - - ######################################## - # e_ZAMS error - ######################################## - star1 = SingleStar(**{'mass': 11.862930493162692, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) - star2 = SingleStar(**{'mass': 1.4739109294156703, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) - - binary = BinaryStar(star1, star2, - **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period': 4111.083887312003, 'eccentricity':0.0}, - properties = sim_prop) - evolve_binary(binary) - - ######################################## - # e_ZAMS error - ######################################## - star1 = SingleStar(**{'mass': 8.527361341212108, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) - star2 = SingleStar(**{'mass': 0.7061748406821822, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) - - binary = BinaryStar(star1, star2, - **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period': 2521.1927287891444, 'eccentricity':0.0}, - properties = sim_prop) - evolve_binary(binary) - - ######################################## - # e_ZAMS error - ######################################## - star1 = SingleStar(**{'mass': 13.661942533447398 ,#29829485, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) - star2 = SingleStar(**{'mass': 4.466151109802313 , #481560266, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) - - binary = BinaryStar(star1, star2, - **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':3110.1346707516914, 'eccentricity':0.0}, + evolve_binary(binary, h5file, binary_id) + binary_id+=1 + ######################################## + # FIXED SN_TYPE errors + ######################################## + star1 = SingleStar(**{'mass': 40.638207, + 'state': 'H-rich_Core_H_burning', + 'natal_kick_array': [30.921294, 4.31745, 1.777768, 3.509656]}) + star2 = SingleStar(**{'mass':37.917852, + 'state': 'H-rich_Core_H_burning', + 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) + + binary = BinaryStar(star1, star2, + **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':2113.352736, 'eccentricity': 0.0}, + properties = sim_prop) + evolve_binary(binary, h5file, binary_id) + binary_id+=1 + ######################################## + # FIXED ECSN errors? + ######################################## + star1 = SingleStar(**{'mass': 12.376778, + 'state': 'H-rich_Core_H_burning', + 'natal_kick_array': [80, 4.31745, 1.777768, 3.509656]}) + star2 = SingleStar(**{'mass': 9.711216, + 'state': 'H-rich_Core_H_burning', + 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) + + + binary = BinaryStar(star1, star2, + **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':79.83702, 'eccentricity': 0.0}, + properties = sim_prop) + evolve_binary(binary, h5file, binary_id) + binary_id+=1 + ######################################## + # Interpolator masses?? + ######################################## + star1 = SingleStar(**{'mass': 7.592921, + 'state': 'H-rich_Core_H_burning', + 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) + star2 = SingleStar(**{'mass':5.038679 , + 'state': 'H-rich_Core_H_burning', + 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) + + binary = BinaryStar(star1, star2, + **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':5.537807, 'eccentricity': 0.0}, properties = sim_prop) - evolve_binary(binary) + evolve_binary(binary, h5file, binary_id) + binary_id+=1 + ######################################## + # Interpolator masses? + ######################################## + star_1 = SingleStar(**{'mass': 38.741115, + 'state': 'H-rich_Core_H_burning',\ + 'natal_kick_array': [21.113771, 2.060135, 2.224789, 4.089729]}) + star_2 = SingleStar(**{'mass': 27.776178, + 'state': 'H-rich_Core_H_burning',\ + 'natal_kick_array': [282.712103, 0.296252, 1.628433, 5.623812]}) + + binary = BinaryStar(star_1, star_2, + **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period': 93.387072, 'eccentricity': 0.0}, + properties = sim_prop) + evolve_binary(binary, h5file, binary_id) + binary_id+=1 + ######################################## + # FIXED NaN spin + ######################################## + star1 = SingleStar(**{'mass': 70.066924, + 'state': 'H-rich_Core_H_burning', + 'natal_kick_array':[0.0, 0.0, 0.0, 0.0], + 'metallicity':1}) + star2 = SingleStar(**{'mass': 34.183110, + 'state': 'H-rich_Core_H_burning', + 'natal_kick_array':[0.0, 0.0, 0.0, 0.0], + 'metallicity':1}) + binary = BinaryStar(star1, star2, + **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':5.931492e+03, + 'separation': orbital_separation_from_period(5.931492e+03, star1.mass, star2.mass), + 'eccentricity': 0.0}, + properties = sim_prop) + evolve_binary(binary, h5file, binary_id) + binary_id+=1 + ######################################## + # FIXED NaN spin + ######################################## + star1 = SingleStar(**{'mass': 28.837286, + 'state': 'H-rich_Core_H_burning', + 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) + star2 = SingleStar(**{'mass': 6.874867, + 'state': 'H-rich_Core_H_burning', + 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) + + binary = BinaryStar(star1, star2, + **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':35.609894, + 'separation': orbital_separation_from_period(35.609894, star1.mass, star2.mass), + 'eccentricity': 0.0}, + properties = sim_prop) + evolve_binary(binary, h5file, binary_id) + binary_id+=1 + ######################################## + # oRLO2 issue + ######################################## + star1 = SingleStar(**{'mass':29.580210, + 'state': 'H-rich_Core_H_burning', + 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) + star2 = SingleStar(**{'mass': 28.814626, + 'state': 'H-rich_Core_H_burning', + 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) + + binary = BinaryStar(star1, star2, + **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':40.437993, 'eccentricity': 0.0}, + properties = sim_prop) + evolve_binary(binary, h5file, binary_id) + binary_id+=1 + ######################################## + # oRLO2 issue + ######################################## + star1 = SingleStar(**{'mass':67.126795, + 'state': 'H-rich_Core_H_burning', + 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) + star2 = SingleStar(**{'mass': 19.622908, + 'state': 'H-rich_Core_H_burning', + 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) + + binary = BinaryStar(star1, star2, + **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':1484.768582, 'eccentricity': 0.0}, + properties = sim_prop) + evolve_binary(binary, h5file, binary_id) + binary_id+=1 + ######################################## + # oRLO2 issue + ######################################## + star1 = SingleStar(**{'mass': 58.947503, + 'state': 'H-rich_Core_H_burning', + 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) + star2 = SingleStar(**{'mass': 56.660506, + 'state': 'H-rich_Core_H_burning', + 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) + + binary = BinaryStar(star1, star2, + **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':2011.300659, 'eccentricity': 0.0}, + properties = sim_prop) + evolve_binary(binary, h5file, binary_id) + binary_id+=1 + ######################################## + # oRLO2 issue + ######################################## + star1 = SingleStar(**{'mass': 170.638207, + 'state': 'H-rich_Core_H_burning', + 'natal_kick_array':[47.979957374424956, 5.317304576107798, 2.7259013166068145, 4.700929589520818]}) + star2 = SingleStar(**{'mass': 37.917852, + 'state': 'H-rich_Core_H_burning', + 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) + + binary = BinaryStar(star1, star2, + **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':113.352736, 'eccentricity': 0.0}, + properties = sim_prop) + evolve_binary(binary, h5file, binary_id) + binary_id+=1 + ######################################## + # oRLO2 issue + ######################################## + star1 = SingleStar(**{'mass': 109.540207, + 'state': 'H-rich_Core_H_burning', + 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) + star2 = SingleStar(**{'mass': 84.344530, + 'state': 'H-rich_Core_H_burning', + 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) + + binary = BinaryStar(star1, star2, + **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':5.651896, 'eccentricity': 0.0}, + properties = sim_prop) + evolve_binary(binary, h5file, binary_id) + binary_id+=1 + ######################################## + # redirect + ######################################## + star1 = SingleStar(**{'mass': 13.889634, + 'state': 'H-rich_Core_H_burning', + 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) + star2 = SingleStar(**{'mass':0.490231, + 'state': 'H-rich_Core_H_burning', + 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) + + binary = BinaryStar(star1, star2, + **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':14513.150157, 'eccentricity': 0.0}, + properties = sim_prop) + evolve_binary(binary, h5file, binary_id) + binary_id+=1 + ######################################## + # redirect + ######################################## + star1 = SingleStar(**{'mass': 9, + 'state': 'H-rich_Core_H_burning', + 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) + star2 = SingleStar(**{'mass':0.8, + 'state': 'H-rich_Core_H_burning', + 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) + + binary = BinaryStar(star1, star2, + **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':4513.150157, 'eccentricity': 0.0}, + properties = sim_prop) + evolve_binary(binary, h5file, binary_id) + binary_id+=1 + ######################################## + # Max time + ######################################## + star_1 = SingleStar(**{'mass': 103.07996766780799, + 'state': 'H-rich_Core_H_burning', + 'natal_kick_array': [0.0, 0.2965418610971261, 2.0789170290719117, 3.207488023705968]}) + star_2 = SingleStar(**{'mass': 83.66522615073987, + 'state': 'H-rich_Core_H_burning', + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) + binary = BinaryStar(star_1, star_2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', + 'orbital_period': 1449.1101985875678,'eccentricity': 0.0}, properties = sim_prop) + evolve_binary(binary, h5file, binary_id) + binary_id+=1 + ######################################## + # Max time + ######################################## + star_1 = SingleStar(**{'mass': 8.860934140643465, + 'state': 'H-rich_Core_H_burning', + 'natal_kick_array': [11.818027275431337, 2.812412688633058, 0.4998731824233789, 2.9272630485628643]}) + star_2 = SingleStar(**{'mass': 8.584716012668551, + 'state': 'H-rich_Core_H_burning', + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) + binary = BinaryStar(star_1, star_2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', + 'orbital_period': 20.82030114750744,'eccentricity': 0.0}, properties = sim_prop) + evolve_binary(binary, h5file, binary_id) + binary_id+=1 + ######################################## + # PR421 + ######################################## + star1 = SingleStar(**{'mass': 24.035366, + 'state': 'H-rich_Core_H_burning', + 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) + star2 = SingleStar(**{'mass': 23.187355, + 'state': 'H-rich_Core_H_burning', + 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) + + binary = BinaryStar(star1, star2, + **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':18.865029, 'eccentricity': 0.0}, + properties = sim_prop) + evolve_binary(binary, h5file, binary_id) + binary_id+=1 + ######################################## + # CE class + ######################################## + star1 = SingleStar(**{'mass':33.964274, + 'state': 'H-rich_Core_H_burning', + 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) + star2 = SingleStar(**{'mass': 28.98149, + 'state': 'H-rich_Core_H_burning', + 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) + + binary = BinaryStar(star1, star2, + **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':82.370989, 'eccentricity': 0.0}, + properties = sim_prop) + evolve_binary(binary, h5file, binary_id) + binary_id+=1 + ######################################## + # PR574 - stepCE fix + ######################################## + star1 = SingleStar(**{'mass':29.580210, + 'state': 'H-rich_Core_H_burning', + 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) + star2 = SingleStar(**{'mass': 28.814626*0.4, + 'state': 'H-rich_Core_H_burning', + 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) + + binary = BinaryStar(star1, star2, + **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':300.437993, 'eccentricity': 0.0}, + properties = sim_prop) + evolve_binary(binary, h5file, binary_id) + binary_id+=1 + ######################################## + # e_ZAMS error + ######################################## + star1 = SingleStar(**{'mass': 8.161885721822461, + 'state': 'H-rich_Core_H_burning', + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) + star2 = SingleStar(**{'mass': 3.5907829421526154, + 'state': 'H-rich_Core_H_burning', + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) + + binary = BinaryStar(star1, star2, + **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period': 36.873457164644144, 'eccentricity': 0.0}, + properties = sim_prop) + evolve_binary(binary, h5file, binary_id) + binary_id+=1 + ######################################## + # e_ZAMS error + ######################################## + star1 = SingleStar(**{'mass': 35.24755025317775, + 'state': 'H-rich_Core_H_burning', + 'natal_kick_array': [19.755993125895806, 0.37149222852233904, 1.6588846085306563, + 1.434617029858906]}) + star2 = SingleStar(**{'mass': 30.000450298072902, + 'state': 'H-rich_Core_H_burning', + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) + + binary = BinaryStar(star1, star2, + **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period': 24060.02101364665, 'eccentricity': 0.8085077857996965}, + properties = sim_prop) + evolve_binary(binary, h5file, binary_id) + binary_id+=1 + ######################################## + # e_ZAMS error + ######################################## + star1 = SingleStar(**{'mass': 11.862930493162692, + 'state': 'H-rich_Core_H_burning', + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) + star2 = SingleStar(**{'mass': 1.4739109294156703, + 'state': 'H-rich_Core_H_burning', + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) + + binary = BinaryStar(star1, star2, + **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period': 4111.083887312003, 'eccentricity':0.0}, + properties = sim_prop) + evolve_binary(binary, h5file, binary_id) + binary_id+=1 + ######################################## + # e_ZAMS error + ######################################## + star1 = SingleStar(**{'mass': 8.527361341212108, + 'state': 'H-rich_Core_H_burning', + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) + star2 = SingleStar(**{'mass': 0.7061748406821822, + 'state': 'H-rich_Core_H_burning', + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) + + binary = BinaryStar(star1, star2, + **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period': 2521.1927287891444, 'eccentricity':0.0}, + properties = sim_prop) + evolve_binary(binary, h5file, binary_id) + binary_id+=1 + ######################################## + # e_ZAMS error + ######################################## + star1 = SingleStar(**{'mass': 13.661942533447398 ,#29829485, + 'state': 'H-rich_Core_H_burning', + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) + star2 = SingleStar(**{'mass': 4.466151109802313 , #481560266, + 'state': 'H-rich_Core_H_burning', + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) + + binary = BinaryStar(star1, star2, + **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':3110.1346707516914, 'eccentricity':0.0}, + properties = sim_prop) + evolve_binary(binary, h5file, binary_id) + binary_id+=1 if __name__ == "__main__": parser = argparse.ArgumentParser(description='Evolve binaries for validation.') @@ -780,4 +816,4 @@ def evolve_binaries(verbose): help="Path to save HDF5 output") args = parser.parse_args() - evolve_binaries(verbose=args.verbose) + evolve_binaries(verbose=args.verbose, args.output) From 82392909bc5d53ba972de7b62223874f544723e4 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Thu, 18 Dec 2025 15:19:07 +0000 Subject: [PATCH 11/91] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- dev-tools/script_data/1Zsun_binaries_suite.py | 142 +++++++++--------- 1 file changed, 71 insertions(+), 71 deletions(-) diff --git a/dev-tools/script_data/1Zsun_binaries_suite.py b/dev-tools/script_data/1Zsun_binaries_suite.py index c632db2b34..9fbd21dbaf 100644 --- a/dev-tools/script_data/1Zsun_binaries_suite.py +++ b/dev-tools/script_data/1Zsun_binaries_suite.py @@ -206,7 +206,7 @@ def evolve_binaries(verbose,output_path): 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) binary = BinaryStar(star_1, star_2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period': 190925.99636740884,'eccentricity': 0.0}, properties = sim_prop) - evolve_binary(binary, h5file, binary_id) + evolve_binary(binary, h5file, binary_id) binary_id+=1 ######################################## # Failing binary in matching @@ -217,7 +217,7 @@ def evolve_binaries(verbose,output_path): 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) binary = BinaryStar(star_1, star_2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period': 20479.71919353725,'eccentricity': 0.0}, properties = sim_prop) - evolve_binary(binary, h5file, binary_id) + evolve_binary(binary, h5file, binary_id) binary_id+=1 ######################################## # flipped S1 and S2 ? @@ -228,8 +228,8 @@ def evolve_binaries(verbose,output_path): 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) binary = BinaryStar(star_1, star_2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period': 18.605997832086413,'eccentricity': 0.0}, properties = sim_prop) - - evolve_binary(binary, h5file, binary_id) + + evolve_binary(binary, h5file, binary_id) binary_id+=1 ######################################## # flipped S1 and S2 @@ -240,7 +240,7 @@ def evolve_binaries(verbose,output_path): 'natal_kick_array': [0.0, 4.190728383757787, 1.1521129697118118, 5.015343794234789]}) binary = BinaryStar(star_1, star_2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period': 9.824025,'eccentricity': 0.0}, properties = sim_prop) - evolve_binary(binary, h5file, binary_id) + evolve_binary(binary, h5file, binary_id) binary_id+=1 ######################################## # flipped S1 and S2 @@ -251,7 +251,7 @@ def evolve_binaries(verbose,output_path): 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) binary = BinaryStar(star_1, star_2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period': 3.820571,'eccentricity': 0.0}, properties = sim_prop) - evolve_binary(binary, h5file, binary_id) + evolve_binary(binary, h5file, binary_id) binary_id+=1 ######################################## # Normal binary evolution @@ -262,7 +262,7 @@ def evolve_binaries(verbose,output_path): 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) binary = BinaryStar(star_1, star_2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period': 30.820571,'eccentricity': 0.0}, properties = sim_prop) - evolve_binary(binary, h5file, binary_id) + evolve_binary(binary, h5file, binary_id) binary_id+=1 ######################################## # Normal binary @@ -273,7 +273,7 @@ def evolve_binaries(verbose,output_path): 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) binary = BinaryStar(star_1, star_2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period': 63123.74544474666,'eccentricity': 0.0}, properties = sim_prop) - evolve_binary(binary, h5file, binary_id) + evolve_binary(binary, h5file, binary_id) binary_id+=1 ######################################## # Normal binary @@ -284,7 +284,7 @@ def evolve_binaries(verbose,output_path): 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) binary = BinaryStar(star_1, star_2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period': 27.77657038557851,'eccentricity': 0.0}, properties = sim_prop) - evolve_binary(binary, h5file, binary_id) + evolve_binary(binary, h5file, binary_id) binary_id+=1 ######################################## # Normal binary @@ -298,7 +298,7 @@ def evolve_binaries(verbose,output_path): binary = BinaryStar(star1, star2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period': 17.957531550841225, 'eccentricity': 0.0,}, properties=sim_prop) - evolve_binary(binary, h5file, binary_id) + evolve_binary(binary, h5file, binary_id) binary_id+=1 ######################################## # High BH spin options @@ -309,7 +309,7 @@ def evolve_binaries(verbose,output_path): 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) binary = BinaryStar(star_1, star_2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period': 501.99252706449792,'eccentricity': 0.0}, properties = sim_prop) - evolve_binary(binary, h5file, binary_id) + evolve_binary(binary, h5file, binary_id) binary_id+=1 ######################################## # Original a>1 spin error @@ -320,7 +320,7 @@ def evolve_binaries(verbose,output_path): 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) binary = BinaryStar(star_1, star_2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period': 151.99252706449792,'eccentricity': 0.0}, properties = sim_prop) - evolve_binary(binary, h5file, binary_id) + evolve_binary(binary, h5file, binary_id) binary_id+=1 ######################################## # FIXED disrupted crash @@ -334,7 +334,7 @@ def evolve_binaries(verbose,output_path): binary = BinaryStar(star1, star2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':12.877004, 'eccentricity': 0.0}, properties = sim_prop) - evolve_binary(binary, h5file, binary_id) + evolve_binary(binary, h5file, binary_id) binary_id+=1 ######################################## # FIXED error with SN type @@ -348,7 +348,7 @@ def evolve_binaries(verbose,output_path): binary = BinaryStar(star1, star2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':4513.150157, 'eccentricity': 0.0}, properties = sim_prop) - evolve_binary(binary, h5file, binary_id) + evolve_binary(binary, h5file, binary_id) binary_id+=1 ######################################## # FIXED oRLO2 looping @@ -359,11 +359,11 @@ def evolve_binaries(verbose,output_path): star2 = SingleStar(**{'mass':37.917852, 'state': 'H-rich_Core_H_burning', 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) - + binary = BinaryStar(star1, star2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':113.352736, 'eccentricity': 0.0}, properties = sim_prop) - evolve_binary(binary, h5file, binary_id) + evolve_binary(binary, h5file, binary_id) binary_id+=1 ######################################## # Redirect to step_CO_HeMS (H-rich non-burning?) @@ -375,7 +375,7 @@ def evolve_binaries(verbose,output_path): binary = BinaryStar(star_1, star_2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period': 66.870417, 'eccentricity': 0.0}, properties = sim_prop) - evolve_binary(binary, h5file, binary_id) + evolve_binary(binary, h5file, binary_id) binary_id+=1 ######################################## # FIXED oRLO2 looping @@ -387,7 +387,7 @@ def evolve_binaries(verbose,output_path): binary = BinaryStar(star_1, star_2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period': 37.958768, 'eccentricity': 0.0}, properties = sim_prop) - evolve_binary(binary, h5file, binary_id) + evolve_binary(binary, h5file, binary_id) binary_id+=1 ######################################## # FIXED? step_detached failure @@ -399,7 +399,7 @@ def evolve_binaries(verbose,output_path): binary = BinaryStar(star1, star2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':3007.865561, 'eccentricity': 0.0}, properties = sim_prop) - evolve_binary(binary, h5file, binary_id) + evolve_binary(binary, h5file, binary_id) binary_id+=1 ######################################## # Disrupted binary @@ -408,11 +408,11 @@ def evolve_binaries(verbose,output_path): 'natal_kick_array': [268.837139, 5.773527, 2.568105, 2.519068]}) star_2 = SingleStar(**{'mass' : 16.286318, 'state' : 'H-rich_Core_H_burning', 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - + binary = BinaryStar(star_1, star_2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':3007.865561, 'eccentricity': 0.0}, properties = sim_prop) - evolve_binary(binary, h5file, binary_id) + evolve_binary(binary, h5file, binary_id) binary_id+=1 ######################################## # FIXED Detached binary failure (low mass) @@ -423,11 +423,11 @@ def evolve_binaries(verbose,output_path): star2 = SingleStar(**{'mass':0.8, 'state': 'H-rich_Core_H_burning', 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - + binary = BinaryStar(star1, star2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':4513.150157, 'eccentricity': 0.0}, properties = sim_prop) - evolve_binary(binary, h5file, binary_id) + evolve_binary(binary, h5file, binary_id) binary_id+=1 ######################################## # FIXED SN_TYPE = None crash @@ -438,11 +438,11 @@ def evolve_binaries(verbose,output_path): star2 = SingleStar(**{'mass':3.273864, 'state': 'H-rich_Core_H_burning', 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - + binary = BinaryStar(star1, star2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':4513.150157, 'eccentricity': 0.0}, properties = sim_prop) - evolve_binary(binary, h5file, binary_id) + evolve_binary(binary, h5file, binary_id) binary_id+=1 ######################################## # FIXED SN_TYPE errors @@ -453,11 +453,11 @@ def evolve_binaries(verbose,output_path): star2 = SingleStar(**{'mass':3.273864, 'state': 'H-rich_Core_H_burning', 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - + binary = BinaryStar(star1, star2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':4513.150157, 'eccentricity': 0.0}, properties = sim_prop) - evolve_binary(binary, h5file, binary_id) + evolve_binary(binary, h5file, binary_id) binary_id+=1 ######################################## # FIXED SN_TYPE errors @@ -468,11 +468,11 @@ def evolve_binaries(verbose,output_path): star2 = SingleStar(**{'mass':37.917852, 'state': 'H-rich_Core_H_burning', 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - + binary = BinaryStar(star1, star2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':2113.352736, 'eccentricity': 0.0}, properties = sim_prop) - evolve_binary(binary, h5file, binary_id) + evolve_binary(binary, h5file, binary_id) binary_id+=1 ######################################## # FIXED ECSN errors? @@ -483,12 +483,12 @@ def evolve_binaries(verbose,output_path): star2 = SingleStar(**{'mass': 9.711216, 'state': 'H-rich_Core_H_burning', 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - - + + binary = BinaryStar(star1, star2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':79.83702, 'eccentricity': 0.0}, properties = sim_prop) - evolve_binary(binary, h5file, binary_id) + evolve_binary(binary, h5file, binary_id) binary_id+=1 ######################################## # Interpolator masses?? @@ -499,11 +499,11 @@ def evolve_binaries(verbose,output_path): star2 = SingleStar(**{'mass':5.038679 , 'state': 'H-rich_Core_H_burning', 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - + binary = BinaryStar(star1, star2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':5.537807, 'eccentricity': 0.0}, properties = sim_prop) - evolve_binary(binary, h5file, binary_id) + evolve_binary(binary, h5file, binary_id) binary_id+=1 ######################################## # Interpolator masses? @@ -514,11 +514,11 @@ def evolve_binaries(verbose,output_path): star_2 = SingleStar(**{'mass': 27.776178, 'state': 'H-rich_Core_H_burning',\ 'natal_kick_array': [282.712103, 0.296252, 1.628433, 5.623812]}) - + binary = BinaryStar(star_1, star_2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period': 93.387072, 'eccentricity': 0.0}, properties = sim_prop) - evolve_binary(binary, h5file, binary_id) + evolve_binary(binary, h5file, binary_id) binary_id+=1 ######################################## # FIXED NaN spin @@ -536,7 +536,7 @@ def evolve_binaries(verbose,output_path): 'separation': orbital_separation_from_period(5.931492e+03, star1.mass, star2.mass), 'eccentricity': 0.0}, properties = sim_prop) - evolve_binary(binary, h5file, binary_id) + evolve_binary(binary, h5file, binary_id) binary_id+=1 ######################################## # FIXED NaN spin @@ -547,13 +547,13 @@ def evolve_binaries(verbose,output_path): star2 = SingleStar(**{'mass': 6.874867, 'state': 'H-rich_Core_H_burning', 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - + binary = BinaryStar(star1, star2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':35.609894, 'separation': orbital_separation_from_period(35.609894, star1.mass, star2.mass), 'eccentricity': 0.0}, properties = sim_prop) - evolve_binary(binary, h5file, binary_id) + evolve_binary(binary, h5file, binary_id) binary_id+=1 ######################################## # oRLO2 issue @@ -564,11 +564,11 @@ def evolve_binaries(verbose,output_path): star2 = SingleStar(**{'mass': 28.814626, 'state': 'H-rich_Core_H_burning', 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - + binary = BinaryStar(star1, star2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':40.437993, 'eccentricity': 0.0}, properties = sim_prop) - evolve_binary(binary, h5file, binary_id) + evolve_binary(binary, h5file, binary_id) binary_id+=1 ######################################## # oRLO2 issue @@ -579,11 +579,11 @@ def evolve_binaries(verbose,output_path): star2 = SingleStar(**{'mass': 19.622908, 'state': 'H-rich_Core_H_burning', 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - + binary = BinaryStar(star1, star2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':1484.768582, 'eccentricity': 0.0}, properties = sim_prop) - evolve_binary(binary, h5file, binary_id) + evolve_binary(binary, h5file, binary_id) binary_id+=1 ######################################## # oRLO2 issue @@ -594,11 +594,11 @@ def evolve_binaries(verbose,output_path): star2 = SingleStar(**{'mass': 56.660506, 'state': 'H-rich_Core_H_burning', 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - + binary = BinaryStar(star1, star2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':2011.300659, 'eccentricity': 0.0}, properties = sim_prop) - evolve_binary(binary, h5file, binary_id) + evolve_binary(binary, h5file, binary_id) binary_id+=1 ######################################## # oRLO2 issue @@ -609,11 +609,11 @@ def evolve_binaries(verbose,output_path): star2 = SingleStar(**{'mass': 37.917852, 'state': 'H-rich_Core_H_burning', 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - + binary = BinaryStar(star1, star2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':113.352736, 'eccentricity': 0.0}, properties = sim_prop) - evolve_binary(binary, h5file, binary_id) + evolve_binary(binary, h5file, binary_id) binary_id+=1 ######################################## # oRLO2 issue @@ -624,11 +624,11 @@ def evolve_binaries(verbose,output_path): star2 = SingleStar(**{'mass': 84.344530, 'state': 'H-rich_Core_H_burning', 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - + binary = BinaryStar(star1, star2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':5.651896, 'eccentricity': 0.0}, properties = sim_prop) - evolve_binary(binary, h5file, binary_id) + evolve_binary(binary, h5file, binary_id) binary_id+=1 ######################################## # redirect @@ -639,11 +639,11 @@ def evolve_binaries(verbose,output_path): star2 = SingleStar(**{'mass':0.490231, 'state': 'H-rich_Core_H_burning', 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - + binary = BinaryStar(star1, star2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':14513.150157, 'eccentricity': 0.0}, properties = sim_prop) - evolve_binary(binary, h5file, binary_id) + evolve_binary(binary, h5file, binary_id) binary_id+=1 ######################################## # redirect @@ -654,11 +654,11 @@ def evolve_binaries(verbose,output_path): star2 = SingleStar(**{'mass':0.8, 'state': 'H-rich_Core_H_burning', 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - + binary = BinaryStar(star1, star2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':4513.150157, 'eccentricity': 0.0}, properties = sim_prop) - evolve_binary(binary, h5file, binary_id) + evolve_binary(binary, h5file, binary_id) binary_id+=1 ######################################## # Max time @@ -671,7 +671,7 @@ def evolve_binaries(verbose,output_path): 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) binary = BinaryStar(star_1, star_2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period': 1449.1101985875678,'eccentricity': 0.0}, properties = sim_prop) - evolve_binary(binary, h5file, binary_id) + evolve_binary(binary, h5file, binary_id) binary_id+=1 ######################################## # Max time @@ -684,7 +684,7 @@ def evolve_binaries(verbose,output_path): 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) binary = BinaryStar(star_1, star_2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period': 20.82030114750744,'eccentricity': 0.0}, properties = sim_prop) - evolve_binary(binary, h5file, binary_id) + evolve_binary(binary, h5file, binary_id) binary_id+=1 ######################################## # PR421 @@ -695,11 +695,11 @@ def evolve_binaries(verbose,output_path): star2 = SingleStar(**{'mass': 23.187355, 'state': 'H-rich_Core_H_burning', 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - + binary = BinaryStar(star1, star2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':18.865029, 'eccentricity': 0.0}, properties = sim_prop) - evolve_binary(binary, h5file, binary_id) + evolve_binary(binary, h5file, binary_id) binary_id+=1 ######################################## # CE class @@ -710,11 +710,11 @@ def evolve_binaries(verbose,output_path): star2 = SingleStar(**{'mass': 28.98149, 'state': 'H-rich_Core_H_burning', 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - + binary = BinaryStar(star1, star2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':82.370989, 'eccentricity': 0.0}, properties = sim_prop) - evolve_binary(binary, h5file, binary_id) + evolve_binary(binary, h5file, binary_id) binary_id+=1 ######################################## # PR574 - stepCE fix @@ -725,11 +725,11 @@ def evolve_binaries(verbose,output_path): star2 = SingleStar(**{'mass': 28.814626*0.4, 'state': 'H-rich_Core_H_burning', 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - + binary = BinaryStar(star1, star2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':300.437993, 'eccentricity': 0.0}, properties = sim_prop) - evolve_binary(binary, h5file, binary_id) + evolve_binary(binary, h5file, binary_id) binary_id+=1 ######################################## # e_ZAMS error @@ -740,11 +740,11 @@ def evolve_binaries(verbose,output_path): star2 = SingleStar(**{'mass': 3.5907829421526154, 'state': 'H-rich_Core_H_burning', 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) - + binary = BinaryStar(star1, star2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period': 36.873457164644144, 'eccentricity': 0.0}, properties = sim_prop) - evolve_binary(binary, h5file, binary_id) + evolve_binary(binary, h5file, binary_id) binary_id+=1 ######################################## # e_ZAMS error @@ -756,11 +756,11 @@ def evolve_binaries(verbose,output_path): star2 = SingleStar(**{'mass': 30.000450298072902, 'state': 'H-rich_Core_H_burning', 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) - + binary = BinaryStar(star1, star2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period': 24060.02101364665, 'eccentricity': 0.8085077857996965}, properties = sim_prop) - evolve_binary(binary, h5file, binary_id) + evolve_binary(binary, h5file, binary_id) binary_id+=1 ######################################## # e_ZAMS error @@ -771,11 +771,11 @@ def evolve_binaries(verbose,output_path): star2 = SingleStar(**{'mass': 1.4739109294156703, 'state': 'H-rich_Core_H_burning', 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) - + binary = BinaryStar(star1, star2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period': 4111.083887312003, 'eccentricity':0.0}, properties = sim_prop) - evolve_binary(binary, h5file, binary_id) + evolve_binary(binary, h5file, binary_id) binary_id+=1 ######################################## # e_ZAMS error @@ -786,11 +786,11 @@ def evolve_binaries(verbose,output_path): star2 = SingleStar(**{'mass': 0.7061748406821822, 'state': 'H-rich_Core_H_burning', 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) - + binary = BinaryStar(star1, star2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period': 2521.1927287891444, 'eccentricity':0.0}, properties = sim_prop) - evolve_binary(binary, h5file, binary_id) + evolve_binary(binary, h5file, binary_id) binary_id+=1 ######################################## # e_ZAMS error @@ -801,11 +801,11 @@ def evolve_binaries(verbose,output_path): star2 = SingleStar(**{'mass': 4.466151109802313 , #481560266, 'state': 'H-rich_Core_H_burning', 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) - + binary = BinaryStar(star1, star2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':3110.1346707516914, 'eccentricity':0.0}, properties = sim_prop) - evolve_binary(binary, h5file, binary_id) + evolve_binary(binary, h5file, binary_id) binary_id+=1 if __name__ == "__main__": From 1a0121391f3533f79fc09ce1bf3d5fddad9a2a90 Mon Sep 17 00:00:00 2001 From: Elizabeth Teng <41969755+elizabethteng@users.noreply.github.com> Date: Thu, 18 Dec 2025 09:19:47 -0600 Subject: [PATCH 12/91] Update authors --- dev-tools/script_data/1Zsun_binaries_suite.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev-tools/script_data/1Zsun_binaries_suite.py b/dev-tools/script_data/1Zsun_binaries_suite.py index 9fbd21dbaf..03a896a0fc 100644 --- a/dev-tools/script_data/1Zsun_binaries_suite.py +++ b/dev-tools/script_data/1Zsun_binaries_suite.py @@ -3,7 +3,7 @@ Script to evolve a few binaries. Used for validation of the branch. -Author: Max Briel +Authors: Max Briel, Elizabeth Teng """ import argparse From e967e01a26114849142e973c2e54283b895ae734 Mon Sep 17 00:00:00 2001 From: Elizabeth Teng <41969755+elizabethteng@users.noreply.github.com> Date: Thu, 18 Dec 2025 09:22:08 -0600 Subject: [PATCH 13/91] remove alarm calls that were never set Removed signal alarm handling in exception block. --- dev-tools/script_data/1Zsun_binaries_suite.py | 5 ----- 1 file changed, 5 deletions(-) diff --git a/dev-tools/script_data/1Zsun_binaries_suite.py b/dev-tools/script_data/1Zsun_binaries_suite.py index 03a896a0fc..56a055144c 100644 --- a/dev-tools/script_data/1Zsun_binaries_suite.py +++ b/dev-tools/script_data/1Zsun_binaries_suite.py @@ -153,9 +153,6 @@ def warning_handler(message, category, filename, lineno, file=None, line=None): grp.create_dataset(col, data=df[col].values) except Exception as e: - # turn off binary alarm in case of exception - signal.alarm(0) - print_failed_binary(binary, e) err_grp = h5file.require_group(f"binary_{binary_id}/errors") @@ -163,8 +160,6 @@ def warning_handler(message, category, filename, lineno, file=None, line=None): err_grp.attrs['exception_message'] = str(e) finally: - # Always turn off binary alarm and restore warning handler - signal.alarm(0) warnings.showwarning = old_showwarning # ensure binary group exists From e5c07ce5c117c0b2728982563acde4b7899b11bb Mon Sep 17 00:00:00 2001 From: Elizabeth Teng <41969755+elizabethteng@users.noreply.github.com> Date: Thu, 18 Dec 2025 09:30:54 -0600 Subject: [PATCH 14/91] Enhance evolve_binaries.sh for better logging and error handling Updated the script to log output and check for errors. --- dev-tools/evolve_binaries.sh | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/dev-tools/evolve_binaries.sh b/dev-tools/evolve_binaries.sh index 051dafcd13..ee5dec4306 100755 --- a/dev-tools/evolve_binaries.sh +++ b/dev-tools/evolve_binaries.sh @@ -88,11 +88,16 @@ pip install -e "$CLONE_DIR" -q 2>&1 | sed 's/^/ /' echo "šŸš€ Running evolve_binaries.py" # # Run the Python script and capture output (stdout and stderr) -python script_data/1Zsun_binaries_suite.py --output "$OUTPUT_FILE" > "$LOG_FILE" 2>&1 +python script_data/1Zsun_binaries_suite.py --output "$OUTPUT_FILE" 2>&1 | tee "$LOG_FILE" if [ ! -f "$OUTPUT_FILE" ]; then echo "ERROR: Results file was not created: $OUTPUT_FILE" exit 2 fi +if [ $? -ne 0 ]; then + echo "ERROR: Python script exited with an error. Check $LOG_FILE for details." + exit 3 +fi + echo -e "āœ… Script completed. Output saved to \n$OUTPUT_FILE" From 1a82ac889fd463469509817f85c039b4d8dbf317 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Thu, 18 Dec 2025 15:31:21 +0000 Subject: [PATCH 15/91] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- dev-tools/evolve_binaries.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev-tools/evolve_binaries.sh b/dev-tools/evolve_binaries.sh index ee5dec4306..5e8e60183f 100755 --- a/dev-tools/evolve_binaries.sh +++ b/dev-tools/evolve_binaries.sh @@ -88,7 +88,7 @@ pip install -e "$CLONE_DIR" -q 2>&1 | sed 's/^/ /' echo "šŸš€ Running evolve_binaries.py" # # Run the Python script and capture output (stdout and stderr) -python script_data/1Zsun_binaries_suite.py --output "$OUTPUT_FILE" 2>&1 | tee "$LOG_FILE" +python script_data/1Zsun_binaries_suite.py --output "$OUTPUT_FILE" 2>&1 | tee "$LOG_FILE" if [ ! -f "$OUTPUT_FILE" ]; then echo "ERROR: Results file was not created: $OUTPUT_FILE" From 5525ea86146c2411d49431bf53d7a7d6d4bfc44c Mon Sep 17 00:00:00 2001 From: Elizabeth Teng <41969755+elizabethteng@users.noreply.github.com> Date: Thu, 18 Dec 2025 09:34:36 -0600 Subject: [PATCH 16/91] Fix argument passing for evolve_binaries function --- dev-tools/script_data/1Zsun_binaries_suite.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev-tools/script_data/1Zsun_binaries_suite.py b/dev-tools/script_data/1Zsun_binaries_suite.py index 56a055144c..f56cbe8823 100644 --- a/dev-tools/script_data/1Zsun_binaries_suite.py +++ b/dev-tools/script_data/1Zsun_binaries_suite.py @@ -811,4 +811,4 @@ def evolve_binaries(verbose,output_path): help="Path to save HDF5 output") args = parser.parse_args() - evolve_binaries(verbose=args.verbose, args.output) + evolve_binaries(verbose=args.verbose, output_path=args.output) From 138d804da8bd5e0a3fd170210e6128f25bb36b04 Mon Sep 17 00:00:00 2001 From: Elizabeth Teng <41969755+elizabethteng@users.noreply.github.com> Date: Thu, 18 Dec 2025 09:46:05 -0600 Subject: [PATCH 17/91] fill in all code for validate_binaries.sh Updated script to accept branch and suffix as arguments, streamlined output file naming. --- dev-tools/validate_binaries.sh | 35 ++++++++++++++++------------------ 1 file changed, 16 insertions(+), 19 deletions(-) diff --git a/dev-tools/validate_binaries.sh b/dev-tools/validate_binaries.sh index 31b7c6d72a..04a041af06 100644 --- a/dev-tools/validate_binaries.sh +++ b/dev-tools/validate_binaries.sh @@ -3,27 +3,24 @@ # A script for validating the outputs of 100 binaries, # which can be compared to a baseline to monitor changes to the code. -# script usage: ./validate_binaries.sh --branch candidate-branch - -# run candidate binaries and save to file -# ./evolve_binaries.sh -# save to file - -# evaluate tolerance for quantitative values - -# evaluate qualitative differences - -# warnings and error tracking - -# structured output - -# compare -# python compare_runs.py baseline.json candidate.json +# script usage: ./validate_binaries.sh --branch candidate_branch +BRANCH=$1 +SUFFIX=$2 +# run candidate binaries and save to file +./evolve_binaries.sh "$BRANCH" +# compare quantitative, qualitative, warnings/errors, structured output +# create outputs/comparison_branchname.txt +SAFE_BRANCH="${BRANCH//\//_}" +CANDIDATE_FILE="outputs/candidate_${SAFE_BRANCH}.h5" +COMPARISON_FILE="outputs/comparison_${SAFE_BRANCH}${SUFFIX:+_$SUFFIX}.txt" +python compare_runs.py baseline.h5 "$CANDIDATE_FILE" > "$COMPARISON_FILE" +if [ $? -ne 0 ]; then + echo "Error: compare_runs.py failed. Check $COMPARISON_FILE" + exit 1 +fi -# outputs/baseline.h5 -# outputs/candidate_branchname.h5 -# outputs/comparison_branchname.txt +echo "Binary evolution comparison saved to $COMPARISON_FILE" From 12a528e85931d7769c5c88ec27874334c56b78cc Mon Sep 17 00:00:00 2001 From: Elizabeth Teng <41969755+elizabethteng@users.noreply.github.com> Date: Thu, 18 Dec 2025 09:52:48 -0600 Subject: [PATCH 18/91] starting point of compare_runs.py for comparing two h5 files --- dev-tools/compare_runs.py | 73 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) create mode 100644 dev-tools/compare_runs.py diff --git a/dev-tools/compare_runs.py b/dev-tools/compare_runs.py new file mode 100644 index 0000000000..8444d08a88 --- /dev/null +++ b/dev-tools/compare_runs.py @@ -0,0 +1,73 @@ +#!/usr/bin/env python3 + +""" +Compare evolution outcomes of set of binaries saved to file with script_data/1Zsun_binaries_suite.py +Used for validation of the branch. + +Author: Elizabeth Teng +""" + + +import sys +import h5py +import numpy as np + +def compare_datasets(base, cand, path="/"): + """ + Recursively compare HDF5 datasets. + Returns a list of strings with differences. + """ + differences = [] + + for key in base.keys(): + base_item = base[key] + if key not in cand: + differences.append(f"{path}{key} missing in candidate") + continue + + cand_item = cand[key] + + if isinstance(base_item, h5py.Dataset): + base_data = base_item[()] + cand_data = cand_item[()] + + if np.issubdtype(base_data.dtype, np.number): + if not np.allclose(base_data, cand_data, rtol=1e-5, atol=1e-8): + differences.append(f"{path}{key} numeric mismatch") + else: + if not np.array_equal(base_data, cand_data): + differences.append(f"{path}{key} non-numeric mismatch") + + elif isinstance(base_item, h5py.Group): + differences.extend(compare_datasets(base_item, cand_item, path=f"{path}{key}/")) + + # Check for extra keys in candidate + for key in cand.keys(): + if key not in base: + differences.append(f"{path}{key} extra in candidate") + + return differences + + +def main(): + if len(sys.argv) != 3: + print("Usage: compare_runs.py baseline.h5 candidate.h5") + sys.exit(1) + + baseline_file = sys.argv[1] + candidate_file = sys.argv[2] + + with h5py.File(baseline_file, 'r') as base, h5py.File(candidate_file, 'r') as cand: + diffs = compare_datasets(base, cand) + + if diffs: + print("Differences found:") + for diff in diffs: + print(" -", diff) + sys.exit(1) + else: + print("No differences detected between baseline and candidate.") + + +if __name__ == "__main__": + main() From 9140a20923de22ac125df5447448b1a8539be8fa Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Thu, 18 Dec 2025 15:52:57 +0000 Subject: [PATCH 19/91] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- dev-tools/compare_runs.py | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/dev-tools/compare_runs.py b/dev-tools/compare_runs.py index 8444d08a88..6ff28d81e2 100644 --- a/dev-tools/compare_runs.py +++ b/dev-tools/compare_runs.py @@ -9,43 +9,45 @@ import sys + import h5py import numpy as np + def compare_datasets(base, cand, path="/"): """ Recursively compare HDF5 datasets. Returns a list of strings with differences. """ differences = [] - + for key in base.keys(): base_item = base[key] if key not in cand: differences.append(f"{path}{key} missing in candidate") continue - + cand_item = cand[key] if isinstance(base_item, h5py.Dataset): base_data = base_item[()] cand_data = cand_item[()] - + if np.issubdtype(base_data.dtype, np.number): if not np.allclose(base_data, cand_data, rtol=1e-5, atol=1e-8): differences.append(f"{path}{key} numeric mismatch") else: if not np.array_equal(base_data, cand_data): differences.append(f"{path}{key} non-numeric mismatch") - + elif isinstance(base_item, h5py.Group): differences.extend(compare_datasets(base_item, cand_item, path=f"{path}{key}/")) - + # Check for extra keys in candidate for key in cand.keys(): if key not in base: differences.append(f"{path}{key} extra in candidate") - + return differences @@ -53,7 +55,7 @@ def main(): if len(sys.argv) != 3: print("Usage: compare_runs.py baseline.h5 candidate.h5") sys.exit(1) - + baseline_file = sys.argv[1] candidate_file = sys.argv[2] From b7f6f028469a21be1a4f0362e7ebeb2e7098e39d Mon Sep 17 00:00:00 2001 From: Elizabeth Teng <41969755+elizabethteng@users.noreply.github.com> Date: Fri, 9 Jan 2026 15:07:18 -0600 Subject: [PATCH 20/91] Add conda source detection in evolve_binaries.sh --- dev-tools/evolve_binaries.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/dev-tools/evolve_binaries.sh b/dev-tools/evolve_binaries.sh index 5e8e60183f..2021995bff 100755 --- a/dev-tools/evolve_binaries.sh +++ b/dev-tools/evolve_binaries.sh @@ -52,6 +52,9 @@ elif [ -f "$HOME/anaconda3/etc/profile.d/conda.sh" ]; then source "$HOME/anaconda3/etc/profile.d/conda.sh" elif [ -f "/opt/homebrew/Caskroom/miniconda/base/etc/profile.d/conda.sh" ]; then source "/opt/homebrew/Caskroom/miniconda/base/etc/profile.d/conda.sh" +elif command -v conda >/dev/null 2>&1; then + CONDA_BASE=$(conda info --base) + source "${CONDA_BASE}/etc/profile.d/conda.sh" else echo -e "\033[31mError: Could not find conda installation. Please check your conda setup.\033[0m" exit 1 From cd618fd404b3fb27c210f144413d4b95a217b003 Mon Sep 17 00:00:00 2001 From: Elizabeth Teng <41969755+elizabethteng@users.noreply.github.com> Date: Fri, 9 Jan 2026 15:19:30 -0600 Subject: [PATCH 21/91] Add h5py import to 1Zsun_binaries_suite.py --- dev-tools/script_data/1Zsun_binaries_suite.py | 1 + 1 file changed, 1 insertion(+) diff --git a/dev-tools/script_data/1Zsun_binaries_suite.py b/dev-tools/script_data/1Zsun_binaries_suite.py index f56cbe8823..b994e0b475 100644 --- a/dev-tools/script_data/1Zsun_binaries_suite.py +++ b/dev-tools/script_data/1Zsun_binaries_suite.py @@ -11,6 +11,7 @@ import signal import sys import warnings +import h5py from posydon.binary_evol.binarystar import BinaryStar, SingleStar from posydon.binary_evol.simulationproperties import SimulationProperties From 17b7013c64ff816f78db01cc29ceaf8831a6d6be Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 9 Jan 2026 21:19:39 +0000 Subject: [PATCH 22/91] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- dev-tools/script_data/1Zsun_binaries_suite.py | 1 + 1 file changed, 1 insertion(+) diff --git a/dev-tools/script_data/1Zsun_binaries_suite.py b/dev-tools/script_data/1Zsun_binaries_suite.py index b994e0b475..ee1b0386ee 100644 --- a/dev-tools/script_data/1Zsun_binaries_suite.py +++ b/dev-tools/script_data/1Zsun_binaries_suite.py @@ -11,6 +11,7 @@ import signal import sys import warnings + import h5py from posydon.binary_evol.binarystar import BinaryStar, SingleStar From 8cd3f6d802c4a28c2fe0dbfbceacaf9171d8dac5 Mon Sep 17 00:00:00 2001 From: Elizabeth Teng <41969755+elizabethteng@users.noreply.github.com> Date: Fri, 9 Jan 2026 15:22:59 -0600 Subject: [PATCH 23/91] Modify usage comment in evolve_binaries.sh Updated script usage instructions to include PATH_TO_POSYODN_DATA. --- dev-tools/evolve_binaries.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev-tools/evolve_binaries.sh b/dev-tools/evolve_binaries.sh index 2021995bff..e6a98bbf76 100755 --- a/dev-tools/evolve_binaries.sh +++ b/dev-tools/evolve_binaries.sh @@ -1,6 +1,6 @@ #!/bin/bash -# Script usage: ./evolve_binaries.sh +# Script usage: export PATH_TO_POSYODN_DATA, then run ./evolve_binaries.sh # This script clones the POSYDON repo to the specified branch (defaults to 'main'), # copies evolve_binaries.py, runs it, and saves output to evolve_binaries.out From cd19659788c85134d6751797b91fab69b4270276 Mon Sep 17 00:00:00 2001 From: Elizabeth Teng Date: Thu, 26 Feb 2026 04:09:34 -0600 Subject: [PATCH 24/91] refactor binary validation suite: multi metallicity support, bug fixes, generate baseline, add more specificity to compare_runs --- dev-tools/.gitignore | 14 + dev-tools/check_outputs.ipynb | 512 +++++++++++ dev-tools/compare_runs.py | 429 ++++++++- dev-tools/evolve_binaries.sh | 185 ++-- dev-tools/generate_baseline.sh | 96 +++ dev-tools/script_data/1Zsun_binaries_suite.py | 815 ------------------ ...inaries_params.ini => binaries_params.ini} | 2 + dev-tools/script_data/binaries_suite.py | 694 +++++++++++++++ dev-tools/validate_binaries.sh | 170 +++- 9 files changed, 1961 insertions(+), 956 deletions(-) create mode 100644 dev-tools/.gitignore create mode 100644 dev-tools/check_outputs.ipynb create mode 100644 dev-tools/generate_baseline.sh delete mode 100644 dev-tools/script_data/1Zsun_binaries_suite.py rename dev-tools/script_data/{1Zsun_binaries_params.ini => binaries_params.ini} (99%) create mode 100644 dev-tools/script_data/binaries_suite.py diff --git a/dev-tools/.gitignore b/dev-tools/.gitignore new file mode 100644 index 0000000000..1cea72efc6 --- /dev/null +++ b/dev-tools/.gitignore @@ -0,0 +1,14 @@ +# Remove the accidentally staged clone +git rm --cached -r workdirs/ + +# Create .gitignore +cat > .gitignore << 'EOF' +workdirs/ +outputs/ +logs/ +baselines/ +test_*.h5 +EOF + +git add .gitignore + diff --git a/dev-tools/check_outputs.ipynb b/dev-tools/check_outputs.ipynb new file mode 100644 index 0000000000..c0073df835 --- /dev/null +++ b/dev-tools/check_outputs.ipynb @@ -0,0 +1,512 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "id": "7e9791d3", + "metadata": {}, + "outputs": [], + "source": [ + "import argparse\n", + "import os\n", + "import signal\n", + "import sys\n", + "import warnings\n", + "import h5py\n", + "import pandas as pd\n", + "\n", + "from posydon.binary_evol.binarystar import BinaryStar, SingleStar\n", + "from posydon.binary_evol.simulationproperties import SimulationProperties\n", + "from posydon.popsyn.io import simprop_kwargs_from_ini\n", + "from posydon.utils.common_functions import orbital_separation_from_period" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "327be9fe", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "env: PATH_TO_POSYDON=/projects/b1119/eteng/software/valid/POSYDON/\n", + "env: PATH_TO_POSYDON_DATA=/projects/b1119/POSYDON_popsynth_data/v2/250520_newSNe/\n" + ] + } + ], + "source": [ + "%env PATH_TO_POSYDON=/projects/b1119/eteng/software/valid/POSYDON/\n", + "%env PATH_TO_POSYDON_DATA=/projects/b1119/POSYDON_popsynth_data/v2/250520_newSNe/" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "994f6ebf", + "metadata": {}, + "outputs": [ + { + "ename": "HDF5ExtError", + "evalue": "HDF5 error back trace\n\n File \"H5F.c\", line 836, in H5Fopen\n unable to synchronously open file\n File \"H5F.c\", line 796, in H5F__open_api_common\n unable to open file\n File \"H5VLcallback.c\", line 3863, in H5VL_file_open\n open failed\n File \"H5VLcallback.c\", line 3675, in H5VL__file_open\n open failed\n File \"H5VLnative_file.c\", line 128, in H5VL__native_file_open\n unable to open file\n File \"H5Fint.c\", line 2018, in H5F_open\n unable to read superblock\n File \"H5Fsuper.c\", line 600, in H5F__super_read\n truncated file: eof = 96, sblock->base_addr = 0, stored_eof = 2048\n\nEnd of HDF5 error back trace\n\nUnable to open/create file './POSYDON_main/outputs/candidate_main.h5'", + "output_type": "error", + "traceback": [ + "\u001b[31m---------------------------------------------------------------------------\u001b[39m", + "\u001b[31mHDF5ExtError\u001b[39m Traceback (most recent call last)", + "\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[4]\u001b[39m\u001b[32m, line 1\u001b[39m\n\u001b[32m----> \u001b[39m\u001b[32m1\u001b[39m df = \u001b[43mpd\u001b[49m\u001b[43m.\u001b[49m\u001b[43mread_hdf\u001b[49m\u001b[43m(\u001b[49m\u001b[33;43m'\u001b[39;49m\u001b[33;43m./POSYDON_main/outputs/candidate_main.h5\u001b[39;49m\u001b[33;43m'\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[33;43m\"\u001b[39;49m\u001b[33;43mevolution\u001b[39;49m\u001b[33;43m\"\u001b[39;49m\u001b[43m)\u001b[49m\n\u001b[32m 2\u001b[39m warnings = pd.read_hdf(\u001b[33m'\u001b[39m\u001b[33m./POSYDON_main/outputs/candidate_main.h5\u001b[39m\u001b[33m'\u001b[39m, \u001b[33m\"\u001b[39m\u001b[33mwarnings\u001b[39m\u001b[33m\"\u001b[39m)\n", + "\u001b[36mFile \u001b[39m\u001b[32m~/.conda/envs/valid/lib/python3.11/site-packages/pandas/io/pytables.py:426\u001b[39m, in \u001b[36mread_hdf\u001b[39m\u001b[34m(path_or_buf, key, mode, errors, where, start, stop, columns, iterator, chunksize, **kwargs)\u001b[39m\n\u001b[32m 423\u001b[39m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m exists:\n\u001b[32m 424\u001b[39m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mFileNotFoundError\u001b[39;00m(\u001b[33mf\u001b[39m\u001b[33m\"\u001b[39m\u001b[33mFile \u001b[39m\u001b[38;5;132;01m{\u001b[39;00mpath_or_buf\u001b[38;5;132;01m}\u001b[39;00m\u001b[33m does not exist\u001b[39m\u001b[33m\"\u001b[39m)\n\u001b[32m--> \u001b[39m\u001b[32m426\u001b[39m store = \u001b[43mHDFStore\u001b[49m\u001b[43m(\u001b[49m\u001b[43mpath_or_buf\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mmode\u001b[49m\u001b[43m=\u001b[49m\u001b[43mmode\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43merrors\u001b[49m\u001b[43m=\u001b[49m\u001b[43merrors\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43m*\u001b[49m\u001b[43m*\u001b[49m\u001b[43mkwargs\u001b[49m\u001b[43m)\u001b[49m\n\u001b[32m 427\u001b[39m \u001b[38;5;66;03m# can't auto open/close if we are using an iterator\u001b[39;00m\n\u001b[32m 428\u001b[39m \u001b[38;5;66;03m# so delegate to the iterator\u001b[39;00m\n\u001b[32m 429\u001b[39m auto_close = \u001b[38;5;28;01mTrue\u001b[39;00m\n", + "\u001b[36mFile \u001b[39m\u001b[32m~/.conda/envs/valid/lib/python3.11/site-packages/pandas/io/pytables.py:585\u001b[39m, in \u001b[36mHDFStore.__init__\u001b[39m\u001b[34m(self, path, mode, complevel, complib, fletcher32, **kwargs)\u001b[39m\n\u001b[32m 583\u001b[39m \u001b[38;5;28mself\u001b[39m._fletcher32 = fletcher32\n\u001b[32m 584\u001b[39m \u001b[38;5;28mself\u001b[39m._filters = \u001b[38;5;28;01mNone\u001b[39;00m\n\u001b[32m--> \u001b[39m\u001b[32m585\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[43m.\u001b[49m\u001b[43mopen\u001b[49m\u001b[43m(\u001b[49m\u001b[43mmode\u001b[49m\u001b[43m=\u001b[49m\u001b[43mmode\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43m*\u001b[49m\u001b[43m*\u001b[49m\u001b[43mkwargs\u001b[49m\u001b[43m)\u001b[49m\n", + "\u001b[36mFile \u001b[39m\u001b[32m~/.conda/envs/valid/lib/python3.11/site-packages/pandas/io/pytables.py:745\u001b[39m, in \u001b[36mHDFStore.open\u001b[39m\u001b[34m(self, mode, **kwargs)\u001b[39m\n\u001b[32m 739\u001b[39m msg = (\n\u001b[32m 740\u001b[39m \u001b[33m\"\u001b[39m\u001b[33mCannot open HDF5 file, which is already opened, \u001b[39m\u001b[33m\"\u001b[39m\n\u001b[32m 741\u001b[39m \u001b[33m\"\u001b[39m\u001b[33meven in read-only mode.\u001b[39m\u001b[33m\"\u001b[39m\n\u001b[32m 742\u001b[39m )\n\u001b[32m 743\u001b[39m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mValueError\u001b[39;00m(msg)\n\u001b[32m--> \u001b[39m\u001b[32m745\u001b[39m \u001b[38;5;28mself\u001b[39m._handle = \u001b[43mtables\u001b[49m\u001b[43m.\u001b[49m\u001b[43mopen_file\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[43m.\u001b[49m\u001b[43m_path\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[43m.\u001b[49m\u001b[43m_mode\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43m*\u001b[49m\u001b[43m*\u001b[49m\u001b[43mkwargs\u001b[49m\u001b[43m)\u001b[49m\n", + "\u001b[36mFile \u001b[39m\u001b[32m~/.conda/envs/valid/lib/python3.11/site-packages/tables/file.py:296\u001b[39m, in \u001b[36mopen_file\u001b[39m\u001b[34m(filename, mode, title, root_uep, filters, **kwargs)\u001b[39m\n\u001b[32m 291\u001b[39m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mValueError\u001b[39;00m(\n\u001b[32m 292\u001b[39m \u001b[33m\"\u001b[39m\u001b[33mThe file \u001b[39m\u001b[33m'\u001b[39m\u001b[38;5;132;01m%s\u001b[39;00m\u001b[33m'\u001b[39m\u001b[33m is already opened. Please \u001b[39m\u001b[33m\"\u001b[39m\n\u001b[32m 293\u001b[39m \u001b[33m\"\u001b[39m\u001b[33mclose it before reopening in write mode.\u001b[39m\u001b[33m\"\u001b[39m % filename)\n\u001b[32m 295\u001b[39m \u001b[38;5;66;03m# Finally, create the File instance, and return it\u001b[39;00m\n\u001b[32m--> \u001b[39m\u001b[32m296\u001b[39m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43mFile\u001b[49m\u001b[43m(\u001b[49m\u001b[43mfilename\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mmode\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mtitle\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mroot_uep\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mfilters\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43m*\u001b[49m\u001b[43m*\u001b[49m\u001b[43mkwargs\u001b[49m\u001b[43m)\u001b[49m\n", + "\u001b[36mFile \u001b[39m\u001b[32m~/.conda/envs/valid/lib/python3.11/site-packages/tables/file.py:746\u001b[39m, in \u001b[36mFile.__init__\u001b[39m\u001b[34m(self, filename, mode, title, root_uep, filters, **kwargs)\u001b[39m\n\u001b[32m 743\u001b[39m \u001b[38;5;28mself\u001b[39m.params = params\n\u001b[32m 745\u001b[39m \u001b[38;5;66;03m# Now, it is time to initialize the File extension\u001b[39;00m\n\u001b[32m--> \u001b[39m\u001b[32m746\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[43m.\u001b[49m\u001b[43m_g_new\u001b[49m\u001b[43m(\u001b[49m\u001b[43mfilename\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mmode\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43m*\u001b[49m\u001b[43m*\u001b[49m\u001b[43mparams\u001b[49m\u001b[43m)\u001b[49m\n\u001b[32m 748\u001b[39m \u001b[38;5;66;03m# Check filters and set PyTables format version for new files.\u001b[39;00m\n\u001b[32m 749\u001b[39m new = \u001b[38;5;28mself\u001b[39m._v_new\n", + "\u001b[36mFile \u001b[39m\u001b[32m~/.conda/envs/valid/lib/python3.11/site-packages/tables/hdf5extension.pyx:514\u001b[39m, in \u001b[36mtables.hdf5extension.File._g_new\u001b[39m\u001b[34m()\u001b[39m\n", + "\u001b[31mHDF5ExtError\u001b[39m: HDF5 error back trace\n\n File \"H5F.c\", line 836, in H5Fopen\n unable to synchronously open file\n File \"H5F.c\", line 796, in H5F__open_api_common\n unable to open file\n File \"H5VLcallback.c\", line 3863, in H5VL_file_open\n open failed\n File \"H5VLcallback.c\", line 3675, in H5VL__file_open\n open failed\n File \"H5VLnative_file.c\", line 128, in H5VL__native_file_open\n unable to open file\n File \"H5Fint.c\", line 2018, in H5F_open\n unable to read superblock\n File \"H5Fsuper.c\", line 600, in H5F__super_read\n truncated file: eof = 96, sblock->base_addr = 0, stored_eof = 2048\n\nEnd of HDF5 error back trace\n\nUnable to open/create file './POSYDON_main/outputs/candidate_main.h5'" + ] + } + ], + "source": [ + "df = pd.read_hdf('./POSYDON_main/outputs/candidate_main.h5', \"evolution\")\n", + "warnings = pd.read_hdf('./POSYDON_main/outputs/candidate_main.h5', \"warnings\")" + ] + }, + { + "cell_type": "code", + "execution_count": 56, + "id": "7028a060", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Index(['state', 'event', 'time', 'separation', 'orbital_period',\n", + " 'eccentricity', 'rl_relative_overflow_1', 'rl_relative_overflow_2',\n", + " 'lg_mtransfer_rate', 'mass_transfer_case',\n", + " ...\n", + " 'S2_mass_conv_reg_fortides', 'S2_thickness_conv_reg_fortides',\n", + " 'S2_radius_conv_reg_fortides', 'S2_lambda_CE_1cent',\n", + " 'S2_lambda_CE_10cent', 'S2_lambda_CE_30cent',\n", + " 'S2_lambda_CE_pure_He_star_10cent', 'S2_total_mass_h1',\n", + " 'S2_total_mass_he4', 'binary_id'],\n", + " dtype='object', length=134)\n" + ] + } + ], + "source": [ + "print(df.keys())" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "id": "76233b25", + "metadata": { + "collapsed": true + }, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
binary_idexception_typeexception_message
01ValueErrorTrying to store a string with len [27] in [S1_...
02ValueErrorTrying to store a string with len [12] in [sta...
03ValueErrorTrying to store a string with len [9] in [even...
04ValueErrorTrying to store a string with len [9] in [even...
05ValueErrorTrying to store a string with len [9] in [even...
07ValueErrorTrying to store a string with len [27] in [S1_...
08ValueErrorTrying to store a string with len [10] in [eve...
09ValueErrorTrying to store a string with len [7] in [even...
010ValueErrorTrying to store a string with len [27] in [S1_...
011ValueErrorTrying to store a string with len [7] in [even...
012ValueErrorTrying to store a string with len [7] in [even...
013ValueErrorTrying to store a string with len [7] in [even...
014ValueErrorTrying to store a string with len [23] in [S1_...
015ValueErrorTrying to store a string with len [9] in [even...
016ValueErrorTrying to store a string with len [9] in [even...
018ValueErrorTrying to store a string with len [7] in [even...
019ValueErrorTrying to store a string with len [7] in [even...
020ValueErrorTrying to store a string with len [7] in [even...
021ValueErrorTrying to store a string with len [7] in [even...
022ValueErrorTrying to store a string with len [9] in [even...
023ValueErrorTrying to store a string with len [9] in [even...
024ValueErrorTrying to store a string with len [9] in [even...
025ValueErrorTrying to store a string with len [7] in [even...
026ValueErrorTrying to store a string with len [9] in [even...
027ValueErrorTrying to store a string with len [7] in [even...
028ValueErrorTrying to store a string with len [7] in [even...
029ValueErrorTrying to store a string with len [7] in [even...
030ValueErrorTrying to store a string with len [7] in [even...
031ValueErrorTrying to store a string with len [7] in [even...
032ValueErrorTrying to store a string with len [7] in [even...
033ValueErrorTrying to store a string with len [7] in [even...
034ValueErrorTrying to store a string with len [7] in [even...
035ValueErrorTrying to store a string with len [9] in [even...
036ValueErrorTrying to store a string with len [7] in [even...
037ValueErrorTrying to store a string with len [10] in [eve...
038ValueErrorTrying to store a string with len [9] in [even...
039MatchingErrorGrid matching failed for merged binary. \\nseco...
040ClassificationErrorBinary is in the detached step but has stable ...
041ValueErrorTrying to store a string with len [7] in [even...
042FlowErrorEvolution of H-rich/He-rich stars in RLO onto ...
043ValueErrorTrying to store a string with len [7] in [even...
\n", + "
" + ], + "text/plain": [ + " binary_id exception_type \\\n", + "0 1 ValueError \n", + "0 2 ValueError \n", + "0 3 ValueError \n", + "0 4 ValueError \n", + "0 5 ValueError \n", + "0 7 ValueError \n", + "0 8 ValueError \n", + "0 9 ValueError \n", + "0 10 ValueError \n", + "0 11 ValueError \n", + "0 12 ValueError \n", + "0 13 ValueError \n", + "0 14 ValueError \n", + "0 15 ValueError \n", + "0 16 ValueError \n", + "0 18 ValueError \n", + "0 19 ValueError \n", + "0 20 ValueError \n", + "0 21 ValueError \n", + "0 22 ValueError \n", + "0 23 ValueError \n", + "0 24 ValueError \n", + "0 25 ValueError \n", + "0 26 ValueError \n", + "0 27 ValueError \n", + "0 28 ValueError \n", + "0 29 ValueError \n", + "0 30 ValueError \n", + "0 31 ValueError \n", + "0 32 ValueError \n", + "0 33 ValueError \n", + "0 34 ValueError \n", + "0 35 ValueError \n", + "0 36 ValueError \n", + "0 37 ValueError \n", + "0 38 ValueError \n", + "0 39 MatchingError \n", + "0 40 ClassificationError \n", + "0 41 ValueError \n", + "0 42 FlowError \n", + "0 43 ValueError \n", + "\n", + " exception_message \n", + "0 Trying to store a string with len [27] in [S1_... \n", + "0 Trying to store a string with len [12] in [sta... \n", + "0 Trying to store a string with len [9] in [even... \n", + "0 Trying to store a string with len [9] in [even... \n", + "0 Trying to store a string with len [9] in [even... \n", + "0 Trying to store a string with len [27] in [S1_... \n", + "0 Trying to store a string with len [10] in [eve... \n", + "0 Trying to store a string with len [7] in [even... \n", + "0 Trying to store a string with len [27] in [S1_... \n", + "0 Trying to store a string with len [7] in [even... \n", + "0 Trying to store a string with len [7] in [even... \n", + "0 Trying to store a string with len [7] in [even... \n", + "0 Trying to store a string with len [23] in [S1_... \n", + "0 Trying to store a string with len [9] in [even... \n", + "0 Trying to store a string with len [9] in [even... \n", + "0 Trying to store a string with len [7] in [even... \n", + "0 Trying to store a string with len [7] in [even... \n", + "0 Trying to store a string with len [7] in [even... \n", + "0 Trying to store a string with len [7] in [even... \n", + "0 Trying to store a string with len [9] in [even... \n", + "0 Trying to store a string with len [9] in [even... \n", + "0 Trying to store a string with len [9] in [even... \n", + "0 Trying to store a string with len [7] in [even... \n", + "0 Trying to store a string with len [9] in [even... \n", + "0 Trying to store a string with len [7] in [even... \n", + "0 Trying to store a string with len [7] in [even... \n", + "0 Trying to store a string with len [7] in [even... \n", + "0 Trying to store a string with len [7] in [even... \n", + "0 Trying to store a string with len [7] in [even... \n", + "0 Trying to store a string with len [7] in [even... \n", + "0 Trying to store a string with len [7] in [even... \n", + "0 Trying to store a string with len [7] in [even... \n", + "0 Trying to store a string with len [9] in [even... \n", + "0 Trying to store a string with len [7] in [even... \n", + "0 Trying to store a string with len [10] in [eve... \n", + "0 Trying to store a string with len [9] in [even... \n", + "0 Grid matching failed for merged binary. \\nseco... \n", + "0 Binary is in the detached step but has stable ... \n", + "0 Trying to store a string with len [7] in [even... \n", + "0 Evolution of H-rich/He-rich stars in RLO onto ... \n", + "0 Trying to store a string with len [7] in [even... " + ] + }, + "execution_count": 20, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "errors" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "68d4d8a8", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "valid", + "language": "python", + "name": "valid" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.11.14" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/dev-tools/compare_runs.py b/dev-tools/compare_runs.py index 6ff28d81e2..0d2fe2df7e 100644 --- a/dev-tools/compare_runs.py +++ b/dev-tools/compare_runs.py @@ -1,75 +1,412 @@ #!/usr/bin/env python3 - """ -Compare evolution outcomes of set of binaries saved to file with script_data/1Zsun_binaries_suite.py -Used for validation of the branch. +Compare evolution outcomes of test binaries saved by binaries_suite.py. -Author: Elizabeth Teng -""" +Reports three categories of differences: + 1. QUANTITATIVE: any numeric difference beyond floating-point representation + 2. QUALITATIVE: changes to categorical/string columns (states, events, step names, SN types, etc.) + 3. WARNINGS & ERRORS: changes to warnings raised or binaries that error out +By default, uses exact comparison (atol=0, rtol=0). The --loose flag enables +a small tolerance for cases where minor floating-point differences are expected. -import sys +Usage: + python compare_runs.py baseline.h5 candidate.h5 + python compare_runs.py baseline.h5 candidate.h5 --verbose + python compare_runs.py baseline.h5 candidate.h5 --loose + +Authors: Elizabeth Teng +""" -import h5py +import argparse +import sys +import os import numpy as np +import pandas as pd -def compare_datasets(base, cand, path="/"): - """ - Recursively compare HDF5 datasets. - Returns a list of strings with differences. +# Columns that represent qualitative (categorical) evolution properties. +# Any column matching these names will be compared as exact string matches +# and reported under "QUALITATIVE" differences. +QUALITATIVE_COLUMNS = { + 'state', 'event', 'step_names', 'S1_state', 'S2_state', + 'SN_type', 'S1_SN_type', 'S2_SN_type', + 'interp_class_HMS_HMS', 'interp_class_CO_HMS_RLO', + 'interp_class_CO_HeMS', 'interp_class_CO_HeMS_RLO', + 'mt_history_HMS_HMS', 'mt_history_CO_HMS_RLO', + 'mt_history_CO_HeMS', 'mt_history_CO_HeMS_RLO', + 'mass_transfer_case', +} + + +def classify_column(col, dtype): + """Classify a column as 'qualitative' or 'quantitative'.""" + if col in QUALITATIVE_COLUMNS: + return 'qualitative' + if pd.api.types.is_numeric_dtype(dtype): + return 'quantitative' + # Catch-all: treat remaining object/string columns as qualitative + return 'qualitative' + + +def compare_evolution_tables(base_df, cand_df, rtol, atol): + """Compare two evolution DataFrames, reporting per-binary diffs. + + Returns: + dict with keys 'quantitative', 'qualitative', 'structural' + each mapping to a list of diff strings. """ - differences = [] + quant_diffs = [] + qual_diffs = [] + struct_diffs = [] + + # Check that binary_id columns exist + if 'binary_id' not in base_df.columns or 'binary_id' not in cand_df.columns: + struct_diffs.append("'binary_id' column missing; cannot do per-binary comparison") + return {'quantitative': quant_diffs, 'qualitative': qual_diffs, 'structural': struct_diffs} + + base_ids = set(base_df['binary_id'].unique()) + cand_ids = set(cand_df['binary_id'].unique()) + + # Missing/extra binaries + for bid in sorted(base_ids - cand_ids): + struct_diffs.append(f"Binary {bid}: MISSING in candidate") + for bid in sorted(cand_ids - base_ids): + struct_diffs.append(f"Binary {bid}: EXTRA in candidate") + + common_ids = sorted(base_ids & cand_ids) - for key in base.keys(): - base_item = base[key] - if key not in cand: - differences.append(f"{path}{key} missing in candidate") + for bid in common_ids: + b = base_df[base_df['binary_id'] == bid].reset_index(drop=True) + c = cand_df[cand_df['binary_id'] == bid].reset_index(drop=True) + + # ── Error status changes ────────────────────────────────────── + base_failed = 'exception_type' in b.columns and b['exception_type'].notna().any() + cand_failed = 'exception_type' in c.columns and c['exception_type'].notna().any() + + if base_failed != cand_failed: + if cand_failed: + exc = c['exception_type'].dropna().iloc[0] if 'exception_type' in c.columns else "unknown" + msg = c['exception_message'].dropna().iloc[0] if 'exception_message' in c.columns else "" + struct_diffs.append(f"Binary {bid}: NEWLY FAILING ({exc}: {msg})") + else: + struct_diffs.append(f"Binary {bid}: NEWLY PASSING (was failing in baseline)") + continue + + if base_failed and cand_failed: + b_exc = str(b['exception_type'].dropna().iloc[0]) if 'exception_type' in b.columns else "" + c_exc = str(c['exception_type'].dropna().iloc[0]) if 'exception_type' in c.columns else "" + b_msg = str(b['exception_message'].dropna().iloc[0]) if 'exception_message' in b.columns else "" + c_msg = str(c['exception_message'].dropna().iloc[0]) if 'exception_message' in c.columns else "" + if b_exc != c_exc: + struct_diffs.append(f"Binary {bid}: error type changed ('{b_exc}' -> '{c_exc}')") + if b_msg != c_msg: + struct_diffs.append(f"Binary {bid}: error message changed ('{b_msg}' -> '{c_msg}')") continue - cand_item = cand[key] + # ── Step count ──────────────────────────────────────────────── + if len(b) != len(c): + struct_diffs.append( + f"Binary {bid}: evolution step count differs " + f"(baseline={len(b)}, candidate={len(c)})" + ) + + # ── Column presence ─────────────────────────────────────────── + base_only_cols = set(b.columns) - set(c.columns) - {'binary_id'} + cand_only_cols = set(c.columns) - set(b.columns) - {'binary_id'} + if base_only_cols: + struct_diffs.append(f"Binary {bid}: columns only in baseline: {sorted(base_only_cols)}") + if cand_only_cols: + struct_diffs.append(f"Binary {bid}: columns only in candidate: {sorted(cand_only_cols)}") + + # ── Per-column comparison ───────────────────────────────────── + common_cols = sorted(set(b.columns) & set(c.columns) - {'binary_id'}) + min_rows = min(len(b), len(c)) + + for col in common_cols: + b_col = b[col].iloc[:min_rows] + c_col = c[col].iloc[:min_rows] + col_type = classify_column(col, b_col.dtype) - if isinstance(base_item, h5py.Dataset): - base_data = base_item[()] - cand_data = cand_item[()] + if col_type == 'quantitative': + b_arr = b_col.to_numpy(dtype=float) + c_arr = c_col.to_numpy(dtype=float) + + # NaN handling: both NaN = match, one NaN = mismatch + both_nan = np.isnan(b_arr) & np.isnan(c_arr) + one_nan = np.isnan(b_arr) ^ np.isnan(c_arr) + + if one_nan.any(): + nan_steps = np.where(one_nan)[0].tolist() + direction = [] + for s in nan_steps[:5]: + bv = "NaN" if np.isnan(b_arr[s]) else f"{b_arr[s]:.6g}" + cv = "NaN" if np.isnan(c_arr[s]) else f"{c_arr[s]:.6g}" + direction.append(f"step {s}: {bv} -> {cv}") + quant_diffs.append( + f"Binary {bid}, '{col}': NaN mismatch at {len(nan_steps)} step(s): " + + "; ".join(direction) + ) + + # Compare non-NaN values + valid = ~(np.isnan(b_arr) | np.isnan(c_arr)) + if valid.any(): + b_valid = b_arr[valid] + c_valid = c_arr[valid] + not_equal = b_valid != c_valid + + if rtol == 0 and atol == 0: + # Exact comparison + if not_equal.any(): + diff_indices = np.where(valid)[0][not_equal] + abs_diff = np.abs(b_valid[not_equal] - c_valid[not_equal]) + worst = np.argmax(abs_diff) + worst_step = diff_indices[worst] + quant_diffs.append( + f"Binary {bid}, '{col}': {not_equal.sum()} value(s) differ. " + f"Largest abs diff = {abs_diff[worst]:.6e} " + f"at step {worst_step} " + f"(baseline={b_valid[not_equal][worst]:.15g}, " + f"candidate={c_valid[not_equal][worst]:.15g})" + ) + else: + # Tolerance-based comparison + if not np.allclose(b_valid, c_valid, rtol=rtol, atol=atol): + abs_diff = np.abs(b_valid - c_valid) + with np.errstate(divide='ignore', invalid='ignore'): + denom = np.maximum(np.abs(b_valid), atol) + rel_diff = abs_diff / denom + worst = np.argmax(abs_diff) + worst_step = np.where(valid)[0][worst] + quant_diffs.append( + f"Binary {bid}, '{col}': numeric mismatch " + f"(max abs diff = {abs_diff[worst]:.6e}, " + f"max rel diff = {rel_diff[worst]:.6e}, " + f"at step {worst_step}, " + f"baseline={b_valid[worst]:.15g}, " + f"candidate={c_valid[worst]:.15g})" + ) - if np.issubdtype(base_data.dtype, np.number): - if not np.allclose(base_data, cand_data, rtol=1e-5, atol=1e-8): - differences.append(f"{path}{key} numeric mismatch") else: - if not np.array_equal(base_data, cand_data): - differences.append(f"{path}{key} non-numeric mismatch") + # Qualitative comparison: exact string match + b_str = b_col.astype(str).values + c_str = c_col.astype(str).values + mismatches = np.where(b_str != c_str)[0] + if len(mismatches) > 0: + details = [] + for s in mismatches[:5]: + details.append(f"step {s}: '{b_str[s]}' -> '{c_str[s]}'") + qual_diffs.append( + f"Binary {bid}, '{col}': {len(mismatches)} step(s) differ: " + + "; ".join(details) + ) - elif isinstance(base_item, h5py.Group): - differences.extend(compare_datasets(base_item, cand_item, path=f"{path}{key}/")) + return {'quantitative': quant_diffs, 'qualitative': qual_diffs, 'structural': struct_diffs} - # Check for extra keys in candidate - for key in cand.keys(): - if key not in base: - differences.append(f"{path}{key} extra in candidate") - return differences +def compare_warnings_tables(base_df, cand_df): + """Compare warning tables between baseline and candidate. + + Returns list of diff strings. + """ + diffs = [] + + if base_df is None and cand_df is None: + return diffs + if base_df is None: + diffs.append(f"Candidate has {len(cand_df)} warning(s), baseline has none") + return diffs + if cand_df is None: + diffs.append(f"Baseline has {len(base_df)} warning(s), candidate has none") + return diffs + + if len(base_df) != len(cand_df): + diffs.append(f"Total warning count differs (baseline={len(base_df)}, candidate={len(cand_df)})") + + # Per-binary warning comparison + if 'binary_id' in base_df.columns and 'binary_id' in cand_df.columns: + base_grouped = base_df.groupby('binary_id') + cand_grouped = cand_df.groupby('binary_id') + all_ids = sorted(set(base_df['binary_id'].unique()) | set(cand_df['binary_id'].unique())) + + for bid in all_ids: + b_warnings = base_grouped.get_group(bid) if bid in base_grouped.groups else pd.DataFrame() + c_warnings = cand_grouped.get_group(bid) if bid in cand_grouped.groups else pd.DataFrame() + + b_count = len(b_warnings) + c_count = len(c_warnings) + + if b_count == 0 and c_count > 0: + cats = c_warnings['category'].unique().tolist() if 'category' in c_warnings.columns else ['unknown'] + diffs.append(f"Binary {bid}: {c_count} NEW warning(s) in candidate ({', '.join(str(c) for c in cats)})") + elif b_count > 0 and c_count == 0: + diffs.append(f"Binary {bid}: {b_count} warning(s) REMOVED in candidate") + elif b_count != c_count: + diffs.append(f"Binary {bid}: warning count changed ({b_count} -> {c_count})") + elif b_count > 0: + # Same count — check if warning categories or messages changed + if 'category' in b_warnings.columns and 'category' in c_warnings.columns: + b_cats = sorted(b_warnings['category'].astype(str).tolist()) + c_cats = sorted(c_warnings['category'].astype(str).tolist()) + if b_cats != c_cats: + diffs.append(f"Binary {bid}: warning categories changed ({b_cats} -> {c_cats})") + + if 'message' in b_warnings.columns and 'message' in c_warnings.columns: + b_msgs = sorted(b_warnings['message'].astype(str).tolist()) + c_msgs = sorted(c_warnings['message'].astype(str).tolist()) + if b_msgs != c_msgs: + diffs.append(f"Binary {bid}: warning messages changed") + + return diffs + + +def read_table_safe(store, key): + """Read a table from HDFStore, returning None if it doesn't exist.""" + try: + if key in store: + return store[key] + except Exception: + pass + return None def main(): - if len(sys.argv) != 3: - print("Usage: compare_runs.py baseline.h5 candidate.h5") - sys.exit(1) + parser = argparse.ArgumentParser( + description="Compare baseline and candidate binary evolution HDF5 files.", + formatter_class=argparse.RawDescriptionHelpFormatter, + epilog=""" +By default, uses EXACT comparison (any numeric difference is reported). +Use --loose to allow small floating-point tolerances (rtol=1e-12, atol=1e-15). + """, + ) + parser.add_argument("baseline", help="Path to baseline HDF5 file") + parser.add_argument("candidate", help="Path to candidate HDF5 file") + parser.add_argument("--loose", action="store_true", + help="Allow small floating-point tolerance (rtol=1e-12, atol=1e-15)") + parser.add_argument("--rtol", type=float, default=None, + help="Override relative tolerance (default: 0, or 1e-12 with --loose)") + parser.add_argument("--atol", type=float, default=None, + help="Override absolute tolerance (default: 0, or 1e-15 with --loose)") + parser.add_argument("--verbose", "-v", action="store_true", + help="Print extra diagnostic info") + args = parser.parse_args() - baseline_file = sys.argv[1] - candidate_file = sys.argv[2] + # Set tolerances + if args.loose: + rtol = args.rtol if args.rtol is not None else 1e-12 + atol = args.atol if args.atol is not None else 1e-15 + else: + rtol = args.rtol if args.rtol is not None else 0.0 + atol = args.atol if args.atol is not None else 0.0 - with h5py.File(baseline_file, 'r') as base, h5py.File(candidate_file, 'r') as cand: - diffs = compare_datasets(base, cand) + for f in [args.baseline, args.candidate]: + if not os.path.exists(f): + print(f"ERROR: File not found: {f}", file=sys.stderr) + sys.exit(2) - if diffs: - print("Differences found:") - for diff in diffs: - print(" -", diff) - sys.exit(1) + quant_diffs = [] + qual_diffs = [] + struct_diffs = [] + warn_diffs = [] + + try: + with pd.HDFStore(args.baseline, mode='r') as base_store, \ + pd.HDFStore(args.candidate, mode='r') as cand_store: + + base_keys = set(base_store.keys()) + cand_keys = set(cand_store.keys()) + + if args.verbose: + print(f"Baseline keys: {sorted(base_keys)}") + print(f"Candidate keys: {sorted(cand_keys)}") + + # ── Evolution table ─────────────────────────────────────── + base_evol = read_table_safe(base_store, '/evolution') + cand_evol = read_table_safe(cand_store, '/evolution') + + if base_evol is None and cand_evol is None: + struct_diffs.append("Neither file contains an 'evolution' table") + elif base_evol is None: + struct_diffs.append("Baseline missing 'evolution' table") + elif cand_evol is None: + struct_diffs.append("Candidate missing 'evolution' table") + else: + if args.verbose: + n_base = base_evol['binary_id'].nunique() if 'binary_id' in base_evol.columns else '?' + n_cand = cand_evol['binary_id'].nunique() if 'binary_id' in cand_evol.columns else '?' + print(f"Baseline: {n_base} binaries, {len(base_evol)} total rows") + print(f"Candidate: {n_cand} binaries, {len(cand_evol)} total rows") + + evol_results = compare_evolution_tables(base_evol, cand_evol, rtol, atol) + quant_diffs.extend(evol_results['quantitative']) + qual_diffs.extend(evol_results['qualitative']) + struct_diffs.extend(evol_results['structural']) + + # ── Warnings table ──────────────────────────────────────── + base_warn = read_table_safe(base_store, '/warnings') + cand_warn = read_table_safe(cand_store, '/warnings') + warn_diffs.extend(compare_warnings_tables(base_warn, cand_warn)) + + # ── Extra/missing top-level keys ────────────────────────── + for k in sorted(base_keys - cand_keys): + if k not in ['/evolution', '/warnings', '/metadata']: + struct_diffs.append(f"Table '{k}' missing in candidate") + for k in sorted(cand_keys - base_keys): + if k not in ['/evolution', '/warnings', '/metadata']: + struct_diffs.append(f"Table '{k}' extra in candidate") + + except Exception as e: + print(f"ERROR reading HDF5 files: {e}", file=sys.stderr) + sys.exit(2) + + # ── Report ──────────────────────────────────────────────────────────── + total_diffs = len(quant_diffs) + len(qual_diffs) + len(struct_diffs) + len(warn_diffs) + tol_label = f"rtol={rtol}, atol={atol}" if rtol > 0 or atol > 0 else "EXACT (rtol=0, atol=0)" + + print("=" * 70) + print("POSYDON Binary Validation — Comparison Report") + print(f" Baseline: {args.baseline}") + print(f" Candidate: {args.candidate}") + print(f" Tolerances: {tol_label}") + print("=" * 70) + + if struct_diffs: + print(f"\n--- STRUCTURAL ({len(struct_diffs)}) ---") + print(" (missing/extra binaries, step count changes, newly failing/passing, errors)\n") + for d in struct_diffs: + print(f" - {d}") + + if qual_diffs: + print(f"\n--- QUALITATIVE ({len(qual_diffs)}) ---") + print(" (state, event, step name, SN type, interpolation class changes)\n") + for d in qual_diffs: + print(f" - {d}") + + if quant_diffs: + print(f"\n--- QUANTITATIVE ({len(quant_diffs)}) ---") + print(" (any numeric value change)\n") + for d in quant_diffs: + print(f" - {d}") + + if warn_diffs: + print(f"\n--- WARNINGS ({len(warn_diffs)}) ---") + print(" (new, removed, or changed warnings)\n") + for d in warn_diffs: + print(f" - {d}") + + print("\n" + "=" * 70) + if total_diffs == 0: + print("RESULT: IDENTICAL — candidate matches baseline exactly.") + sys.exit(0) else: - print("No differences detected between baseline and candidate.") + print(f"RESULT: {total_diffs} DIFFERENCE(S) DETECTED") + print(f" Structural: {len(struct_diffs)}") + print(f" Qualitative: {len(qual_diffs)}") + print(f" Quantitative: {len(quant_diffs)}") + print(f" Warnings: {len(warn_diffs)}") + print("=" * 70) + sys.exit(1) if __name__ == "__main__": - main() + main() \ No newline at end of file diff --git a/dev-tools/evolve_binaries.sh b/dev-tools/evolve_binaries.sh index 2021995bff..8bfcceef2a 100755 --- a/dev-tools/evolve_binaries.sh +++ b/dev-tools/evolve_binaries.sh @@ -1,69 +1,86 @@ #!/bin/bash -# Script usage: ./evolve_binaries.sh -# This script clones the POSYDON repo to the specified branch (defaults to 'main'), -# copies evolve_binaries.py, runs it, and saves output to evolve_binaries.out - -# Set default branch to 'main' if not provided -BRANCH=${1:-main} -REPO_URL="https://github.com/POSYDON-code/POSYDON" - -if [[ -n "$2" ]]; then - SHA=$2 - WORK_DIR="POSYDON_${BRANCH}_${SHA}" -else - WORK_DIR="POSYDON_$BRANCH" -fi - -# Remove existing directory if it exists -if [ -d "$WORK_DIR" ]; then - echo "šŸ—‘ļø Removing existing directory: $WORK_DIR" - rm -rf "$WORK_DIR" +# ============================================================================= +# evolve_binaries.sh — Clone a POSYDON branch, install it, and run the +# binary validation suite at all requested metallicities. +# +# Usage: +# ./evolve_binaries.sh [sha] [metallicities] +# +# Examples: +# ./evolve_binaries.sh main # all metallicities +# ./evolve_binaries.sh feature/my-fix abc123f # specific commit +# ./evolve_binaries.sh main "" "1 0.45 0.1" # subset of metallicities +# +# Output structure: +# outputs//candidate_Zsun.h5 — evolution results per metallicity +# logs//evolve_Zsun.log — log per metallicity +# workdirs/POSYDON_/ — cloned repo + conda env +# ============================================================================= + +set -euo pipefail +# Load git if needed +if ! command -v git >/dev/null 2>&1; then + if command -v module >/dev/null 2>&1; then + module load git + fi fi -echo "šŸ“ Creating working directory: $WORK_DIR" -# Create the working directory -mkdir -p "$WORK_DIR" +# ── Configuration ────────────────────────────────────────────────────────── +ALL_METALLICITIES="2 1 0.45 0.2 0.1 0.01 0.001 0.0001" -FULL_PATH="$(realpath "$WORK_DIR")" -CLONE_DIR="$FULL_PATH/POSYDON" +BRANCH=${1:-main} +SHA=${2:-} +METALLICITIES=${3:-$ALL_METALLICITIES} -OUTPUT_DIR="$FULL_PATH/outputs" -LOG_DIR="$FULL_PATH/logs" +REPO_URL="https://github.com/POSYDON-code/POSYDON" +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +# Sanitize branch name for filesystem SAFE_BRANCH="${BRANCH//\//_}" -OUTPUT_FILE="$OUTPUT_DIR/candidate_${SAFE_BRANCH}.h5" -LOG_FILE="$LOG_DIR/evolve_${SAFE_BRANCH}.log" -mkdir -p "$OUTPUT_DIR" "$LOG_DIR" -echo "šŸ“‹ Copying script_data folder" -# copy the script_data folder -cp -r "./script_data" "$WORK_DIR" +# Directories (all relative to SCRIPT_DIR, the dev-tools root) +WORK_DIR="$SCRIPT_DIR/workdirs/POSYDON_${SAFE_BRANCH}" +OUTPUT_DIR="$SCRIPT_DIR/outputs/${SAFE_BRANCH}" +LOG_DIR="$SCRIPT_DIR/logs/${SAFE_BRANCH}" +CLONE_DIR="$WORK_DIR/POSYDON" -cd "$WORK_DIR" +mkdir -p "$OUTPUT_DIR" "$LOG_DIR" -# Initialize conda for bash +# ── Conda Setup ──────────────────────────────────────────────────────────── echo "šŸ”§ Initializing conda" -# Source conda's shell integration -if [ -f "$HOME/miniconda3/etc/profile.d/conda.sh" ]; then - source "$HOME/miniconda3/etc/profile.d/conda.sh" -elif [ -f "$HOME/anaconda3/etc/profile.d/conda.sh" ]; then - source "$HOME/anaconda3/etc/profile.d/conda.sh" -elif [ -f "/opt/homebrew/Caskroom/miniconda/base/etc/profile.d/conda.sh" ]; then - source "/opt/homebrew/Caskroom/miniconda/base/etc/profile.d/conda.sh" -elif command -v conda >/dev/null 2>&1; then - CONDA_BASE=$(conda info --base) - source "${CONDA_BASE}/etc/profile.d/conda.sh" -else - echo -e "\033[31mError: Could not find conda installation. Please check your conda setup.\033[0m" - exit 1 +CONDA_SH="" +for candidate in \ + "$HOME/miniconda3/etc/profile.d/conda.sh" \ + "$HOME/anaconda3/etc/profile.d/conda.sh" \ + "/opt/homebrew/Caskroom/miniconda/base/etc/profile.d/conda.sh"; do + if [ -f "$candidate" ]; then + CONDA_SH="$candidate" + break + fi +done + +if [ -z "$CONDA_SH" ]; then + if command -v conda >/dev/null 2>&1; then + CONDA_SH="$(conda info --base)/etc/profile.d/conda.sh" + else + echo "ERROR: Could not find conda installation." >&2 + exit 1 + fi fi +source "$CONDA_SH" + +# ── Clone Repository ────────────────────────────────────────────────────── +if [ -d "$WORK_DIR" ]; then + echo "šŸ—‘ļø Removing existing work directory: $WORK_DIR" + rm -rf "$WORK_DIR" +fi +mkdir -p "$WORK_DIR" -# Clone the repository to the specified branch echo "šŸ”„ Cloning POSYDON repository (branch: $BRANCH)" -if ! git clone -b "$BRANCH" "$REPO_URL" "$CLONE_DIR" 2>&1 | sed 's/^/ /'; then - echo -e "\033[31mError: Failed to clone branch '$BRANCH'. Please check if the branch exists.\033[0m" +if ! git clone -b "$BRANCH" "$REPO_URL" "$CLONE_DIR" 2>&1 | sed 's/^/ /'; then + echo "ERROR: Failed to clone branch '$BRANCH'." >&2 exit 1 fi @@ -78,29 +95,59 @@ if [[ -n "$SHA" ]]; then cd - fi -# Create conda environment for POSYDON v2 -echo "šŸ Creating conda environment" -conda create --prefix="$FULL_PATH/conda_env" python=3.11 -y -q 2>&1 | sed 's/^/ /' +# ── Create Conda Environment ───────────────────────────────────────────── +ENV_PREFIX="$WORK_DIR/conda_env" -echo "⚔ Activating conda environment" -conda activate "$FULL_PATH/conda_env" +echo "šŸ Creating conda environment at $ENV_PREFIX" +conda create --prefix="$ENV_PREFIX" python=3.11 -y -q 2>&1 | sed 's/^/ /' +conda activate "$ENV_PREFIX" -# install POSYDON manually echo "šŸ“¦ Installing POSYDON" -pip install -e "$CLONE_DIR" -q 2>&1 | sed 's/^/ /' - -echo "šŸš€ Running evolve_binaries.py" -# # Run the Python script and capture output (stdout and stderr) -python script_data/1Zsun_binaries_suite.py --output "$OUTPUT_FILE" 2>&1 | tee "$LOG_FILE" +pip install -e "$CLONE_DIR" -q 2>&1 | sed 's/^/ /' + +# ── Run Suite for Each Metallicity ──────────────────────────────────────── +SUITE_SCRIPT="$SCRIPT_DIR/script_data/binaries_suite.py" +FAILED=0 + +for Z in $METALLICITIES; do + OUTPUT_FILE="$OUTPUT_DIR/candidate_${Z}Zsun.h5" + LOG_FILE="$LOG_DIR/evolve_${Z}Zsun.log" + + echo "" + echo "============================================================" + echo " šŸš€ Evolving binaries for Z = ${Z} Zsun" + echo " Output: $OUTPUT_FILE" + echo " Log: $LOG_FILE" + echo "============================================================" + + if python "$SUITE_SCRIPT" \ + --metallicity "$Z" \ + --output "$OUTPUT_FILE" \ + 2>&1 | tee "$LOG_FILE"; then + + if [ ! -f "$OUTPUT_FILE" ]; then + echo "WARNING: Output file not created for Z=${Z}" >&2 + FAILED=$((FAILED + 1)) + else + echo " Z=${Z} Zsun complete." + fi + else + echo "WARNING: Suite failed for Z=${Z}. Check $LOG_FILE" >&2 + FAILED=$((FAILED + 1)) + fi +done -if [ ! -f "$OUTPUT_FILE" ]; then - echo "ERROR: Results file was not created: $OUTPUT_FILE" - exit 2 -fi +# ── Deactivate Environment ──────────────────────────────────────────────── +conda deactivate -if [ $? -ne 0 ]; then - echo "ERROR: Python script exited with an error. Check $LOG_FILE for details." - exit 3 +echo "" +echo "============================================================" +if [ $FAILED -eq 0 ]; then + echo "āœ… All metallicities completed successfully." +else + echo "Completed with $FAILED failure(s)." fi +echo " Outputs in: $OUTPUT_DIR/" +echo "============================================================" -echo -e "āœ… Script completed. Output saved to \n$OUTPUT_FILE" +exit $FAILED \ No newline at end of file diff --git a/dev-tools/generate_baseline.sh b/dev-tools/generate_baseline.sh new file mode 100644 index 0000000000..a4e31534a7 --- /dev/null +++ b/dev-tools/generate_baseline.sh @@ -0,0 +1,96 @@ +#!/bin/bash +# ============================================================================= +# generate_baseline.sh — Generate baseline HDF5 files from a designated branch. +# +# This runs the binary validation suite against a chosen branch (or commit) +# and saves the results as the baseline for future comparisons. +# +# Usage: +# ./generate_baseline.sh [sha] [metallicities] +# +# Examples: +# ./generate_baseline.sh main # baseline from main, all Z +# ./generate_baseline.sh v2.1.0 # baseline from a release tag +# ./generate_baseline.sh main abc123f # baseline from a specific commit +# ./generate_baseline.sh main "" "1 0.45" # baseline for subset of Z +# +# Output: +# baselines//baseline_Zsun.h5 — one file per metallicity +# baselines//baseline_info.txt — records branch, commit SHA, date +# ============================================================================= + +set -euo pipefail + +BRANCH=${1:-main} +SHA=${2:-} +METALLICITIES=${3:-"2 1 0.45 0.2 0.1 0.01 0.001 0.0001"} + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +SAFE_BRANCH="${BRANCH//\//_}" +BASELINE_DIR="$SCRIPT_DIR/baselines/${SAFE_BRANCH}" + +echo "============================================================" +echo " POSYDON Binary Validation — Generating Baseline" +echo " Branch: $BRANCH" +echo " SHA: ${SHA:-HEAD}" +echo " Metallicities: $METALLICITIES" +echo " Output dir: $BASELINE_DIR" +echo "============================================================" + +# ── Step 1: Evolve binaries for the baseline branch ────────────────────── +echo "" +echo "Step 1: Evolving binaries on branch '$BRANCH'..." +"$SCRIPT_DIR/evolve_binaries.sh" "$BRANCH" "$SHA" "$METALLICITIES" + +# ── Step 2: Copy results into the baselines directory ──────────────────── +echo "" +echo "Step 2: Copying results to baseline directory..." + +mkdir -p "$BASELINE_DIR" + +CANDIDATE_DIR="$SCRIPT_DIR/outputs/${SAFE_BRANCH}" +COPIED=0 + +for Z in $METALLICITIES; do + SRC="$CANDIDATE_DIR/candidate_${Z}Zsun.h5" + DST="$BASELINE_DIR/baseline_${Z}Zsun.h5" + + if [ -f "$SRC" ]; then + cp "$SRC" "$DST" + echo " Saved: $DST" + COPIED=$((COPIED + 1)) + else + echo " WARNING: Missing output for Z=${Z}: $SRC" >&2 + fi +done + +# ── Step 3: Record baseline metadata ───────────────────────────────────── +CLONE_DIR="$SCRIPT_DIR/workdirs/POSYDON_${SAFE_BRANCH}/POSYDON" +ACTUAL_SHA="" +if [ -d "$CLONE_DIR" ]; then + ACTUAL_SHA=$(cd "$CLONE_DIR" && git rev-parse HEAD 2>/dev/null || echo "unknown") +fi + +INFO_FILE="$BASELINE_DIR/baseline_info.txt" +cat > "$INFO_FILE" << EOF +POSYDON Binary Validation Baseline +=================================== +Branch: $BRANCH +Commit SHA: ${ACTUAL_SHA:-unknown} +Requested SHA: ${SHA:-HEAD} +Generated: $(date -u '+%Y-%m-%d %H:%M:%S UTC') +Metallicities: $METALLICITIES +Files: $COPIED +EOF + +echo "" +echo "============================================================" +echo " Baseline generated: $COPIED file(s)" +echo " Info: $INFO_FILE" +echo " Directory: $BASELINE_DIR" +echo "============================================================" + +if [ $COPIED -eq 0 ]; then + echo "ERROR: No baseline files were created!" >&2 + exit 1 +fi \ No newline at end of file diff --git a/dev-tools/script_data/1Zsun_binaries_suite.py b/dev-tools/script_data/1Zsun_binaries_suite.py deleted file mode 100644 index b994e0b475..0000000000 --- a/dev-tools/script_data/1Zsun_binaries_suite.py +++ /dev/null @@ -1,815 +0,0 @@ -#!/usr/bin/env python3 -""" -Script to evolve a few binaries. -Used for validation of the branch. - -Authors: Max Briel, Elizabeth Teng -""" - -import argparse -import os -import signal -import sys -import warnings -import h5py - -from posydon.binary_evol.binarystar import BinaryStar, SingleStar -from posydon.binary_evol.simulationproperties import SimulationProperties -from posydon.popsyn.io import simprop_kwargs_from_ini -from posydon.utils.common_functions import orbital_separation_from_period - -target_rows = 12 -line_length = 140 -columns_to_show = ['step_names', 'state', 'event', 'S1_state', 'S1_mass', 'S2_state', 'S2_mass', 'orbital_period'] - -def load_inlist(verbose): - - sim_kwargs = simprop_kwargs_from_ini('script_data/1Zsun_binaries_params.ini', verbose=verbose) - metallicity = {'metallicity':1, 'verbose':verbose} - - sim_kwargs['step_HMS_HMS'][1].update(metallicity) - sim_kwargs['step_CO_HeMS'][1].update(metallicity) - sim_kwargs['step_CO_HMS_RLO'][1].update(metallicity) - sim_kwargs['step_CO_HeMS_RLO'][1].update(metallicity) - sim_kwargs['step_detached'][1].update(metallicity) - sim_kwargs['step_disrupted'][1].update(metallicity) - sim_kwargs['step_merged'][1].update(metallicity) - sim_kwargs['step_initially_single'][1].update(metallicity) - - sim_prop = SimulationProperties(**sim_kwargs) - - sim_prop.load_steps(verbose=verbose) - return sim_prop - -def write_binary_to_screen(binary): - """Writes a binary DataFrame prettily to the screen - - Args: - binary: BinaryStar object with evolved data - """ - df = binary.to_df(**{'extra_columns':{'step_names':'str'}}) - - # Filter to only existing columns - available_columns = [col for col in columns_to_show if col in df.columns] - df_filtered = df[available_columns] - - # Reset index to use a counter instead of NaN - df_filtered = df_filtered.reset_index(drop=True) - - print("=" * line_length) - - # Print the DataFrame - df_string = df_filtered.to_string(index=True, float_format='%.3f') - print(df_string) - - # Add empty lines to reach exactly 10 rows of output - current_rows = len(df_filtered) + 1 # add one for header - - if current_rows < target_rows: - # Calculate the width of the output to print empty lines of the same width - lines = df_string.split('\n') - if len(lines) > 1: - # Use the width of the data lines (skip header) - empty_lines_needed = target_rows - current_rows - for i in range(empty_lines_needed): - print("") - - print("-" * line_length) - - -def print_failed_binary(binary,e, max_error_lines=3): - - print("=" * line_length) - print(f"🚨 Binary Evolution Failed!") - print(f"Exception: {type(e).__name__}") - print(f"Message: {e}") - - # Get the binary's current state and limit output - try: - df = binary.to_df(**{'extra_columns':{'step_names':'str'}}) - if len(df) > 0: - # Select only the desired columns - - available_columns = [col for col in columns_to_show if col in df.columns] - df_filtered = df[available_columns] - - # Reset index to use a counter instead of NaN - df_filtered = df_filtered.reset_index(drop=True) - - # Limit to max_error_lines - if len(df_filtered) > max_error_lines: - df_filtered = df_filtered.tail(max_error_lines) - print(f"\nShowing last {max_error_lines} evolution steps before failure:") - else: - print(f"\nEvolution steps before failure ({len(df_filtered)} steps):") - - df_string = df_filtered.to_string(index=True, float_format='%.3f') - print(df_string) - - current_rows = len(df_filtered) + 1 + 5 # add one for header - empty_lines_needed = target_rows - current_rows - for i in range(empty_lines_needed): - print("") - else: - print("\nNo evolution steps recorded before failure.") - except Exception as inner_e: - print(f"\nCould not retrieve binary state: {inner_e}") - - print("-" * line_length) - -def evolve_binary(binary, h5file, binary_id): - """ - Evolves a single binary, prints its evolution, and saves to HDF5. - - Args: - binary: BinaryStar object - h5file: open h5py.File object for writing - binary_id: unique identifier for this binary - """ - - # Capture warnings during evolution - captured_warnings = [] - - def warning_handler(message, category, filename, lineno, file=None, line=None): - captured_warnings.append({ - 'message': str(message), - 'category': category.__name__, - 'filename': filename, - 'lineno': lineno - }) - - # Set up warning capture - old_showwarning = warnings.showwarning - warnings.showwarning = warning_handler - - try: - binary.evolve() - # Display the evolution summary for successful evolution - write_binary_to_screen(binary) - - # Save to HDF5 - df = binary.to_df(**{'extra_columns':{'step_names':'str'}}) - grp = h5file.create_group(f"binary_{binary_id}") - for col in df.columns: - grp.create_dataset(col, data=df[col].values) - - except Exception as e: - print_failed_binary(binary, e) - - err_grp = h5file.require_group(f"binary_{binary_id}/errors") - err_grp.attrs['exception_type'] = type(e).__name__ - err_grp.attrs['exception_message'] = str(e) - - finally: - warnings.showwarning = old_showwarning - - # ensure binary group exists - grp = h5file.require_group(f"binary_{binary_id}") - - # Save warnings to h5 file - if captured_warnings: - warn_grp = grp.create_group("warnings") - for i, warning in enumerate(captured_warnings): - warn_subgrp = warn_grp.create_group(f"warning_{i}") - warn_subgrp.attrs['category'] = warning['category'] - warn_subgrp.attrs['message'] = warning['message'] - warn_subgrp.attrs['filename'] = warning['filename'] - warn_subgrp.attrs['lineno'] = warning['lineno'] - - print(f"āš ļø {len(captured_warnings)} warning(s) raised during evolution:") - for i, warning in enumerate(captured_warnings[:3], 1): # Show max 3 warnings - print(f" {i}. {warning['category']}: {warning['message']}") - if len(captured_warnings) > 3: - print(f" ... and {len(captured_warnings) - 3} more warning(s)") - else: - print(f"No warning(s) raised during evolution\n\n\n\n") - print("=" * line_length) - -def evolve_binaries(verbose,output_path): - """Evolves a few binaries to validate their output - """ - sim_prop = load_inlist(verbose) - - with h5py.File(output_path,'w') as h5file: - binary_id=0 - - ######################################## - # Failing binary in matching - ######################################## - star_1 = SingleStar(**{'mass': 11.948472796094759, 'state': 'H-rich_Core_H_burning','metallicity':1, - 'natal_kick_array': [231.97383621190582, 5.927334890264575, 1.5990566013567014, 6.137994236518587]}) - star_2 = SingleStar(**{'mass': 7.636958434479617, 'state': 'H-rich_Core_H_burning','metallicity':1, - 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) - binary = BinaryStar(star_1, star_2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', - 'orbital_period': 190925.99636740884,'eccentricity': 0.0}, properties = sim_prop) - evolve_binary(binary, h5file, binary_id) - binary_id+=1 - ######################################## - # Failing binary in matching - ######################################## - star_1 = SingleStar(**{'mass': 30.169861921689556, 'state': 'H-rich_Core_H_burning','metallicity':1, - 'natal_kick_array': [77.96834852144123, 0.05021460132555987, 2.3146518208348152, 1.733054979982291]}) - star_2 = SingleStar(**{'mass': 10.972734402996027, 'state': 'H-rich_Core_H_burning','metallicity':1, - 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) - binary = BinaryStar(star_1, star_2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', - 'orbital_period': 20479.71919353725,'eccentricity': 0.0}, properties = sim_prop) - evolve_binary(binary, h5file, binary_id) - binary_id+=1 - ######################################## - # flipped S1 and S2 ? - ######################################## - star_1 = SingleStar(**{'mass': 9.474917413943635, 'state': 'H-rich_Core_H_burning','metallicity':1, - 'natal_kick_array': [133.5713935237759, 4.398754864537542, 2.703102872841114, 1.4633904612711142]}) - star_2 = SingleStar(**{'mass': 9.311073918196263, 'state': 'H-rich_Core_H_burning','metallicity':1, - 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) - binary = BinaryStar(star_1, star_2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', - 'orbital_period': 18.605997832086413,'eccentricity': 0.0}, properties = sim_prop) - - evolve_binary(binary, h5file, binary_id) - binary_id+=1 - ######################################## - # flipped S1 and S2 - ######################################## - star_1 = SingleStar(**{'mass': 10.438541, 'state': 'H-rich_Core_H_burning','metallicity':1, - 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) - star_2 = SingleStar(**{'mass': 1.400713, 'state': 'H-rich_Core_H_burning','metallicity':1, - 'natal_kick_array': [0.0, 4.190728383757787, 1.1521129697118118, 5.015343794234789]}) - binary = BinaryStar(star_1, star_2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', - 'orbital_period': 9.824025,'eccentricity': 0.0}, properties = sim_prop) - evolve_binary(binary, h5file, binary_id) - binary_id+=1 - ######################################## - # flipped S1 and S2 - ######################################## - star_1= SingleStar(**{'mass': 9.845907 , 'state': 'H-rich_Core_H_burning','metallicity':1, - 'natal_kick_array': [0.0, 4.190728383757787, 1.1521129697118118, 5.015343794234789]}) - star_2 = SingleStar(**{'mass': 9.611029, 'state': 'H-rich_Core_H_burning','metallicity':1, - 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) - binary = BinaryStar(star_1, star_2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', - 'orbital_period': 3.820571,'eccentricity': 0.0}, properties = sim_prop) - evolve_binary(binary, h5file, binary_id) - binary_id+=1 - ######################################## - # Normal binary evolution - ######################################## - star_1= SingleStar(**{'mass': 30.845907 , 'state': 'H-rich_Core_H_burning','metallicity':1, - 'natal_kick_array': [0.0, 4.190728383757787, 1.1521129697118118, 5.015343794234789]}) - star_2 = SingleStar(**{'mass': 30.611029, 'state': 'H-rich_Core_H_burning','metallicity':1, - 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) - binary = BinaryStar(star_1, star_2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', - 'orbital_period': 30.820571,'eccentricity': 0.0}, properties = sim_prop) - evolve_binary(binary, h5file, binary_id) - binary_id+=1 - ######################################## - # Normal binary - ######################################## - star_1= SingleStar(**{'mass': 9.213534679594247 , 'state': 'H-rich_Core_H_burning','metallicity':1, - 'natal_kick_array': [327.5906384501521, 1.7707176050073297, 1.573225822966838, 1.6757313876001914]}) - star_2 = SingleStar(**{'mass': 7.209878522799272, 'state': 'H-rich_Core_H_burning','metallicity':1, - 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) - binary = BinaryStar(star_1, star_2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', - 'orbital_period': 63123.74544474666,'eccentricity': 0.0}, properties = sim_prop) - evolve_binary(binary, h5file, binary_id) - binary_id+=1 - ######################################## - # Normal binary - ######################################## - star_1= SingleStar(**{'mass': 9.561158487732602 , 'state': 'H-rich_Core_H_burning','metallicity':1, - 'natal_kick_array': [317.5423844462847, 2.9095984678057603, 1.754121288652108, 2.3693917842468784]}) - star_2 = SingleStar(**{'mass': 9.382732464319286, 'state': 'H-rich_Core_H_burning','metallicity':1, - 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) - binary = BinaryStar(star_1, star_2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', - 'orbital_period': 27.77657038557851,'eccentricity': 0.0}, properties = sim_prop) - evolve_binary(binary, h5file, binary_id) - binary_id+=1 - ######################################## - # Normal binary - ######################################## - star1 = SingleStar(**{'mass': 7.552858,#29829485, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array': [40.91509926587841, 2.6295454150818256, 1.6718337470964977, 6.0408769315244895]}) - star2 = SingleStar(**{'mass': 6.742063, #481560266, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) - binary = BinaryStar(star1, star2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', - 'orbital_period': 17.957531550841225, 'eccentricity': 0.0,}, - properties=sim_prop) - evolve_binary(binary, h5file, binary_id) - binary_id+=1 - ######################################## - # High BH spin options - ######################################## - star_1 = SingleStar(**{'mass': 31.616785, 'state': 'H-rich_Core_H_burning', - 'natal_kick_array': [10, 4.190728383757787, 1.1521129697118118, 5.015343794234789]}) - star_2 = SingleStar(**{'mass': 26.874267, 'state': 'H-rich_Core_H_burning', - 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) - binary = BinaryStar(star_1, star_2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', - 'orbital_period': 501.99252706449792,'eccentricity': 0.0}, properties = sim_prop) - evolve_binary(binary, h5file, binary_id) - binary_id+=1 - ######################################## - # Original a>1 spin error - ######################################## - star_1 = SingleStar(**{'mass': 18.107506844123645, 'state': 'H-rich_Core_H_burning', - 'natal_kick_array': [528.2970725443025, 4.190728383757787, 1.1521129697118118, 5.015343794234789]}) - star_2 = SingleStar(**{'mass': 15.641392951875442, 'state': 'H-rich_Core_H_burning', - 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) - binary = BinaryStar(star_1, star_2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', - 'orbital_period': 151.99252706449792,'eccentricity': 0.0}, properties = sim_prop) - evolve_binary(binary, h5file, binary_id) - binary_id+=1 - ######################################## - # FIXED disrupted crash - ######################################## - star1 = SingleStar(**{'mass': 52.967313, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) - star2 = SingleStar(**{'mass': 36.306444, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) - binary = BinaryStar(star1, star2, - **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':12.877004, 'eccentricity': 0.0}, - properties = sim_prop) - evolve_binary(binary, h5file, binary_id) - binary_id+=1 - ######################################## - # FIXED error with SN type - ######################################## - star1 = SingleStar(**{'mass': 17.782576, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) - star2 = SingleStar(**{'mass':3.273864, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) - binary = BinaryStar(star1, star2, - **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':4513.150157, 'eccentricity': 0.0}, - properties = sim_prop) - evolve_binary(binary, h5file, binary_id) - binary_id+=1 - ######################################## - # FIXED oRLO2 looping - ######################################## - star1 = SingleStar(**{'mass': 170.638207, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array': [4.921294, 4.31745, 1.777768, 3.509656]}) - star2 = SingleStar(**{'mass':37.917852, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) - - binary = BinaryStar(star1, star2, - **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':113.352736, 'eccentricity': 0.0}, - properties = sim_prop) - evolve_binary(binary, h5file, binary_id) - binary_id+=1 - ######################################## - # Redirect to step_CO_HeMS (H-rich non-burning?) - ######################################## - star_1 = SingleStar(**{'mass': 8.333579, 'state': 'H-rich_Core_H_burning',\ - 'natal_kick_array': [17.125568, 4.101834, 0.917541, 3.961291]}) - star_2 = SingleStar(**{'mass' : 8.208376, 'state' : 'H-rich_Core_H_burning', - 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - binary = BinaryStar(star_1, star_2, - **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period': 66.870417, 'eccentricity': 0.0}, - properties = sim_prop) - evolve_binary(binary, h5file, binary_id) - binary_id+=1 - ######################################## - # FIXED oRLO2 looping - ######################################## - star_1 = SingleStar(**{'mass': 16.921378, 'state': 'H-rich_Core_H_burning',\ - 'natal_kick_array': [268.837139, 5.773527, 2.568105, 2.519068]}) - star_2 = SingleStar(**{'mass' : 16.286318, 'state' : 'H-rich_Core_H_burning', - 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - binary = BinaryStar(star_1, star_2, - **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period': 37.958768, 'eccentricity': 0.0}, - properties = sim_prop) - evolve_binary(binary, h5file, binary_id) - binary_id+=1 - ######################################## - # FIXED? step_detached failure - ######################################## - star1 = SingleStar(**{'mass': 19.787769, 'state': 'H-rich_Core_H_burning', - 'natal_kick_array': [24.464803, 0.666314, 1.954698, 5.598975]}) - star2 = SingleStar(**{'mass': 7.638741, 'state': 'H-rich_Core_H_burning', - 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - binary = BinaryStar(star1, star2, - **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':3007.865561, 'eccentricity': 0.0}, - properties = sim_prop) - evolve_binary(binary, h5file, binary_id) - binary_id+=1 - ######################################## - # Disrupted binary - ######################################## - star_1 = SingleStar(**{'mass': 16.921378, 'state': 'H-rich_Core_H_burning',\ - 'natal_kick_array': [268.837139, 5.773527, 2.568105, 2.519068]}) - star_2 = SingleStar(**{'mass' : 16.286318, 'state' : 'H-rich_Core_H_burning', - 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - - binary = BinaryStar(star_1, star_2, - **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':3007.865561, 'eccentricity': 0.0}, - properties = sim_prop) - evolve_binary(binary, h5file, binary_id) - binary_id+=1 - ######################################## - # FIXED Detached binary failure (low mass) - ######################################## - star1 = SingleStar(**{'mass': 9, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - star2 = SingleStar(**{'mass':0.8, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - - binary = BinaryStar(star1, star2, - **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':4513.150157, 'eccentricity': 0.0}, - properties = sim_prop) - evolve_binary(binary, h5file, binary_id) - binary_id+=1 - ######################################## - # FIXED SN_TYPE = None crash - ######################################## - star1 = SingleStar(**{'mass': 17.782576, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - star2 = SingleStar(**{'mass':3.273864, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - - binary = BinaryStar(star1, star2, - **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':4513.150157, 'eccentricity': 0.0}, - properties = sim_prop) - evolve_binary(binary, h5file, binary_id) - binary_id+=1 - ######################################## - # FIXED SN_TYPE errors - ######################################## - star1 = SingleStar(**{'mass': 6.782576, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - star2 = SingleStar(**{'mass':3.273864, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - - binary = BinaryStar(star1, star2, - **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':4513.150157, 'eccentricity': 0.0}, - properties = sim_prop) - evolve_binary(binary, h5file, binary_id) - binary_id+=1 - ######################################## - # FIXED SN_TYPE errors - ######################################## - star1 = SingleStar(**{'mass': 40.638207, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array': [30.921294, 4.31745, 1.777768, 3.509656]}) - star2 = SingleStar(**{'mass':37.917852, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - - binary = BinaryStar(star1, star2, - **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':2113.352736, 'eccentricity': 0.0}, - properties = sim_prop) - evolve_binary(binary, h5file, binary_id) - binary_id+=1 - ######################################## - # FIXED ECSN errors? - ######################################## - star1 = SingleStar(**{'mass': 12.376778, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array': [80, 4.31745, 1.777768, 3.509656]}) - star2 = SingleStar(**{'mass': 9.711216, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - - - binary = BinaryStar(star1, star2, - **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':79.83702, 'eccentricity': 0.0}, - properties = sim_prop) - evolve_binary(binary, h5file, binary_id) - binary_id+=1 - ######################################## - # Interpolator masses?? - ######################################## - star1 = SingleStar(**{'mass': 7.592921, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - star2 = SingleStar(**{'mass':5.038679 , - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - - binary = BinaryStar(star1, star2, - **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':5.537807, 'eccentricity': 0.0}, - properties = sim_prop) - evolve_binary(binary, h5file, binary_id) - binary_id+=1 - ######################################## - # Interpolator masses? - ######################################## - star_1 = SingleStar(**{'mass': 38.741115, - 'state': 'H-rich_Core_H_burning',\ - 'natal_kick_array': [21.113771, 2.060135, 2.224789, 4.089729]}) - star_2 = SingleStar(**{'mass': 27.776178, - 'state': 'H-rich_Core_H_burning',\ - 'natal_kick_array': [282.712103, 0.296252, 1.628433, 5.623812]}) - - binary = BinaryStar(star_1, star_2, - **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period': 93.387072, 'eccentricity': 0.0}, - properties = sim_prop) - evolve_binary(binary, h5file, binary_id) - binary_id+=1 - ######################################## - # FIXED NaN spin - ######################################## - star1 = SingleStar(**{'mass': 70.066924, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array':[0.0, 0.0, 0.0, 0.0], - 'metallicity':1}) - star2 = SingleStar(**{'mass': 34.183110, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array':[0.0, 0.0, 0.0, 0.0], - 'metallicity':1}) - binary = BinaryStar(star1, star2, - **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':5.931492e+03, - 'separation': orbital_separation_from_period(5.931492e+03, star1.mass, star2.mass), - 'eccentricity': 0.0}, - properties = sim_prop) - evolve_binary(binary, h5file, binary_id) - binary_id+=1 - ######################################## - # FIXED NaN spin - ######################################## - star1 = SingleStar(**{'mass': 28.837286, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - star2 = SingleStar(**{'mass': 6.874867, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - - binary = BinaryStar(star1, star2, - **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':35.609894, - 'separation': orbital_separation_from_period(35.609894, star1.mass, star2.mass), - 'eccentricity': 0.0}, - properties = sim_prop) - evolve_binary(binary, h5file, binary_id) - binary_id+=1 - ######################################## - # oRLO2 issue - ######################################## - star1 = SingleStar(**{'mass':29.580210, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - star2 = SingleStar(**{'mass': 28.814626, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - - binary = BinaryStar(star1, star2, - **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':40.437993, 'eccentricity': 0.0}, - properties = sim_prop) - evolve_binary(binary, h5file, binary_id) - binary_id+=1 - ######################################## - # oRLO2 issue - ######################################## - star1 = SingleStar(**{'mass':67.126795, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - star2 = SingleStar(**{'mass': 19.622908, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - - binary = BinaryStar(star1, star2, - **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':1484.768582, 'eccentricity': 0.0}, - properties = sim_prop) - evolve_binary(binary, h5file, binary_id) - binary_id+=1 - ######################################## - # oRLO2 issue - ######################################## - star1 = SingleStar(**{'mass': 58.947503, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - star2 = SingleStar(**{'mass': 56.660506, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - - binary = BinaryStar(star1, star2, - **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':2011.300659, 'eccentricity': 0.0}, - properties = sim_prop) - evolve_binary(binary, h5file, binary_id) - binary_id+=1 - ######################################## - # oRLO2 issue - ######################################## - star1 = SingleStar(**{'mass': 170.638207, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array':[47.979957374424956, 5.317304576107798, 2.7259013166068145, 4.700929589520818]}) - star2 = SingleStar(**{'mass': 37.917852, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - - binary = BinaryStar(star1, star2, - **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':113.352736, 'eccentricity': 0.0}, - properties = sim_prop) - evolve_binary(binary, h5file, binary_id) - binary_id+=1 - ######################################## - # oRLO2 issue - ######################################## - star1 = SingleStar(**{'mass': 109.540207, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - star2 = SingleStar(**{'mass': 84.344530, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - - binary = BinaryStar(star1, star2, - **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':5.651896, 'eccentricity': 0.0}, - properties = sim_prop) - evolve_binary(binary, h5file, binary_id) - binary_id+=1 - ######################################## - # redirect - ######################################## - star1 = SingleStar(**{'mass': 13.889634, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - star2 = SingleStar(**{'mass':0.490231, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - - binary = BinaryStar(star1, star2, - **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':14513.150157, 'eccentricity': 0.0}, - properties = sim_prop) - evolve_binary(binary, h5file, binary_id) - binary_id+=1 - ######################################## - # redirect - ######################################## - star1 = SingleStar(**{'mass': 9, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - star2 = SingleStar(**{'mass':0.8, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - - binary = BinaryStar(star1, star2, - **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':4513.150157, 'eccentricity': 0.0}, - properties = sim_prop) - evolve_binary(binary, h5file, binary_id) - binary_id+=1 - ######################################## - # Max time - ######################################## - star_1 = SingleStar(**{'mass': 103.07996766780799, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array': [0.0, 0.2965418610971261, 2.0789170290719117, 3.207488023705968]}) - star_2 = SingleStar(**{'mass': 83.66522615073987, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) - binary = BinaryStar(star_1, star_2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', - 'orbital_period': 1449.1101985875678,'eccentricity': 0.0}, properties = sim_prop) - evolve_binary(binary, h5file, binary_id) - binary_id+=1 - ######################################## - # Max time - ######################################## - star_1 = SingleStar(**{'mass': 8.860934140643465, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array': [11.818027275431337, 2.812412688633058, 0.4998731824233789, 2.9272630485628643]}) - star_2 = SingleStar(**{'mass': 8.584716012668551, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) - binary = BinaryStar(star_1, star_2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', - 'orbital_period': 20.82030114750744,'eccentricity': 0.0}, properties = sim_prop) - evolve_binary(binary, h5file, binary_id) - binary_id+=1 - ######################################## - # PR421 - ######################################## - star1 = SingleStar(**{'mass': 24.035366, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - star2 = SingleStar(**{'mass': 23.187355, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - - binary = BinaryStar(star1, star2, - **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':18.865029, 'eccentricity': 0.0}, - properties = sim_prop) - evolve_binary(binary, h5file, binary_id) - binary_id+=1 - ######################################## - # CE class - ######################################## - star1 = SingleStar(**{'mass':33.964274, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - star2 = SingleStar(**{'mass': 28.98149, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - - binary = BinaryStar(star1, star2, - **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':82.370989, 'eccentricity': 0.0}, - properties = sim_prop) - evolve_binary(binary, h5file, binary_id) - binary_id+=1 - ######################################## - # PR574 - stepCE fix - ######################################## - star1 = SingleStar(**{'mass':29.580210, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - star2 = SingleStar(**{'mass': 28.814626*0.4, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - - binary = BinaryStar(star1, star2, - **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':300.437993, 'eccentricity': 0.0}, - properties = sim_prop) - evolve_binary(binary, h5file, binary_id) - binary_id+=1 - ######################################## - # e_ZAMS error - ######################################## - star1 = SingleStar(**{'mass': 8.161885721822461, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) - star2 = SingleStar(**{'mass': 3.5907829421526154, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) - - binary = BinaryStar(star1, star2, - **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period': 36.873457164644144, 'eccentricity': 0.0}, - properties = sim_prop) - evolve_binary(binary, h5file, binary_id) - binary_id+=1 - ######################################## - # e_ZAMS error - ######################################## - star1 = SingleStar(**{'mass': 35.24755025317775, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array': [19.755993125895806, 0.37149222852233904, 1.6588846085306563, - 1.434617029858906]}) - star2 = SingleStar(**{'mass': 30.000450298072902, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) - - binary = BinaryStar(star1, star2, - **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period': 24060.02101364665, 'eccentricity': 0.8085077857996965}, - properties = sim_prop) - evolve_binary(binary, h5file, binary_id) - binary_id+=1 - ######################################## - # e_ZAMS error - ######################################## - star1 = SingleStar(**{'mass': 11.862930493162692, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) - star2 = SingleStar(**{'mass': 1.4739109294156703, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) - - binary = BinaryStar(star1, star2, - **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period': 4111.083887312003, 'eccentricity':0.0}, - properties = sim_prop) - evolve_binary(binary, h5file, binary_id) - binary_id+=1 - ######################################## - # e_ZAMS error - ######################################## - star1 = SingleStar(**{'mass': 8.527361341212108, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) - star2 = SingleStar(**{'mass': 0.7061748406821822, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) - - binary = BinaryStar(star1, star2, - **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period': 2521.1927287891444, 'eccentricity':0.0}, - properties = sim_prop) - evolve_binary(binary, h5file, binary_id) - binary_id+=1 - ######################################## - # e_ZAMS error - ######################################## - star1 = SingleStar(**{'mass': 13.661942533447398 ,#29829485, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) - star2 = SingleStar(**{'mass': 4.466151109802313 , #481560266, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) - - binary = BinaryStar(star1, star2, - **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':3110.1346707516914, 'eccentricity':0.0}, - properties = sim_prop) - evolve_binary(binary, h5file, binary_id) - binary_id+=1 - -if __name__ == "__main__": - parser = argparse.ArgumentParser(description='Evolve binaries for validation.') - parser.add_argument('--verbose', '-v', action='store_true', default=False, - help='Enable verbose output (default: False)') - parser.add_argument("--output", type=str, required=True, - help="Path to save HDF5 output") - args = parser.parse_args() - - evolve_binaries(verbose=args.verbose, output_path=args.output) diff --git a/dev-tools/script_data/1Zsun_binaries_params.ini b/dev-tools/script_data/binaries_params.ini similarity index 99% rename from dev-tools/script_data/1Zsun_binaries_params.ini rename to dev-tools/script_data/binaries_params.ini index f5400f3117..c001928c2b 100644 --- a/dev-tools/script_data/1Zsun_binaries_params.ini +++ b/dev-tools/script_data/binaries_params.ini @@ -1,4 +1,6 @@ # POSYDON default BinaryPopulation inifile, use ConfigParser syntax +# This ini is used ONLY for SimulationProperties configuration. +# Metallicity is overridden at runtime by binaries_suite.py. [environment_variables] PATH_TO_POSYDON = '' diff --git a/dev-tools/script_data/binaries_suite.py b/dev-tools/script_data/binaries_suite.py new file mode 100644 index 0000000000..08e0365dd9 --- /dev/null +++ b/dev-tools/script_data/binaries_suite.py @@ -0,0 +1,694 @@ +#!/usr/bin/env python3 +""" +Script to evolve a set of test binaries at a given metallicity. +Used for validation of POSYDON branches. + +Usage: + python binaries_suite.py --output results.h5 --metallicity 1 + python binaries_suite.py --output results.h5 --metallicity 0.45 --verbose + +Authors: Max Briel, Elizabeth Teng +""" + +import argparse +import os +import sys +import warnings +import pandas as pd + +from posydon.binary_evol.binarystar import BinaryStar, SingleStar +from posydon.binary_evol.simulationproperties import SimulationProperties +from posydon.popsyn.io import simprop_kwargs_from_ini +from posydon.utils.common_functions import orbital_separation_from_period + +AVAILABLE_METALLICITIES = [2., 1., 0.45, 0.2, 0.1, 0.01, 0.001, 0.0001] + +# Display settings +TARGET_ROWS = 12 +LINE_LENGTH = 80 +COLUMNS_TO_SHOW = ['step_names', 'state', 'event', + 'S1_state', 'S1_mass', + 'S2_state', 'S2_mass', 'orbital_period'] + +def load_inlist(metallicity, verbose, ini_path=None): + """Load simulation properties from ini file and configure for given metallicity. + + Args: + metallicity: float, metallicity in solar units + verbose: bool + ini_path: str, path to ini file (auto-detected if None) + + Returns: + SimulationProperties object with loaded steps + """ + if ini_path is None: + script_dir = os.path.dirname(os.path.abspath(__file__)) + ini_path = os.path.join(script_dir, 'binaries_params.ini') + + if not os.path.exists(ini_path): + raise FileNotFoundError(f"INI file not found: {ini_path}") + + sim_kwargs = simprop_kwargs_from_ini(ini_path, verbose=verbose) + + metallicity_kwargs = {'metallicity': metallicity, 'verbose': verbose} + + metallicity_steps = ['step_HMS_HMS', 'step_CO_HeMS', 'step_CO_HMS_RLO', + 'step_CO_HeMS_RLO', 'step_detached', 'step_disrupted', + 'step_merged', 'step_initially_single'] + for step_name in metallicity_steps: + if step_name in sim_kwargs: + sim_kwargs[step_name][1].update(metallicity_kwargs) + + sim_prop = SimulationProperties(**sim_kwargs) + sim_prop.load_steps(verbose=verbose) + return sim_prop + +def write_binary_to_screen(binary): + """Writes a binary DataFrame to screen.""" + df = binary.to_df(**{'extra_columns':{'step_names':'str'}}) + + # Filter to only existing columns + available_columns = [col for col in COLUMNS_TO_SHOW if col in df.columns] + df_filtered = df[available_columns].reset_index(drop=True) + + print("=" * LINE_LENGTH) + + # Print the DataFrame + df_string = df_filtered.to_string(index=True, float_format='%.3f') + print(df_string) + + # Add empty lines to reach exactly 10 rows of output + current_rows = len(df_filtered) + 1 # add one for header + + if current_rows < TARGET_ROWS: + for _ in range(TARGET_ROWS - current_rows): + print("") + + print("-" * LINE_LENGTH) + + +def print_failed_binary(binary,e, max_error_lines=3): + """Print information about a binary that failed to evolve.""" + + print("=" * LINE_LENGTH) + print(f"🚨 Binary Evolution Failed!") + print(f"Exception: {type(e).__name__}") + print(f"Message: {e}") + + # Get the binary's current state and limit output + try: + df = binary.to_df(**{'extra_columns':{'step_names':'str'}}) + if len(df) > 0: + # Select only the desired columns + + available_columns = [col for col in COLUMNS_TO_SHOW if col in df.columns] + df_filtered = df[available_columns].reset_index(drop=True) + + # Limit to max_error_lines + if len(df_filtered) > max_error_lines: + df_filtered = df_filtered.tail(max_error_lines) + print(f"\nShowing last {max_error_lines} evolution steps before failure:") + else: + print(f"\nEvolution steps before failure ({len(df_filtered)} steps):") + + df_string = df_filtered.to_string(index=True, float_format='%.3f') + print(df_string) + + current_rows = len(df_filtered) + 1 + 5 # add one for header + empty_lines_needed = TARGET_ROWS - current_rows + for _ in range(max(0, empty_lines_needed)): + print("") + else: + print("\nNo evolution steps recorded before failure.") + except Exception as inner_e: + print(f"\nCould not retrieve binary state: {inner_e}") + + print("-" * LINE_LENGTH) + +def evolve_binary(binary, h5file, binary_id): + """ + Evolves a single binary, prints its evolution, and saves to HDF5. + + Args: + binary: BinaryStar object + h5file: open pd.HDFStore object for writing + binary_id: unique identifier for this binary + """ + + # Capture warnings during evolution + captured_warnings = [] + + def warning_handler(message, category, filename, lineno, file=None, line=None): + captured_warnings.append({ + "binary_id": int(binary_id), + "category": category.__name__, + "message": str(message), + "filename": filename, + "lineno": lineno + }) + + # Set up warning capture + old_showwarning = warnings.showwarning + warnings.showwarning = warning_handler + + print(f"Binary {binary_id}") + evolution_df = None + + try: + binary.evolve() + write_binary_to_screen(binary) + evolution_df = binary.to_df(extra_columns={'step_names':'str'}) + + except Exception as e: + print_failed_binary(binary, e) + + # If evolution fails, create a minimal df with error info + evolution_df = pd.DataFrame([{ + "binary_id": int(binary_id), + "exception_type": type(e).__name__, + "exception_message": str(e) + }]) + + finally: + warnings.showwarning = old_showwarning + + # Ensure we always have a dataframe + if evolution_df is not None: + # Decode bytes columns if needed + for col in evolution_df.select_dtypes([object]): + if evolution_df[col].apply(lambda x: isinstance(x, bytes)).any(): + evolution_df[col] = evolution_df[col].apply( + lambda x: x.decode('utf-8') if isinstance(x, bytes) else x + ) + + # Always ensure binary_id exists + if "binary_id" not in evolution_df.columns: + evolution_df["binary_id"] = int(binary_id) + + # Defragment + evolution_df = evolution_df.copy() + + # Determine min_itemsize from the dataframe we're actually saving + string_cols = evolution_df.select_dtypes([object]).columns + min_itemsize = {col: 100 for col in string_cols} + h5file.append("evolution", evolution_df, format="table", + data_columns=True, min_itemsize=min_itemsize) + + # Save warnings + if captured_warnings: + warn_df = pd.DataFrame(captured_warnings) + # Ensure consistent string column sizes for warnings table + warn_string_cols = warn_df.select_dtypes([object]).columns + warn_min_itemsize = {col: 200 for col in warn_string_cols} + h5file.append("warnings", warn_df, format="table", + min_itemsize=warn_min_itemsize) + print(f"āš ļø {len(captured_warnings)} warning(s) raised during evolution:") + for i, w in enumerate(captured_warnings[:3], 1): + print(f" {i}. {w['category']}: {w['message'][:80]}") + if len(captured_warnings) > 3: + print(f" ... and {len(captured_warnings) - 3} more warning(s)") + else: + print(f" No warning(s) raised during evolution") + + print(f"āœ… Finished binary {binary_id}") + print("=" * LINE_LENGTH) + + + +def get_test_binaries(metallicity, sim_prop): + """Return the list of test binaries as (star1_kwargs, star2_kwargs, binary_kwargs, description) tuples. + + All binaries use the specified metallicity. + """ + Z = metallicity + + binaries = [ + # 0: Failing binary in matching + ({'mass': 11.948472796094759, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [231.97383621190582, 5.927334890264575, 1.5990566013567014, 6.137994236518587]}, + {'mass': 7.636958434479617, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}, + {'time': 0.0, 'state': 'detached', 'event': 'ZAMS', + 'orbital_period': 190925.99636740884, 'eccentricity': 0.0}, + "Failing binary in matching"), + + # 1: Failing binary in matching + ({'mass': 30.169861921689556, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [77.96834852144123, 0.05021460132555987, 2.3146518208348152, 1.733054979982291]}, + {'mass': 10.972734402996027, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}, + {'time': 0.0, 'state': 'detached', 'event': 'ZAMS', + 'orbital_period': 20479.71919353725, 'eccentricity': 0.0}, + "Failing binary in matching"), + + # 2: Flipped S1 and S2 (near-equal mass) + ({'mass': 9.474917413943635, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [133.5713935237759, 4.398754864537542, 2.703102872841114, 1.4633904612711142]}, + {'mass': 9.311073918196263, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}, + {'time': 0.0, 'state': 'detached', 'event': 'ZAMS', + 'orbital_period': 18.605997832086413, 'eccentricity': 0.0}, + "Flipped S1 and S2 (near-equal mass)"), + + # 3: Flipped S1 and S2 (high mass ratio) + ({'mass': 10.438541, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}, + {'mass': 1.400713, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [0.0, 4.190728383757787, 1.1521129697118118, 5.015343794234789]}, + {'time': 0.0, 'state': 'detached', 'event': 'ZAMS', + 'orbital_period': 9.824025, 'eccentricity': 0.0}, + "Flipped S1 and S2 (high mass ratio)"), + + # 4: Flipped S1 and S2 + ({'mass': 9.845907, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [0.0, 4.190728383757787, 1.1521129697118118, 5.015343794234789]}, + {'mass': 9.611029, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}, + {'time': 0.0, 'state': 'detached', 'event': 'ZAMS', + 'orbital_period': 3.820571, 'eccentricity': 0.0}, + "Flipped S1 and S2"), + + # 5: Normal binary evolution (high mass) + ({'mass': 30.845907, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [0.0, 4.190728383757787, 1.1521129697118118, 5.015343794234789]}, + {'mass': 30.611029, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}, + {'time': 0.0, 'state': 'detached', 'event': 'ZAMS', + 'orbital_period': 30.820571, 'eccentricity': 0.0}, + "Normal binary evolution (high mass)"), + + # 6: Normal binary (wide orbit) + ({'mass': 9.213534679594247, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [327.5906384501521, 1.7707176050073297, 1.573225822966838, 1.6757313876001914]}, + {'mass': 7.209878522799272, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}, + {'time': 0.0, 'state': 'detached', 'event': 'ZAMS', + 'orbital_period': 63123.74544474666, 'eccentricity': 0.0}, + "Normal binary (wide orbit)"), + + # 7: Normal binary (near-equal mass, close) + ({'mass': 9.561158487732602, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [317.5423844462847, 2.9095984678057603, 1.754121288652108, 2.3693917842468784]}, + {'mass': 9.382732464319286, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}, + {'time': 0.0, 'state': 'detached', 'event': 'ZAMS', + 'orbital_period': 27.77657038557851, 'eccentricity': 0.0}, + "Normal binary (near-equal mass, close)"), + + # 8: Normal binary + ({'mass': 7.552858, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [40.91509926587841, 2.6295454150818256, 1.6718337470964977, 6.0408769315244895]}, + {'mass': 6.742063, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}, + {'time': 0.0, 'state': 'detached', 'event': 'ZAMS', + 'orbital_period': 17.957531550841225, 'eccentricity': 0.0}, + "Normal binary"), + + # 9: High BH spin options + ({'mass': 31.616785, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [10, 4.190728383757787, 1.1521129697118118, 5.015343794234789]}, + {'mass': 26.874267, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}, + {'time': 0.0, 'state': 'detached', 'event': 'ZAMS', + 'orbital_period': 501.99252706449792, 'eccentricity': 0.0}, + "High BH spin options"), + + # 10: Original a>1 spin error + ({'mass': 18.107506844123645, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [528.2970725443025, 4.190728383757787, 1.1521129697118118, 5.015343794234789]}, + {'mass': 15.641392951875442, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}, + {'time': 0.0, 'state': 'detached', 'event': 'ZAMS', + 'orbital_period': 151.99252706449792, 'eccentricity': 0.0}, + "Original a>1 spin error"), + + # 11: FIXED disrupted crash + ({'mass': 52.967313, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}, + {'mass': 36.306444, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}, + {'time': 0.0, 'state': 'detached', 'event': 'ZAMS', + 'orbital_period': 12.877004, 'eccentricity': 0.0}, + "FIXED disrupted crash"), + + # 12: FIXED error with SN type + ({'mass': 17.782576, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}, + {'mass': 3.273864, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}, + {'time': 0.0, 'state': 'detached', 'event': 'ZAMS', + 'orbital_period': 4513.150157, 'eccentricity': 0.0}, + "FIXED error with SN type"), + + # 13: FIXED oRLO2 looping + ({'mass': 170.638207, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [4.921294, 4.31745, 1.777768, 3.509656]}, + {'mass': 37.917852, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}, + {'time': 0.0, 'state': 'detached', 'event': 'ZAMS', + 'orbital_period': 113.352736, 'eccentricity': 0.0}, + "FIXED oRLO2 looping"), + + # 14: Redirect to step_CO_HeMS + ({'mass': 8.333579, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [17.125568, 4.101834, 0.917541, 3.961291]}, + {'mass': 8.208376, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}, + {'time': 0.0, 'state': 'detached', 'event': 'ZAMS', + 'orbital_period': 66.870417, 'eccentricity': 0.0}, + "Redirect to step_CO_HeMS"), + + # 15: FIXED oRLO2 looping + ({'mass': 16.921378, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [268.837139, 5.773527, 2.568105, 2.519068]}, + {'mass': 16.286318, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}, + {'time': 0.0, 'state': 'detached', 'event': 'ZAMS', + 'orbital_period': 37.958768, 'eccentricity': 0.0}, + "FIXED oRLO2 looping"), + + # 16: FIXED step_detached failure + ({'mass': 19.787769, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [24.464803, 0.666314, 1.954698, 5.598975]}, + {'mass': 7.638741, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}, + {'time': 0.0, 'state': 'detached', 'event': 'ZAMS', + 'orbital_period': 3007.865561, 'eccentricity': 0.0}, + "FIXED step_detached failure"), + + # 17: Disrupted binary + ({'mass': 16.921378, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [268.837139, 5.773527, 2.568105, 2.519068]}, + {'mass': 16.286318, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}, + {'time': 0.0, 'state': 'detached', 'event': 'ZAMS', + 'orbital_period': 3007.865561, 'eccentricity': 0.0}, + "Disrupted binary"), + + # 18: FIXED Detached binary failure (low mass) + ({'mass': 9, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}, + {'mass': 0.8, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}, + {'time': 0.0, 'state': 'detached', 'event': 'ZAMS', + 'orbital_period': 4513.150157, 'eccentricity': 0.0}, + "FIXED Detached binary failure (low mass)"), + + # 19: FIXED SN_TYPE = None crash + ({'mass': 17.782576, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}, + {'mass': 3.273864, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}, + {'time': 0.0, 'state': 'detached', 'event': 'ZAMS', + 'orbital_period': 4513.150157, 'eccentricity': 0.0}, + "FIXED SN_TYPE = None crash"), + + # 20: FIXED SN_TYPE errors (low mass primary) + ({'mass': 6.782576, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}, + {'mass': 3.273864, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}, + {'time': 0.0, 'state': 'detached', 'event': 'ZAMS', + 'orbital_period': 4513.150157, 'eccentricity': 0.0}, + "FIXED SN_TYPE errors (low mass primary)"), + + # 21: FIXED SN_TYPE errors (high mass) + ({'mass': 40.638207, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [30.921294, 4.31745, 1.777768, 3.509656]}, + {'mass': 37.917852, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}, + {'time': 0.0, 'state': 'detached', 'event': 'ZAMS', + 'orbital_period': 2113.352736, 'eccentricity': 0.0}, + "FIXED SN_TYPE errors (high mass)"), + + # 22: FIXED ECSN errors + ({'mass': 12.376778, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [80, 4.31745, 1.777768, 3.509656]}, + {'mass': 9.711216, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}, + {'time': 0.0, 'state': 'detached', 'event': 'ZAMS', + 'orbital_period': 79.83702, 'eccentricity': 0.0}, + "FIXED ECSN errors"), + + # 23: Interpolator masses (close) + ({'mass': 7.592921, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}, + {'mass': 5.038679, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}, + {'time': 0.0, 'state': 'detached', 'event': 'ZAMS', + 'orbital_period': 5.537807, 'eccentricity': 0.0}, + "Interpolator masses (close)"), + + # 24: Interpolator masses (both kicked) + ({'mass': 38.741115, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [21.113771, 2.060135, 2.224789, 4.089729]}, + {'mass': 27.776178, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [282.712103, 0.296252, 1.628433, 5.623812]}, + {'time': 0.0, 'state': 'detached', 'event': 'ZAMS', + 'orbital_period': 93.387072, 'eccentricity': 0.0}, + "Interpolator masses (both kicked)"), + + # 25: FIXED NaN spin (very high mass, wide) + ({'mass': 70.066924, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}, + {'mass': 34.183110, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}, + {'time': 0.0, 'state': 'detached', 'event': 'ZAMS', + 'orbital_period': 5.931492e+03, 'eccentricity': 0.0}, + "FIXED NaN spin (very high mass, wide)"), + + # 26: FIXED NaN spin + ({'mass': 28.837286, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}, + {'mass': 6.874867, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}, + {'time': 0.0, 'state': 'detached', 'event': 'ZAMS', + 'orbital_period': 35.609894, 'eccentricity': 0.0}, + "FIXED NaN spin"), + + # 27: oRLO2 issue (near-equal mass) + ({'mass': 29.580210, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}, + {'mass': 28.814626, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}, + {'time': 0.0, 'state': 'detached', 'event': 'ZAMS', + 'orbital_period': 40.437993, 'eccentricity': 0.0}, + "oRLO2 issue (near-equal mass)"), + + # 28: oRLO2 issue (high mass ratio) + ({'mass': 67.126795, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}, + {'mass': 19.622908, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}, + {'time': 0.0, 'state': 'detached', 'event': 'ZAMS', + 'orbital_period': 1484.768582, 'eccentricity': 0.0}, + "oRLO2 issue (high mass ratio)"), + + # 29: oRLO2 issue (very high mass, near-equal) + ({'mass': 58.947503, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}, + {'mass': 56.660506, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}, + {'time': 0.0, 'state': 'detached', 'event': 'ZAMS', + 'orbital_period': 2011.300659, 'eccentricity': 0.0}, + "oRLO2 issue (very high mass, near-equal)"), + + # 30: oRLO2 issue (extreme mass, kicked) + ({'mass': 170.638207, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [47.979957374424956, 5.317304576107798, 2.7259013166068145, 4.700929589520818]}, + {'mass': 37.917852, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}, + {'time': 0.0, 'state': 'detached', 'event': 'ZAMS', + 'orbital_period': 113.352736, 'eccentricity': 0.0}, + "oRLO2 issue (extreme mass, kicked)"), + + # 31: oRLO2 issue (very high mass, close) + ({'mass': 109.540207, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}, + {'mass': 84.344530, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}, + {'time': 0.0, 'state': 'detached', 'event': 'ZAMS', + 'orbital_period': 5.651896, 'eccentricity': 0.0}, + "oRLO2 issue (very high mass, close)"), + + # 32: Redirect (extreme mass ratio) + ({'mass': 13.889634, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}, + {'mass': 0.490231, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}, + {'time': 0.0, 'state': 'detached', 'event': 'ZAMS', + 'orbital_period': 14513.150157, 'eccentricity': 0.0}, + "Redirect (extreme mass ratio)"), + + # 33: Redirect (low mass secondary) + ({'mass': 9, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}, + {'mass': 0.8, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}, + {'time': 0.0, 'state': 'detached', 'event': 'ZAMS', + 'orbital_period': 4513.150157, 'eccentricity': 0.0}, + "Redirect (low mass secondary)"), + + # 34: Max time (very high mass, wide) + ({'mass': 103.07996766780799, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [0.0, 0.2965418610971261, 2.0789170290719117, 3.207488023705968]}, + {'mass': 83.66522615073987, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}, + {'time': 0.0, 'state': 'detached', 'event': 'ZAMS', + 'orbital_period': 1449.1101985875678, 'eccentricity': 0.0}, + "Max time (very high mass, wide)"), + + # 35: Max time + ({'mass': 8.860934140643465, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [11.818027275431337, 2.812412688633058, 0.4998731824233789, 2.9272630485628643]}, + {'mass': 8.584716012668551, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}, + {'time': 0.0, 'state': 'detached', 'event': 'ZAMS', + 'orbital_period': 20.82030114750744, 'eccentricity': 0.0}, + "Max time"), + + # 36: PR421 + ({'mass': 24.035366, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}, + {'mass': 23.187355, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}, + {'time': 0.0, 'state': 'detached', 'event': 'ZAMS', + 'orbital_period': 18.865029, 'eccentricity': 0.0}, + "PR421"), + + # 37: CE class + ({'mass': 33.964274, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}, + {'mass': 28.98149, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}, + {'time': 0.0, 'state': 'detached', 'event': 'ZAMS', + 'orbital_period': 82.370989, 'eccentricity': 0.0}, + "CE class"), + + # 38: PR574 - stepCE fix + ({'mass': 29.580210, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}, + {'mass': 28.814626 * 0.4, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}, + {'time': 0.0, 'state': 'detached', 'event': 'ZAMS', + 'orbital_period': 300.437993, 'eccentricity': 0.0}, + "PR574 - stepCE fix"), + + # 39: e_ZAMS error + ({'mass': 8.161885721822461, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}, + {'mass': 3.5907829421526154, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}, + {'time': 0.0, 'state': 'detached', 'event': 'ZAMS', + 'orbital_period': 36.873457164644144, 'eccentricity': 0.0}, + "e_ZAMS error"), + + # 40: e_ZAMS error (eccentric) + ({'mass': 35.24755025317775, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [19.755993125895806, 0.37149222852233904, 1.6588846085306563, 1.434617029858906]}, + {'mass': 30.000450298072902, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}, + {'time': 0.0, 'state': 'detached', 'event': 'ZAMS', + 'orbital_period': 24060.02101364665, 'eccentricity': 0.8085077857996965}, + "e_ZAMS error (eccentric)"), + + # 41: e_ZAMS error (high mass ratio) + ({'mass': 11.862930493162692, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}, + {'mass': 1.4739109294156703, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}, + {'time': 0.0, 'state': 'detached', 'event': 'ZAMS', + 'orbital_period': 4111.083887312003, 'eccentricity': 0.0}, + "e_ZAMS error (high mass ratio)"), + + # 42: e_ZAMS error (extreme mass ratio) + ({'mass': 8.527361341212108, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}, + {'mass': 0.7061748406821822, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}, + {'time': 0.0, 'state': 'detached', 'event': 'ZAMS', + 'orbital_period': 2521.1927287891444, 'eccentricity': 0.0}, + "e_ZAMS error (extreme mass ratio)"), + + # 43: e_ZAMS error + ({'mass': 13.661942533447398, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}, + {'mass': 4.466151109802313, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}, + {'time': 0.0, 'state': 'detached', 'event': 'ZAMS', + 'orbital_period': 3110.1346707516914, 'eccentricity': 0.0}, + "e_ZAMS error"), + ] + + return binaries + + +def evolve_binaries(metallicity, verbose, output_path, ini_path=None): + """Evolves the test binary suite at the given metallicity and saves results. + + Args: + metallicity: float, metallicity in solar units + verbose: bool + output_path: str, path to save HDF5 output + ini_path: str, path to ini file (auto-detected if None) + """ + print(f"{'=' * LINE_LENGTH}") + print(f" Evolving test binaries at Z = {metallicity} Zsun") + print(f" Output: {output_path}") + print(f"{'=' * LINE_LENGTH}\n") + + sim_prop = load_inlist(metallicity, verbose, ini_path) + test_binaries = get_test_binaries(metallicity, sim_prop) + + with pd.HDFStore(output_path, mode="w") as h5file: + # Save metadata + meta_df = pd.DataFrame([{ + 'metallicity': metallicity, + 'n_binaries': len(test_binaries), + }]) + h5file.put("metadata", meta_df, format="table") + + for binary_id, (s1_kw, s2_kw, bin_kw, description) in enumerate(test_binaries): + print(f"\n[{binary_id}/{len(test_binaries)-1}] {description}") + + star_1 = SingleStar(**s1_kw) + star_2 = SingleStar(**s2_kw) + + # Add separation from period if not explicitly provided + if 'separation' not in bin_kw and 'orbital_period' in bin_kw: + bin_kw['separation'] = orbital_separation_from_period( + bin_kw['orbital_period'], star_1.mass, star_2.mass + ) + + binary = BinaryStar(star_1, star_2, **bin_kw, properties=sim_prop) + evolve_binary(binary, h5file, binary_id) + + print(f"\n{'=' * LINE_LENGTH}") + print(f" All {len(test_binaries)} binaries complete. Results saved to {output_path}") + print(f"{'=' * LINE_LENGTH}") + +if __name__ == "__main__": + parser = argparse.ArgumentParser( + description='Evolve test binaries for POSYDON branch validation.', + formatter_class=argparse.ArgumentDefaultsHelpFormatter + ) + parser.add_argument('--verbose', '-v', action='store_true', default=False, + help='Enable verbose output') + parser.add_argument('--output', type=str, required=True, + help='Path to save HDF5 output') + parser.add_argument('--metallicity', '-Z', type=float, default=1.0, + help=f'Metallicity in solar units. Available: {AVAILABLE_METALLICITIES}') + parser.add_argument('--ini', type=str, default=None, + help='Path to params ini file (auto-detected if not given)') + args = parser.parse_args() + + if args.metallicity not in AVAILABLE_METALLICITIES: + print(f"WARNING: Metallicity {args.metallicity} not in standard set {AVAILABLE_METALLICITIES}.") + print(f"Proceeding anyway, but POSYDON grids may not exist for this value.") + + evolve_binaries( + metallicity=args.metallicity, + verbose=args.verbose, + output_path=args.output, + ini_path=args.ini, + ) \ No newline at end of file diff --git a/dev-tools/validate_binaries.sh b/dev-tools/validate_binaries.sh index 04a041af06..2ae354b4fa 100644 --- a/dev-tools/validate_binaries.sh +++ b/dev-tools/validate_binaries.sh @@ -1,26 +1,144 @@ -#!/bin/bash - -# A script for validating the outputs of 100 binaries, -# which can be compared to a baseline to monitor changes to the code. - -# script usage: ./validate_binaries.sh --branch candidate_branch - -BRANCH=$1 -SUFFIX=$2 - -# run candidate binaries and save to file -./evolve_binaries.sh "$BRANCH" - -# compare quantitative, qualitative, warnings/errors, structured output -# create outputs/comparison_branchname.txt -SAFE_BRANCH="${BRANCH//\//_}" -CANDIDATE_FILE="outputs/candidate_${SAFE_BRANCH}.h5" -COMPARISON_FILE="outputs/comparison_${SAFE_BRANCH}${SUFFIX:+_$SUFFIX}.txt" -python compare_runs.py baseline.h5 "$CANDIDATE_FILE" > "$COMPARISON_FILE" - -if [ $? -ne 0 ]; then - echo "Error: compare_runs.py failed. Check $COMPARISON_FILE" - exit 1 -fi - -echo "Binary evolution comparison saved to $COMPARISON_FILE" +#!/bin/bash +# ============================================================================= +# validate_binaries.sh — Run the full validation pipeline: +# 1. Evolve test binaries on a candidate branch +# 2. Compare against baseline files +# +# Usage: +# ./validate_binaries.sh [baseline_branch] [metallicities] +# +# Examples: +# ./validate_binaries.sh feature/new-SN # compare vs main baseline +# ./validate_binaries.sh feature/new-SN v2.1.0 # compare vs v2.1.0 baseline +# ./validate_binaries.sh feature/new-SN main "1 0.45" # subset of metallicities +# +# Prerequisites: +# Run generate_baseline.sh first to create baseline files. +# +# Output: +# outputs//comparison_Zsun.txt — per-metallicity comparison reports +# outputs//comparison_summary.txt — overall summary +# ============================================================================= + +set -euo pipefail + +CANDIDATE_BRANCH=${1:?Usage: ./validate_binaries.sh [baseline_branch] [metallicities]} +BASELINE_BRANCH=${2:-main} +METALLICITIES=${3:-"2 1 0.45 0.2 0.1 0.01 0.001 0.0001"} + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +SAFE_CANDIDATE="${CANDIDATE_BRANCH//\//_}" +SAFE_BASELINE="${BASELINE_BRANCH//\//_}" + +BASELINE_DIR="$SCRIPT_DIR/baselines/${SAFE_BASELINE}" +OUTPUT_DIR="$SCRIPT_DIR/outputs/${SAFE_CANDIDATE}" +SUMMARY_FILE="$OUTPUT_DIR/comparison_summary.txt" + +echo "============================================================" +echo " POSYDON Binary Validation" +echo " Candidate: $CANDIDATE_BRANCH" +echo " Baseline: $BASELINE_BRANCH" +echo " Metallicities: $METALLICITIES" +echo "============================================================" + +# ── Verify baseline exists ──────────────────────────────────────────────── +if [ ! -d "$BASELINE_DIR" ]; then + echo "ERROR: Baseline directory not found: $BASELINE_DIR" >&2 + echo "Run generate_baseline.sh first:" >&2 + echo " ./generate_baseline.sh $BASELINE_BRANCH" >&2 + exit 1 +fi + +# Check that at least one baseline file exists +BASELINE_COUNT=0 +for Z in $METALLICITIES; do + if [ -f "$BASELINE_DIR/baseline_${Z}Zsun.h5" ]; then + BASELINE_COUNT=$((BASELINE_COUNT + 1)) + fi +done +if [ $BASELINE_COUNT -eq 0 ]; then + echo "ERROR: No baseline files found in $BASELINE_DIR for requested metallicities." >&2 + exit 1 +fi +echo " Found $BASELINE_COUNT baseline file(s)." + +# ── Step 1: Evolve binaries on candidate branch ────────────────────────── +echo "" +echo "Step 1: Evolving binaries on candidate branch '$CANDIDATE_BRANCH'..." +"$SCRIPT_DIR/evolve_binaries.sh" "$CANDIDATE_BRANCH" "" "$METALLICITIES" + +# ── Step 2: Compare each metallicity ───────────────────────────────────── +echo "" +echo "Step 2: Comparing results..." + +TOTAL=0 +PASS=0 +FAIL=0 +SKIP=0 + +# Initialize summary +mkdir -p "$OUTPUT_DIR" +cat > "$SUMMARY_FILE" << EOF +POSYDON Binary Validation — Comparison Summary +================================================ +Candidate branch: $CANDIDATE_BRANCH +Baseline branch: $BASELINE_BRANCH +Date: $(date -u '+%Y-%m-%d %H:%M:%S UTC') +================================================ + +EOF + +for Z in $METALLICITIES; do + TOTAL=$((TOTAL + 1)) + + BASELINE_FILE="$BASELINE_DIR/baseline_${Z}Zsun.h5" + CANDIDATE_FILE="$OUTPUT_DIR/candidate_${Z}Zsun.h5" + COMPARISON_FILE="$OUTPUT_DIR/comparison_${Z}Zsun.txt" + + echo "" + echo "--- Z = ${Z} Zsun ---" + + if [ ! -f "$BASELINE_FILE" ]; then + echo " SKIP: No baseline file for Z=${Z}" + echo "Z = ${Z} Zsun: SKIPPED (no baseline)" >> "$SUMMARY_FILE" + SKIP=$((SKIP + 1)) + continue + fi + + if [ ! -f "$CANDIDATE_FILE" ]; then + echo " FAIL: No candidate file for Z=${Z}" + echo "Z = ${Z} Zsun: FAIL (no candidate output)" >> "$SUMMARY_FILE" + FAIL=$((FAIL + 1)) + continue + fi + + if python "$SCRIPT_DIR/compare_runs.py" "$BASELINE_FILE" "$CANDIDATE_FILE" \ + 2>&1 | tee "$COMPARISON_FILE"; then + echo " PASS: No differences" + echo "Z = ${Z} Zsun: PASS" >> "$SUMMARY_FILE" + PASS=$((PASS + 1)) + else + echo " DIFFERENCES DETECTED — see $COMPARISON_FILE" + echo "Z = ${Z} Zsun: DIFFERENCES DETECTED (see comparison_${Z}Zsun.txt)" >> "$SUMMARY_FILE" + FAIL=$((FAIL + 1)) + fi +done + +# ── Final Summary ───────────────────────────────────────────────────────── +cat >> "$SUMMARY_FILE" << EOF + +================================================ +TOTAL: $TOTAL | PASS: $PASS | FAIL: $FAIL | SKIP: $SKIP +EOF + +echo "" +echo "============================================================" +echo " Validation Summary" +echo " TOTAL: $TOTAL | PASS: $PASS | FAIL: $FAIL | SKIP: $SKIP" +echo " Full summary: $SUMMARY_FILE" +echo "============================================================" + +if [ $FAIL -gt 0 ]; then + exit 1 +fi +exit 0 \ No newline at end of file From 396e94b592ef604ded1a805f52ab80385c9f8a3c Mon Sep 17 00:00:00 2001 From: Elizabeth Teng Date: Thu, 26 Feb 2026 04:15:34 -0600 Subject: [PATCH 25/91] gitignore --- dev-tools/.gitignore | 9 - dev-tools/check_outputs.ipynb | 512 ---------------------------------- 2 files changed, 521 deletions(-) delete mode 100644 dev-tools/check_outputs.ipynb diff --git a/dev-tools/.gitignore b/dev-tools/.gitignore index 1cea72efc6..bec9d97e5a 100644 --- a/dev-tools/.gitignore +++ b/dev-tools/.gitignore @@ -1,14 +1,5 @@ -# Remove the accidentally staged clone -git rm --cached -r workdirs/ - -# Create .gitignore -cat > .gitignore << 'EOF' workdirs/ outputs/ logs/ baselines/ test_*.h5 -EOF - -git add .gitignore - diff --git a/dev-tools/check_outputs.ipynb b/dev-tools/check_outputs.ipynb deleted file mode 100644 index c0073df835..0000000000 --- a/dev-tools/check_outputs.ipynb +++ /dev/null @@ -1,512 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": 1, - "id": "7e9791d3", - "metadata": {}, - "outputs": [], - "source": [ - "import argparse\n", - "import os\n", - "import signal\n", - "import sys\n", - "import warnings\n", - "import h5py\n", - "import pandas as pd\n", - "\n", - "from posydon.binary_evol.binarystar import BinaryStar, SingleStar\n", - "from posydon.binary_evol.simulationproperties import SimulationProperties\n", - "from posydon.popsyn.io import simprop_kwargs_from_ini\n", - "from posydon.utils.common_functions import orbital_separation_from_period" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "id": "327be9fe", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "env: PATH_TO_POSYDON=/projects/b1119/eteng/software/valid/POSYDON/\n", - "env: PATH_TO_POSYDON_DATA=/projects/b1119/POSYDON_popsynth_data/v2/250520_newSNe/\n" - ] - } - ], - "source": [ - "%env PATH_TO_POSYDON=/projects/b1119/eteng/software/valid/POSYDON/\n", - "%env PATH_TO_POSYDON_DATA=/projects/b1119/POSYDON_popsynth_data/v2/250520_newSNe/" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "id": "994f6ebf", - "metadata": {}, - "outputs": [ - { - "ename": "HDF5ExtError", - "evalue": "HDF5 error back trace\n\n File \"H5F.c\", line 836, in H5Fopen\n unable to synchronously open file\n File \"H5F.c\", line 796, in H5F__open_api_common\n unable to open file\n File \"H5VLcallback.c\", line 3863, in H5VL_file_open\n open failed\n File \"H5VLcallback.c\", line 3675, in H5VL__file_open\n open failed\n File \"H5VLnative_file.c\", line 128, in H5VL__native_file_open\n unable to open file\n File \"H5Fint.c\", line 2018, in H5F_open\n unable to read superblock\n File \"H5Fsuper.c\", line 600, in H5F__super_read\n truncated file: eof = 96, sblock->base_addr = 0, stored_eof = 2048\n\nEnd of HDF5 error back trace\n\nUnable to open/create file './POSYDON_main/outputs/candidate_main.h5'", - "output_type": "error", - "traceback": [ - "\u001b[31m---------------------------------------------------------------------------\u001b[39m", - "\u001b[31mHDF5ExtError\u001b[39m Traceback (most recent call last)", - "\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[4]\u001b[39m\u001b[32m, line 1\u001b[39m\n\u001b[32m----> \u001b[39m\u001b[32m1\u001b[39m df = \u001b[43mpd\u001b[49m\u001b[43m.\u001b[49m\u001b[43mread_hdf\u001b[49m\u001b[43m(\u001b[49m\u001b[33;43m'\u001b[39;49m\u001b[33;43m./POSYDON_main/outputs/candidate_main.h5\u001b[39;49m\u001b[33;43m'\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[33;43m\"\u001b[39;49m\u001b[33;43mevolution\u001b[39;49m\u001b[33;43m\"\u001b[39;49m\u001b[43m)\u001b[49m\n\u001b[32m 2\u001b[39m warnings = pd.read_hdf(\u001b[33m'\u001b[39m\u001b[33m./POSYDON_main/outputs/candidate_main.h5\u001b[39m\u001b[33m'\u001b[39m, \u001b[33m\"\u001b[39m\u001b[33mwarnings\u001b[39m\u001b[33m\"\u001b[39m)\n", - "\u001b[36mFile \u001b[39m\u001b[32m~/.conda/envs/valid/lib/python3.11/site-packages/pandas/io/pytables.py:426\u001b[39m, in \u001b[36mread_hdf\u001b[39m\u001b[34m(path_or_buf, key, mode, errors, where, start, stop, columns, iterator, chunksize, **kwargs)\u001b[39m\n\u001b[32m 423\u001b[39m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m exists:\n\u001b[32m 424\u001b[39m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mFileNotFoundError\u001b[39;00m(\u001b[33mf\u001b[39m\u001b[33m\"\u001b[39m\u001b[33mFile \u001b[39m\u001b[38;5;132;01m{\u001b[39;00mpath_or_buf\u001b[38;5;132;01m}\u001b[39;00m\u001b[33m does not exist\u001b[39m\u001b[33m\"\u001b[39m)\n\u001b[32m--> \u001b[39m\u001b[32m426\u001b[39m store = \u001b[43mHDFStore\u001b[49m\u001b[43m(\u001b[49m\u001b[43mpath_or_buf\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mmode\u001b[49m\u001b[43m=\u001b[49m\u001b[43mmode\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43merrors\u001b[49m\u001b[43m=\u001b[49m\u001b[43merrors\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43m*\u001b[49m\u001b[43m*\u001b[49m\u001b[43mkwargs\u001b[49m\u001b[43m)\u001b[49m\n\u001b[32m 427\u001b[39m \u001b[38;5;66;03m# can't auto open/close if we are using an iterator\u001b[39;00m\n\u001b[32m 428\u001b[39m \u001b[38;5;66;03m# so delegate to the iterator\u001b[39;00m\n\u001b[32m 429\u001b[39m auto_close = \u001b[38;5;28;01mTrue\u001b[39;00m\n", - "\u001b[36mFile \u001b[39m\u001b[32m~/.conda/envs/valid/lib/python3.11/site-packages/pandas/io/pytables.py:585\u001b[39m, in \u001b[36mHDFStore.__init__\u001b[39m\u001b[34m(self, path, mode, complevel, complib, fletcher32, **kwargs)\u001b[39m\n\u001b[32m 583\u001b[39m \u001b[38;5;28mself\u001b[39m._fletcher32 = fletcher32\n\u001b[32m 584\u001b[39m \u001b[38;5;28mself\u001b[39m._filters = \u001b[38;5;28;01mNone\u001b[39;00m\n\u001b[32m--> \u001b[39m\u001b[32m585\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[43m.\u001b[49m\u001b[43mopen\u001b[49m\u001b[43m(\u001b[49m\u001b[43mmode\u001b[49m\u001b[43m=\u001b[49m\u001b[43mmode\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43m*\u001b[49m\u001b[43m*\u001b[49m\u001b[43mkwargs\u001b[49m\u001b[43m)\u001b[49m\n", - "\u001b[36mFile \u001b[39m\u001b[32m~/.conda/envs/valid/lib/python3.11/site-packages/pandas/io/pytables.py:745\u001b[39m, in \u001b[36mHDFStore.open\u001b[39m\u001b[34m(self, mode, **kwargs)\u001b[39m\n\u001b[32m 739\u001b[39m msg = (\n\u001b[32m 740\u001b[39m \u001b[33m\"\u001b[39m\u001b[33mCannot open HDF5 file, which is already opened, \u001b[39m\u001b[33m\"\u001b[39m\n\u001b[32m 741\u001b[39m \u001b[33m\"\u001b[39m\u001b[33meven in read-only mode.\u001b[39m\u001b[33m\"\u001b[39m\n\u001b[32m 742\u001b[39m )\n\u001b[32m 743\u001b[39m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mValueError\u001b[39;00m(msg)\n\u001b[32m--> \u001b[39m\u001b[32m745\u001b[39m \u001b[38;5;28mself\u001b[39m._handle = \u001b[43mtables\u001b[49m\u001b[43m.\u001b[49m\u001b[43mopen_file\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[43m.\u001b[49m\u001b[43m_path\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[43m.\u001b[49m\u001b[43m_mode\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43m*\u001b[49m\u001b[43m*\u001b[49m\u001b[43mkwargs\u001b[49m\u001b[43m)\u001b[49m\n", - "\u001b[36mFile \u001b[39m\u001b[32m~/.conda/envs/valid/lib/python3.11/site-packages/tables/file.py:296\u001b[39m, in \u001b[36mopen_file\u001b[39m\u001b[34m(filename, mode, title, root_uep, filters, **kwargs)\u001b[39m\n\u001b[32m 291\u001b[39m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mValueError\u001b[39;00m(\n\u001b[32m 292\u001b[39m \u001b[33m\"\u001b[39m\u001b[33mThe file \u001b[39m\u001b[33m'\u001b[39m\u001b[38;5;132;01m%s\u001b[39;00m\u001b[33m'\u001b[39m\u001b[33m is already opened. Please \u001b[39m\u001b[33m\"\u001b[39m\n\u001b[32m 293\u001b[39m \u001b[33m\"\u001b[39m\u001b[33mclose it before reopening in write mode.\u001b[39m\u001b[33m\"\u001b[39m % filename)\n\u001b[32m 295\u001b[39m \u001b[38;5;66;03m# Finally, create the File instance, and return it\u001b[39;00m\n\u001b[32m--> \u001b[39m\u001b[32m296\u001b[39m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43mFile\u001b[49m\u001b[43m(\u001b[49m\u001b[43mfilename\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mmode\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mtitle\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mroot_uep\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mfilters\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43m*\u001b[49m\u001b[43m*\u001b[49m\u001b[43mkwargs\u001b[49m\u001b[43m)\u001b[49m\n", - "\u001b[36mFile \u001b[39m\u001b[32m~/.conda/envs/valid/lib/python3.11/site-packages/tables/file.py:746\u001b[39m, in \u001b[36mFile.__init__\u001b[39m\u001b[34m(self, filename, mode, title, root_uep, filters, **kwargs)\u001b[39m\n\u001b[32m 743\u001b[39m \u001b[38;5;28mself\u001b[39m.params = params\n\u001b[32m 745\u001b[39m \u001b[38;5;66;03m# Now, it is time to initialize the File extension\u001b[39;00m\n\u001b[32m--> \u001b[39m\u001b[32m746\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[43m.\u001b[49m\u001b[43m_g_new\u001b[49m\u001b[43m(\u001b[49m\u001b[43mfilename\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mmode\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43m*\u001b[49m\u001b[43m*\u001b[49m\u001b[43mparams\u001b[49m\u001b[43m)\u001b[49m\n\u001b[32m 748\u001b[39m \u001b[38;5;66;03m# Check filters and set PyTables format version for new files.\u001b[39;00m\n\u001b[32m 749\u001b[39m new = \u001b[38;5;28mself\u001b[39m._v_new\n", - "\u001b[36mFile \u001b[39m\u001b[32m~/.conda/envs/valid/lib/python3.11/site-packages/tables/hdf5extension.pyx:514\u001b[39m, in \u001b[36mtables.hdf5extension.File._g_new\u001b[39m\u001b[34m()\u001b[39m\n", - "\u001b[31mHDF5ExtError\u001b[39m: HDF5 error back trace\n\n File \"H5F.c\", line 836, in H5Fopen\n unable to synchronously open file\n File \"H5F.c\", line 796, in H5F__open_api_common\n unable to open file\n File \"H5VLcallback.c\", line 3863, in H5VL_file_open\n open failed\n File \"H5VLcallback.c\", line 3675, in H5VL__file_open\n open failed\n File \"H5VLnative_file.c\", line 128, in H5VL__native_file_open\n unable to open file\n File \"H5Fint.c\", line 2018, in H5F_open\n unable to read superblock\n File \"H5Fsuper.c\", line 600, in H5F__super_read\n truncated file: eof = 96, sblock->base_addr = 0, stored_eof = 2048\n\nEnd of HDF5 error back trace\n\nUnable to open/create file './POSYDON_main/outputs/candidate_main.h5'" - ] - } - ], - "source": [ - "df = pd.read_hdf('./POSYDON_main/outputs/candidate_main.h5', \"evolution\")\n", - "warnings = pd.read_hdf('./POSYDON_main/outputs/candidate_main.h5', \"warnings\")" - ] - }, - { - "cell_type": "code", - "execution_count": 56, - "id": "7028a060", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Index(['state', 'event', 'time', 'separation', 'orbital_period',\n", - " 'eccentricity', 'rl_relative_overflow_1', 'rl_relative_overflow_2',\n", - " 'lg_mtransfer_rate', 'mass_transfer_case',\n", - " ...\n", - " 'S2_mass_conv_reg_fortides', 'S2_thickness_conv_reg_fortides',\n", - " 'S2_radius_conv_reg_fortides', 'S2_lambda_CE_1cent',\n", - " 'S2_lambda_CE_10cent', 'S2_lambda_CE_30cent',\n", - " 'S2_lambda_CE_pure_He_star_10cent', 'S2_total_mass_h1',\n", - " 'S2_total_mass_he4', 'binary_id'],\n", - " dtype='object', length=134)\n" - ] - } - ], - "source": [ - "print(df.keys())" - ] - }, - { - "cell_type": "code", - "execution_count": 20, - "id": "76233b25", - "metadata": { - "collapsed": true - }, - "outputs": [ - { - "data": { - "text/html": [ - "
\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
binary_idexception_typeexception_message
01ValueErrorTrying to store a string with len [27] in [S1_...
02ValueErrorTrying to store a string with len [12] in [sta...
03ValueErrorTrying to store a string with len [9] in [even...
04ValueErrorTrying to store a string with len [9] in [even...
05ValueErrorTrying to store a string with len [9] in [even...
07ValueErrorTrying to store a string with len [27] in [S1_...
08ValueErrorTrying to store a string with len [10] in [eve...
09ValueErrorTrying to store a string with len [7] in [even...
010ValueErrorTrying to store a string with len [27] in [S1_...
011ValueErrorTrying to store a string with len [7] in [even...
012ValueErrorTrying to store a string with len [7] in [even...
013ValueErrorTrying to store a string with len [7] in [even...
014ValueErrorTrying to store a string with len [23] in [S1_...
015ValueErrorTrying to store a string with len [9] in [even...
016ValueErrorTrying to store a string with len [9] in [even...
018ValueErrorTrying to store a string with len [7] in [even...
019ValueErrorTrying to store a string with len [7] in [even...
020ValueErrorTrying to store a string with len [7] in [even...
021ValueErrorTrying to store a string with len [7] in [even...
022ValueErrorTrying to store a string with len [9] in [even...
023ValueErrorTrying to store a string with len [9] in [even...
024ValueErrorTrying to store a string with len [9] in [even...
025ValueErrorTrying to store a string with len [7] in [even...
026ValueErrorTrying to store a string with len [9] in [even...
027ValueErrorTrying to store a string with len [7] in [even...
028ValueErrorTrying to store a string with len [7] in [even...
029ValueErrorTrying to store a string with len [7] in [even...
030ValueErrorTrying to store a string with len [7] in [even...
031ValueErrorTrying to store a string with len [7] in [even...
032ValueErrorTrying to store a string with len [7] in [even...
033ValueErrorTrying to store a string with len [7] in [even...
034ValueErrorTrying to store a string with len [7] in [even...
035ValueErrorTrying to store a string with len [9] in [even...
036ValueErrorTrying to store a string with len [7] in [even...
037ValueErrorTrying to store a string with len [10] in [eve...
038ValueErrorTrying to store a string with len [9] in [even...
039MatchingErrorGrid matching failed for merged binary. \\nseco...
040ClassificationErrorBinary is in the detached step but has stable ...
041ValueErrorTrying to store a string with len [7] in [even...
042FlowErrorEvolution of H-rich/He-rich stars in RLO onto ...
043ValueErrorTrying to store a string with len [7] in [even...
\n", - "
" - ], - "text/plain": [ - " binary_id exception_type \\\n", - "0 1 ValueError \n", - "0 2 ValueError \n", - "0 3 ValueError \n", - "0 4 ValueError \n", - "0 5 ValueError \n", - "0 7 ValueError \n", - "0 8 ValueError \n", - "0 9 ValueError \n", - "0 10 ValueError \n", - "0 11 ValueError \n", - "0 12 ValueError \n", - "0 13 ValueError \n", - "0 14 ValueError \n", - "0 15 ValueError \n", - "0 16 ValueError \n", - "0 18 ValueError \n", - "0 19 ValueError \n", - "0 20 ValueError \n", - "0 21 ValueError \n", - "0 22 ValueError \n", - "0 23 ValueError \n", - "0 24 ValueError \n", - "0 25 ValueError \n", - "0 26 ValueError \n", - "0 27 ValueError \n", - "0 28 ValueError \n", - "0 29 ValueError \n", - "0 30 ValueError \n", - "0 31 ValueError \n", - "0 32 ValueError \n", - "0 33 ValueError \n", - "0 34 ValueError \n", - "0 35 ValueError \n", - "0 36 ValueError \n", - "0 37 ValueError \n", - "0 38 ValueError \n", - "0 39 MatchingError \n", - "0 40 ClassificationError \n", - "0 41 ValueError \n", - "0 42 FlowError \n", - "0 43 ValueError \n", - "\n", - " exception_message \n", - "0 Trying to store a string with len [27] in [S1_... \n", - "0 Trying to store a string with len [12] in [sta... \n", - "0 Trying to store a string with len [9] in [even... \n", - "0 Trying to store a string with len [9] in [even... \n", - "0 Trying to store a string with len [9] in [even... \n", - "0 Trying to store a string with len [27] in [S1_... \n", - "0 Trying to store a string with len [10] in [eve... \n", - "0 Trying to store a string with len [7] in [even... \n", - "0 Trying to store a string with len [27] in [S1_... \n", - "0 Trying to store a string with len [7] in [even... \n", - "0 Trying to store a string with len [7] in [even... \n", - "0 Trying to store a string with len [7] in [even... \n", - "0 Trying to store a string with len [23] in [S1_... \n", - "0 Trying to store a string with len [9] in [even... \n", - "0 Trying to store a string with len [9] in [even... \n", - "0 Trying to store a string with len [7] in [even... \n", - "0 Trying to store a string with len [7] in [even... \n", - "0 Trying to store a string with len [7] in [even... \n", - "0 Trying to store a string with len [7] in [even... \n", - "0 Trying to store a string with len [9] in [even... \n", - "0 Trying to store a string with len [9] in [even... \n", - "0 Trying to store a string with len [9] in [even... \n", - "0 Trying to store a string with len [7] in [even... \n", - "0 Trying to store a string with len [9] in [even... \n", - "0 Trying to store a string with len [7] in [even... \n", - "0 Trying to store a string with len [7] in [even... \n", - "0 Trying to store a string with len [7] in [even... \n", - "0 Trying to store a string with len [7] in [even... \n", - "0 Trying to store a string with len [7] in [even... \n", - "0 Trying to store a string with len [7] in [even... \n", - "0 Trying to store a string with len [7] in [even... \n", - "0 Trying to store a string with len [7] in [even... \n", - "0 Trying to store a string with len [9] in [even... \n", - "0 Trying to store a string with len [7] in [even... \n", - "0 Trying to store a string with len [10] in [eve... \n", - "0 Trying to store a string with len [9] in [even... \n", - "0 Grid matching failed for merged binary. \\nseco... \n", - "0 Binary is in the detached step but has stable ... \n", - "0 Trying to store a string with len [7] in [even... \n", - "0 Evolution of H-rich/He-rich stars in RLO onto ... \n", - "0 Trying to store a string with len [7] in [even... " - ] - }, - "execution_count": 20, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "errors" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "68d4d8a8", - "metadata": {}, - "outputs": [], - "source": [] - } - ], - "metadata": { - "kernelspec": { - "display_name": "valid", - "language": "python", - "name": "valid" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.11.14" - } - }, - "nbformat": 4, - "nbformat_minor": 5 -} From 1f260a86db3803b1cd901ac31bf27648deb66143 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Thu, 26 Feb 2026 10:17:22 +0000 Subject: [PATCH 26/91] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- dev-tools/compare_runs.py | 6 +++--- dev-tools/evolve_binaries.sh | 2 +- dev-tools/generate_baseline.sh | 2 +- dev-tools/script_data/binaries_suite.py | 17 +++++++++-------- dev-tools/validate_binaries.sh | 2 +- 5 files changed, 15 insertions(+), 14 deletions(-) diff --git a/dev-tools/compare_runs.py b/dev-tools/compare_runs.py index 0d2fe2df7e..a19c0f9ddc 100644 --- a/dev-tools/compare_runs.py +++ b/dev-tools/compare_runs.py @@ -19,12 +19,12 @@ """ import argparse -import sys import os +import sys + import numpy as np import pandas as pd - # Columns that represent qualitative (categorical) evolution properties. # Any column matching these names will be compared as exact string matches # and reported under "QUALITATIVE" differences. @@ -409,4 +409,4 @@ def main(): if __name__ == "__main__": - main() \ No newline at end of file + main() diff --git a/dev-tools/evolve_binaries.sh b/dev-tools/evolve_binaries.sh index 8bfcceef2a..30f7d7b745 100755 --- a/dev-tools/evolve_binaries.sh +++ b/dev-tools/evolve_binaries.sh @@ -150,4 +150,4 @@ fi echo " Outputs in: $OUTPUT_DIR/" echo "============================================================" -exit $FAILED \ No newline at end of file +exit $FAILED diff --git a/dev-tools/generate_baseline.sh b/dev-tools/generate_baseline.sh index a4e31534a7..845b52cf3c 100644 --- a/dev-tools/generate_baseline.sh +++ b/dev-tools/generate_baseline.sh @@ -93,4 +93,4 @@ echo "============================================================" if [ $COPIED -eq 0 ]; then echo "ERROR: No baseline files were created!" >&2 exit 1 -fi \ No newline at end of file +fi diff --git a/dev-tools/script_data/binaries_suite.py b/dev-tools/script_data/binaries_suite.py index 08e0365dd9..157dc0dbab 100644 --- a/dev-tools/script_data/binaries_suite.py +++ b/dev-tools/script_data/binaries_suite.py @@ -14,6 +14,7 @@ import os import sys import warnings + import pandas as pd from posydon.binary_evol.binarystar import BinaryStar, SingleStar @@ -26,7 +27,7 @@ # Display settings TARGET_ROWS = 12 LINE_LENGTH = 80 -COLUMNS_TO_SHOW = ['step_names', 'state', 'event', +COLUMNS_TO_SHOW = ['step_names', 'state', 'event', 'S1_state', 'S1_mass', 'S2_state', 'S2_mass', 'orbital_period'] @@ -150,9 +151,9 @@ def warning_handler(message, category, filename, lineno, file=None, line=None): # Set up warning capture old_showwarning = warnings.showwarning warnings.showwarning = warning_handler - + print(f"Binary {binary_id}") - evolution_df = None + evolution_df = None try: binary.evolve() @@ -171,7 +172,7 @@ def warning_handler(message, category, filename, lineno, file=None, line=None): finally: warnings.showwarning = old_showwarning - + # Ensure we always have a dataframe if evolution_df is not None: # Decode bytes columns if needed @@ -212,9 +213,9 @@ def warning_handler(message, category, filename, lineno, file=None, line=None): print(f"āœ… Finished binary {binary_id}") print("=" * LINE_LENGTH) - - - + + + def get_test_binaries(metallicity, sim_prop): """Return the list of test binaries as (star1_kwargs, star2_kwargs, binary_kwargs, description) tuples. @@ -691,4 +692,4 @@ def evolve_binaries(metallicity, verbose, output_path, ini_path=None): verbose=args.verbose, output_path=args.output, ini_path=args.ini, - ) \ No newline at end of file + ) diff --git a/dev-tools/validate_binaries.sh b/dev-tools/validate_binaries.sh index 2ae354b4fa..6f902cf65d 100644 --- a/dev-tools/validate_binaries.sh +++ b/dev-tools/validate_binaries.sh @@ -141,4 +141,4 @@ echo "============================================================" if [ $FAIL -gt 0 ]; then exit 1 fi -exit 0 \ No newline at end of file +exit 0 From 200431a007281afb18ef87a7b44c00df4cc11c38 Mon Sep 17 00:00:00 2001 From: Elizabeth Teng Date: Mon, 9 Mar 2026 16:25:24 -0500 Subject: [PATCH 27/91] adding baseline h5 file for binary evolution --- dev-tools/generate_baseline.sh | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 dev-tools/generate_baseline.sh diff --git a/dev-tools/generate_baseline.sh b/dev-tools/generate_baseline.sh old mode 100644 new mode 100755 From 48b3ce9a5d123f6b69c6480a5ad529de6613ac3d Mon Sep 17 00:00:00 2001 From: Elizabeth Teng Date: Mon, 9 Mar 2026 16:26:45 -0500 Subject: [PATCH 28/91] add tolerances as CLI --- dev-tools/validate_binaries.sh | 85 ++++++++++++++++++++++++++++++++-- 1 file changed, 80 insertions(+), 5 deletions(-) mode change 100644 => 100755 dev-tools/validate_binaries.sh diff --git a/dev-tools/validate_binaries.sh b/dev-tools/validate_binaries.sh old mode 100644 new mode 100755 index 2ae354b4fa..8a312f8873 --- a/dev-tools/validate_binaries.sh +++ b/dev-tools/validate_binaries.sh @@ -1,16 +1,35 @@ #!/bin/bash # ============================================================================= -# validate_binaries.sh — Run the full validation pipeline: +# validate_binaries.sh: Run the full validation pipeline: # 1. Evolve test binaries on a candidate branch # 2. Compare against baseline files # # Usage: # ./validate_binaries.sh [baseline_branch] [metallicities] +# [--loose] [--rtol VALUE] [--atol VALUE] +# +# Positional arguments: +# candidate_branch Branch or tag to validate (required) +# baseline_branch Branch or tag to compare against (default: main) +# metallicities Space-separated list of Z values, quoted +# (default: "2 1 0.45 0.2 0.1 0.01 0.001 0.0001") +# +# Tolerance flags (passed through to compare_runs.py): +# --loose Use relaxed floating-point tolerances +# (rtol=1e-12, atol=1e-15 unless overridden) +# --rtol VALUE Set explicit relative tolerance +# --atol VALUE Set explicit absolute tolerance +# +# --rtol and --atol can be combined with --loose (explicit values take +# precedence over the --loose defaults) or used on their own without --loose. # # Examples: -# ./validate_binaries.sh feature/new-SN # compare vs main baseline -# ./validate_binaries.sh feature/new-SN v2.1.0 # compare vs v2.1.0 baseline -# ./validate_binaries.sh feature/new-SN main "1 0.45" # subset of metallicities +# ./validate_binaries.sh feature/new-SN # compare vs main, exact +# ./validate_binaries.sh feature/new-SN v2.1.0 # compare vs v2.1.0, exact +# ./validate_binaries.sh feature/new-SN main "1 0.45" # subset of metallicities +# ./validate_binaries.sh feature/new-SN --loose # relaxed tolerances +# ./validate_binaries.sh feature/new-SN main --rtol 1e-8 # custom rtol, default atol +# ./validate_binaries.sh feature/new-SN main "1 0.45" --loose --atol 1e-10 # # Prerequisites: # Run generate_baseline.sh first to create baseline files. @@ -22,9 +41,37 @@ set -euo pipefail -CANDIDATE_BRANCH=${1:?Usage: ./validate_binaries.sh [baseline_branch] [metallicities]} +# ── Parse arguments ─────────────────────────────────────────────────────── + +CANDIDATE_BRANCH=${1:?Usage: ./validate_binaries.sh [baseline_branch] [metallicities] [--loose] [--rtol VALUE] [--atol VALUE]} BASELINE_BRANCH=${2:-main} METALLICITIES=${3:-"2 1 0.45 0.2 0.1 0.01 0.001 0.0001"} +shift $(( $# < 3 ? $# : 3 )) + +LOOSE=false +RTOL="" +ATOL="" + +while [[ $# -gt 0 ]]; do + case "$1" in + --loose) + LOOSE=true + shift + ;; + --rtol) + RTOL="${2:?--rtol requires a value}" + shift 2 + ;; + --atol) + ATOL="${2:?--atol requires a value}" + shift 2 + ;; + *) + echo "ERROR: Unknown option: $1" >&2 + exit 1 + ;; + esac +done SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" SAFE_CANDIDATE="${CANDIDATE_BRANCH//\//_}" @@ -34,6 +81,30 @@ BASELINE_DIR="$SCRIPT_DIR/baselines/${SAFE_BASELINE}" OUTPUT_DIR="$SCRIPT_DIR/outputs/${SAFE_CANDIDATE}" SUMMARY_FILE="$OUTPUT_DIR/comparison_summary.txt" +# ── Build compare_runs.py flags ─────────────────────────────────────────── +COMPARE_FLAGS="" +if [ "$LOOSE" = "true" ]; then + COMPARE_FLAGS="$COMPARE_FLAGS --loose" +fi +if [ -n "$RTOL" ]; then + COMPARE_FLAGS="$COMPARE_FLAGS --rtol $RTOL" +fi +if [ -n "$ATOL" ]; then + COMPARE_FLAGS="$COMPARE_FLAGS --atol $ATOL" +fi + +# Build a human-readable tolerance label for the summary +if [ -n "$RTOL" ] || [ -n "$ATOL" ]; then + TOL_LABEL="rtol=${RTOL:-default}, atol=${ATOL:-default}" + if [ "$LOOSE" = "true" ]; then + TOL_LABEL="$TOL_LABEL (--loose)" + fi +elif [ "$LOOSE" = "true" ]; then + TOL_LABEL="--loose (rtol=1e-12, atol=1e-15)" +else + TOL_LABEL="EXACT (rtol=0, atol=0)" +fi + echo "============================================================" echo " POSYDON Binary Validation" echo " Candidate: $CANDIDATE_BRANCH" @@ -83,6 +154,7 @@ POSYDON Binary Validation — Comparison Summary ================================================ Candidate branch: $CANDIDATE_BRANCH Baseline branch: $BASELINE_BRANCH +Tolerances: $TOL_LABEL Date: $(date -u '+%Y-%m-%d %H:%M:%S UTC') ================================================ @@ -112,7 +184,10 @@ for Z in $METALLICITIES; do continue fi + # $COMPARE_FLAGS is intentionally unquoted so it word-splits into + # separate arguments for compare_runs.py. if python "$SCRIPT_DIR/compare_runs.py" "$BASELINE_FILE" "$CANDIDATE_FILE" \ + $COMPARE_FLAGS \ 2>&1 | tee "$COMPARISON_FILE"; then echo " PASS: No differences" echo "Z = ${Z} Zsun: PASS" >> "$SUMMARY_FILE" From 9d1d0fc30d9909e7305cf78e2584424c7eb435bf Mon Sep 17 00:00:00 2001 From: Elizabeth Teng Date: Mon, 9 Mar 2026 16:36:42 -0500 Subject: [PATCH 29/91] separate handling of errored binaries from successful binaries into an error table --- dev-tools/compare_runs.py | 87 ++++++++++++++++--------- dev-tools/script_data/binaries_suite.py | 23 ++++--- 2 files changed, 73 insertions(+), 37 deletions(-) diff --git a/dev-tools/compare_runs.py b/dev-tools/compare_runs.py index a19c0f9ddc..d2fbab7545 100644 --- a/dev-tools/compare_runs.py +++ b/dev-tools/compare_runs.py @@ -19,12 +19,12 @@ """ import argparse -import os import sys - +import os import numpy as np import pandas as pd + # Columns that represent qualitative (categorical) evolution properties. # Any column matching these names will be compared as exact string matches # and reported under "QUALITATIVE" differences. @@ -80,30 +80,6 @@ def compare_evolution_tables(base_df, cand_df, rtol, atol): b = base_df[base_df['binary_id'] == bid].reset_index(drop=True) c = cand_df[cand_df['binary_id'] == bid].reset_index(drop=True) - # ── Error status changes ────────────────────────────────────── - base_failed = 'exception_type' in b.columns and b['exception_type'].notna().any() - cand_failed = 'exception_type' in c.columns and c['exception_type'].notna().any() - - if base_failed != cand_failed: - if cand_failed: - exc = c['exception_type'].dropna().iloc[0] if 'exception_type' in c.columns else "unknown" - msg = c['exception_message'].dropna().iloc[0] if 'exception_message' in c.columns else "" - struct_diffs.append(f"Binary {bid}: NEWLY FAILING ({exc}: {msg})") - else: - struct_diffs.append(f"Binary {bid}: NEWLY PASSING (was failing in baseline)") - continue - - if base_failed and cand_failed: - b_exc = str(b['exception_type'].dropna().iloc[0]) if 'exception_type' in b.columns else "" - c_exc = str(c['exception_type'].dropna().iloc[0]) if 'exception_type' in c.columns else "" - b_msg = str(b['exception_message'].dropna().iloc[0]) if 'exception_message' in b.columns else "" - c_msg = str(c['exception_message'].dropna().iloc[0]) if 'exception_message' in c.columns else "" - if b_exc != c_exc: - struct_diffs.append(f"Binary {bid}: error type changed ('{b_exc}' -> '{c_exc}')") - if b_msg != c_msg: - struct_diffs.append(f"Binary {bid}: error message changed ('{b_msg}' -> '{c_msg}')") - continue - # ── Step count ──────────────────────────────────────────────── if len(b) != len(c): struct_diffs.append( @@ -260,6 +236,52 @@ def compare_warnings_tables(base_df, cand_df): return diffs +def compare_errors_tables(base_df, cand_df): + """Compare error tables between baseline and candidate. + + Returns list of diff strings. + """ + diffs = [] + + if base_df is None and cand_df is None: + return diffs + if base_df is None and cand_df is not None: + cand_ids = sorted(cand_df['binary_id'].unique()) if 'binary_id' in cand_df.columns else [] + diffs.append(f"Candidate has {len(cand_df)} error(s) (binaries {cand_ids}), baseline has none") + return diffs + if base_df is not None and cand_df is None: + base_ids = sorted(base_df['binary_id'].unique()) if 'binary_id' in base_df.columns else [] + diffs.append(f"Baseline has {len(base_df)} error(s) (binaries {base_ids}), candidate has none") + return diffs + + # Compare per-binary errors + if 'binary_id' in base_df.columns and 'binary_id' in cand_df.columns: + base_ids = set(base_df['binary_id'].unique()) + cand_ids = set(cand_df['binary_id'].unique()) + + for bid in sorted(cand_ids - base_ids): + row = cand_df[cand_df['binary_id'] == bid].iloc[0] + exc = row.get('exception_type', 'unknown') + diffs.append(f"Binary {bid}: NEWLY FAILING in candidate ({exc})") + + for bid in sorted(base_ids - cand_ids): + diffs.append(f"Binary {bid}: NEWLY PASSING in candidate (was failing in baseline)") + + for bid in sorted(base_ids & cand_ids): + b_row = base_df[base_df['binary_id'] == bid].iloc[0] + c_row = cand_df[cand_df['binary_id'] == bid].iloc[0] + b_exc = str(b_row.get('exception_type', '')) + c_exc = str(c_row.get('exception_type', '')) + b_msg = str(b_row.get('exception_message', '')) + c_msg = str(c_row.get('exception_message', '')) + if b_exc != c_exc: + diffs.append(f"Binary {bid}: error type changed ('{b_exc}' -> '{c_exc}')") + if b_msg != c_msg: + diffs.append(f"Binary {bid}: error message changed") + + return diffs + + def read_table_safe(store, key): """Read a table from HDFStore, returning None if it doesn't exist.""" try: @@ -347,12 +369,19 @@ def main(): cand_warn = read_table_safe(cand_store, '/warnings') warn_diffs.extend(compare_warnings_tables(base_warn, cand_warn)) + # ── Errors table ────────────────────────────────────────── + base_err = read_table_safe(base_store, '/errors') + cand_err = read_table_safe(cand_store, '/errors') + error_diffs = compare_errors_tables(base_err, cand_err) + struct_diffs.extend(error_diffs) + # ── Extra/missing top-level keys ────────────────────────── + ignored_keys = {'/evolution', '/warnings', '/errors', '/metadata'} for k in sorted(base_keys - cand_keys): - if k not in ['/evolution', '/warnings', '/metadata']: + if k not in ignored_keys: struct_diffs.append(f"Table '{k}' missing in candidate") for k in sorted(cand_keys - base_keys): - if k not in ['/evolution', '/warnings', '/metadata']: + if k not in ignored_keys: struct_diffs.append(f"Table '{k}' extra in candidate") except Exception as e: @@ -409,4 +438,4 @@ def main(): if __name__ == "__main__": - main() + main() \ No newline at end of file diff --git a/dev-tools/script_data/binaries_suite.py b/dev-tools/script_data/binaries_suite.py index 157dc0dbab..dda3824c75 100644 --- a/dev-tools/script_data/binaries_suite.py +++ b/dev-tools/script_data/binaries_suite.py @@ -43,6 +43,7 @@ def load_inlist(metallicity, verbose, ini_path=None): SimulationProperties object with loaded steps """ if ini_path is None: + # Look for ini file relative to this script's location script_dir = os.path.dirname(os.path.abspath(__file__)) ini_path = os.path.join(script_dir, 'binaries_params.ini') @@ -53,9 +54,12 @@ def load_inlist(metallicity, verbose, ini_path=None): metallicity_kwargs = {'metallicity': metallicity, 'verbose': verbose} - metallicity_steps = ['step_HMS_HMS', 'step_CO_HeMS', 'step_CO_HMS_RLO', - 'step_CO_HeMS_RLO', 'step_detached', 'step_disrupted', - 'step_merged', 'step_initially_single'] + # Apply metallicity to all steps that need it + metallicity_steps = [ + 'step_HMS_HMS', 'step_CO_HeMS', 'step_CO_HMS_RLO', + 'step_CO_HeMS_RLO', 'step_detached', 'step_disrupted', + 'step_merged', 'step_initially_single' + ] for step_name in metallicity_steps: if step_name in sim_kwargs: sim_kwargs[step_name][1].update(metallicity_kwargs) @@ -101,7 +105,6 @@ def print_failed_binary(binary,e, max_error_lines=3): df = binary.to_df(**{'extra_columns':{'step_names':'str'}}) if len(df) > 0: # Select only the desired columns - available_columns = [col for col in COLUMNS_TO_SHOW if col in df.columns] df_filtered = df[available_columns].reset_index(drop=True) @@ -163,12 +166,16 @@ def warning_handler(message, category, filename, lineno, file=None, line=None): except Exception as e: print_failed_binary(binary, e) - # If evolution fails, create a minimal df with error info - evolution_df = pd.DataFrame([{ + # Save error to separate table (different schema from evolution) + error_df = pd.DataFrame([{ "binary_id": int(binary_id), "exception_type": type(e).__name__, "exception_message": str(e) }]) + error_string_cols = error_df.select_dtypes([object]).columns + error_min_itemsize = {col: 1000 for col in error_string_cols} + h5file.append("errors", error_df, format="table", + min_itemsize=error_min_itemsize) finally: warnings.showwarning = old_showwarning @@ -191,7 +198,7 @@ def warning_handler(message, category, filename, lineno, file=None, line=None): # Determine min_itemsize from the dataframe we're actually saving string_cols = evolution_df.select_dtypes([object]).columns - min_itemsize = {col: 100 for col in string_cols} + min_itemsize = {col: 500 for col in string_cols} h5file.append("evolution", evolution_df, format="table", data_columns=True, min_itemsize=min_itemsize) @@ -200,7 +207,7 @@ def warning_handler(message, category, filename, lineno, file=None, line=None): warn_df = pd.DataFrame(captured_warnings) # Ensure consistent string column sizes for warnings table warn_string_cols = warn_df.select_dtypes([object]).columns - warn_min_itemsize = {col: 200 for col in warn_string_cols} + warn_min_itemsize = {col: 1000 for col in warn_string_cols} h5file.append("warnings", warn_df, format="table", min_itemsize=warn_min_itemsize) print(f"āš ļø {len(captured_warnings)} warning(s) raised during evolution:") From d71b0ad9d291fbd8a56186b88fdc5e55f6e4b028 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 9 Mar 2026 21:41:30 +0000 Subject: [PATCH 30/91] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- dev-tools/compare_runs.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dev-tools/compare_runs.py b/dev-tools/compare_runs.py index d2fbab7545..b153c5127b 100644 --- a/dev-tools/compare_runs.py +++ b/dev-tools/compare_runs.py @@ -19,12 +19,12 @@ """ import argparse -import sys import os +import sys + import numpy as np import pandas as pd - # Columns that represent qualitative (categorical) evolution properties. # Any column matching these names will be compared as exact string matches # and reported under "QUALITATIVE" differences. @@ -438,4 +438,4 @@ def main(): if __name__ == "__main__": - main() \ No newline at end of file + main() From 9f72e664a582add746f55b0f4e7b677266c7e093 Mon Sep 17 00:00:00 2001 From: Elizabeth Teng Date: Mon, 9 Mar 2026 16:52:58 -0500 Subject: [PATCH 31/91] consolidate h5 writes for efficiency --- dev-tools/script_data/binaries_suite.py | 94 ++++++++++++++++--------- 1 file changed, 59 insertions(+), 35 deletions(-) diff --git a/dev-tools/script_data/binaries_suite.py b/dev-tools/script_data/binaries_suite.py index dda3824c75..8339adbbb4 100644 --- a/dev-tools/script_data/binaries_suite.py +++ b/dev-tools/script_data/binaries_suite.py @@ -31,6 +31,11 @@ 'S1_state', 'S1_mass', 'S2_state', 'S2_mass', 'orbital_period'] +# Suppress fragmentation warnings from POSYDON internals. +# The .copy() calls below already handle the actual performance impact; +# these warnings are just noise from to_df() building DataFrames column-by-column. +# warnings.filterwarnings("ignore", message=".*DataFrame is highly fragmented.*") + def load_inlist(metallicity, verbose, ini_path=None): """Load simulation properties from ini file and configure for given metallicity. @@ -157,6 +162,7 @@ def warning_handler(message, category, filename, lineno, file=None, line=None): print(f"Binary {binary_id}") evolution_df = None + error_df = None try: binary.evolve() @@ -166,16 +172,11 @@ def warning_handler(message, category, filename, lineno, file=None, line=None): except Exception as e: print_failed_binary(binary, e) - # Save error to separate table (different schema from evolution) error_df = pd.DataFrame([{ "binary_id": int(binary_id), "exception_type": type(e).__name__, "exception_message": str(e) }]) - error_string_cols = error_df.select_dtypes([object]).columns - error_min_itemsize = {col: 1000 for col in error_string_cols} - h5file.append("errors", error_df, format="table", - min_itemsize=error_min_itemsize) finally: warnings.showwarning = old_showwarning @@ -193,23 +194,11 @@ def warning_handler(message, category, filename, lineno, file=None, line=None): if "binary_id" not in evolution_df.columns: evolution_df["binary_id"] = int(binary_id) - # Defragment + # Defragment the DataFrame from POSYDON's column-by-column construction evolution_df = evolution_df.copy() - # Determine min_itemsize from the dataframe we're actually saving - string_cols = evolution_df.select_dtypes([object]).columns - min_itemsize = {col: 500 for col in string_cols} - h5file.append("evolution", evolution_df, format="table", - data_columns=True, min_itemsize=min_itemsize) - # Save warnings if captured_warnings: - warn_df = pd.DataFrame(captured_warnings) - # Ensure consistent string column sizes for warnings table - warn_string_cols = warn_df.select_dtypes([object]).columns - warn_min_itemsize = {col: 1000 for col in warn_string_cols} - h5file.append("warnings", warn_df, format="table", - min_itemsize=warn_min_itemsize) print(f"āš ļø {len(captured_warnings)} warning(s) raised during evolution:") for i, w in enumerate(captured_warnings[:3], 1): print(f" {i}. {w['category']}: {w['message'][:80]}") @@ -221,8 +210,6 @@ def warning_handler(message, category, filename, lineno, file=None, line=None): print(f"āœ… Finished binary {binary_id}") print("=" * LINE_LENGTH) - - def get_test_binaries(metallicity, sim_prop): """Return the list of test binaries as (star1_kwargs, star2_kwargs, binary_kwargs, description) tuples. @@ -647,7 +634,38 @@ def evolve_binaries(metallicity, verbose, output_path, ini_path=None): sim_prop = load_inlist(metallicity, verbose, ini_path) test_binaries = get_test_binaries(metallicity, sim_prop) - + + # Collect all results in memory, then write once at the end. + # This avoids repeated HDFStore.append() calls, each of which + # reconciles schemas, checks string sizing, and flushes to disk. + all_evolution_dfs = [] + all_error_dfs = [] + all_warning_dfs = [] + + for binary_id, (s1_kw, s2_kw, bin_kw, description) in enumerate(test_binaries): + print(f"\n[{binary_id}/{len(test_binaries)-1}] {description}") + + star_1 = SingleStar(**s1_kw) + star_2 = SingleStar(**s2_kw) + + # Add separation from period if not explicitly provided + if 'separation' not in bin_kw and 'orbital_period' in bin_kw: + bin_kw['separation'] = orbital_separation_from_period( + bin_kw['orbital_period'], star_1.mass, star_2.mass + ) + + binary = BinaryStar(star_1, star_2, **bin_kw, properties=sim_prop) + evo_df, err_df, warn_list = evolve_binary(binary, binary_id) + + if evo_df is not None: + all_evolution_dfs.append(evo_df) + if err_df is not None: + all_error_dfs.append(err_df) + if warn_list: + all_warning_dfs.append(pd.DataFrame(warn_list)) + + + # ── Single-pass HDF5 write ────────────────────────────────────────── with pd.HDFStore(output_path, mode="w") as h5file: # Save metadata meta_df = pd.DataFrame([{ @@ -656,20 +674,26 @@ def evolve_binaries(metallicity, verbose, output_path, ini_path=None): }]) h5file.put("metadata", meta_df, format="table") - for binary_id, (s1_kw, s2_kw, bin_kw, description) in enumerate(test_binaries): - print(f"\n[{binary_id}/{len(test_binaries)-1}] {description}") - - star_1 = SingleStar(**s1_kw) - star_2 = SingleStar(**s2_kw) - - # Add separation from period if not explicitly provided - if 'separation' not in bin_kw and 'orbital_period' in bin_kw: - bin_kw['separation'] = orbital_separation_from_period( - bin_kw['orbital_period'], star_1.mass, star_2.mass - ) - - binary = BinaryStar(star_1, star_2, **bin_kw, properties=sim_prop) - evolve_binary(binary, h5file, binary_id) + if all_evolution_dfs: + combined_evo = pd.concat(all_evolution_dfs, ignore_index=True) + string_cols = combined_evo.select_dtypes([object]).columns + min_itemsize = {col: 500 for col in string_cols} + h5file.put("evolution", combined_evo, format="table", + data_columns=True, min_itemsize=min_itemsize) + + if all_error_dfs: + combined_err = pd.concat(all_error_dfs, ignore_index=True) + err_string_cols = combined_err.select_dtypes([object]).columns + err_min_itemsize = {col: 1000 for col in err_string_cols} + h5file.put("errors", combined_err, format="table", + min_itemsize=err_min_itemsize) + + if all_warning_dfs: + combined_warn = pd.concat(all_warning_dfs, ignore_index=True) + warn_string_cols = combined_warn.select_dtypes([object]).columns + warn_min_itemsize = {col: 1000 for col in warn_string_cols} + h5file.put("warnings", combined_warn, format="table", + min_itemsize=warn_min_itemsize) print(f"\n{'=' * LINE_LENGTH}") print(f" All {len(test_binaries)} binaries complete. Results saved to {output_path}") From 3a3cd77d7c21bf42249f0b4f2fdce202314dc69f Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 9 Mar 2026 21:58:35 +0000 Subject: [PATCH 32/91] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- dev-tools/script_data/binaries_suite.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dev-tools/script_data/binaries_suite.py b/dev-tools/script_data/binaries_suite.py index 8339adbbb4..5cd8be7147 100644 --- a/dev-tools/script_data/binaries_suite.py +++ b/dev-tools/script_data/binaries_suite.py @@ -634,14 +634,14 @@ def evolve_binaries(metallicity, verbose, output_path, ini_path=None): sim_prop = load_inlist(metallicity, verbose, ini_path) test_binaries = get_test_binaries(metallicity, sim_prop) - + # Collect all results in memory, then write once at the end. # This avoids repeated HDFStore.append() calls, each of which # reconciles schemas, checks string sizing, and flushes to disk. all_evolution_dfs = [] all_error_dfs = [] all_warning_dfs = [] - + for binary_id, (s1_kw, s2_kw, bin_kw, description) in enumerate(test_binaries): print(f"\n[{binary_id}/{len(test_binaries)-1}] {description}") From 1efad00d690c359c35b8c988e9c75e5904eb9b3f Mon Sep 17 00:00:00 2001 From: Elizabeth Teng Date: Mon, 9 Mar 2026 17:01:18 -0500 Subject: [PATCH 33/91] add flag to promote existing evolved branch to baseline status --- dev-tools/generate_baseline.sh | 51 +++++++++++++++++++++++++++------- 1 file changed, 41 insertions(+), 10 deletions(-) diff --git a/dev-tools/generate_baseline.sh b/dev-tools/generate_baseline.sh index 845b52cf3c..3539be5c81 100755 --- a/dev-tools/generate_baseline.sh +++ b/dev-tools/generate_baseline.sh @@ -7,12 +7,15 @@ # # Usage: # ./generate_baseline.sh [sha] [metallicities] +# ./generate_baseline.sh --promote [metallicities] # # Examples: -# ./generate_baseline.sh main # baseline from main, all Z +# ./generate_baseline.sh main # evolve + save baseline, all Z # ./generate_baseline.sh v2.1.0 # baseline from a release tag # ./generate_baseline.sh main abc123f # baseline from a specific commit # ./generate_baseline.sh main "" "1 0.45" # baseline for subset of Z +# ./generate_baseline.sh --promote main # promote existing outputs to baseline +# ./generate_baseline.sh --promote main "1 0.45" # promote subset of existing outputs # # Output: # baselines//baseline_Zsun.h5 — one file per metallicity @@ -21,26 +24,54 @@ set -euo pipefail +# ── Parse arguments ─────────────────────────────────────────────────────── +PROMOTE=false +if [ "${1:-}" = "--promote" ]; then + PROMOTE=true + shift +fi + BRANCH=${1:-main} -SHA=${2:-} -METALLICITIES=${3:-"2 1 0.45 0.2 0.1 0.01 0.001 0.0001"} +if [ "$PROMOTE" = true ]; then + SHA="" + METALLICITIES=${2:-"2 1 0.45 0.2 0.1 0.01 0.001 0.0001"} +else + SHA=${2:-} + METALLICITIES=${3:-"2 1 0.45 0.2 0.1 0.01 0.001 0.0001"} +fi SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" SAFE_BRANCH="${BRANCH//\//_}" BASELINE_DIR="$SCRIPT_DIR/baselines/${SAFE_BRANCH}" +CANDIDATE_DIR="$SCRIPT_DIR/outputs/${SAFE_BRANCH}" echo "============================================================" echo " POSYDON Binary Validation — Generating Baseline" echo " Branch: $BRANCH" -echo " SHA: ${SHA:-HEAD}" +if [ "$PROMOTE" = true ]; then + echo " Mode: --promote (using existing outputs)" +else + echo " SHA: ${SHA:-HEAD}" +fi echo " Metallicities: $METALLICITIES" echo " Output dir: $BASELINE_DIR" echo "============================================================" -# ── Step 1: Evolve binaries for the baseline branch ────────────────────── -echo "" -echo "Step 1: Evolving binaries on branch '$BRANCH'..." -"$SCRIPT_DIR/evolve_binaries.sh" "$BRANCH" "$SHA" "$METALLICITIES" +# ── Step 1: Evolve binaries (skip if --promote) ────────────────────────── +if [ "$PROMOTE" = true ]; then + echo "" + echo "Step 1: SKIPPED (--promote: using existing outputs in $CANDIDATE_DIR)" + + if [ ! -d "$CANDIDATE_DIR" ]; then + echo "ERROR: No outputs found at $CANDIDATE_DIR" >&2 + echo "Run evolve_binaries.sh first, or drop --promote to evolve from scratch." >&2 + exit 1 + fi +else + echo "" + echo "Step 1: Evolving binaries on branch '$BRANCH'..." + "$SCRIPT_DIR/evolve_binaries.sh" "$BRANCH" "$SHA" "$METALLICITIES" +fi # ── Step 2: Copy results into the baselines directory ──────────────────── echo "" @@ -48,7 +79,6 @@ echo "Step 2: Copying results to baseline directory..." mkdir -p "$BASELINE_DIR" -CANDIDATE_DIR="$SCRIPT_DIR/outputs/${SAFE_BRANCH}" COPIED=0 for Z in $METALLICITIES; do @@ -78,6 +108,7 @@ POSYDON Binary Validation Baseline Branch: $BRANCH Commit SHA: ${ACTUAL_SHA:-unknown} Requested SHA: ${SHA:-HEAD} +Mode: $([ "$PROMOTE" = true ] && echo "promoted from existing outputs" || echo "evolved from scratch") Generated: $(date -u '+%Y-%m-%d %H:%M:%S UTC') Metallicities: $METALLICITIES Files: $COPIED @@ -93,4 +124,4 @@ echo "============================================================" if [ $COPIED -eq 0 ]; then echo "ERROR: No baseline files were created!" >&2 exit 1 -fi +fi \ No newline at end of file From d3d578b6133848ca8cc31bdaab61d149011369f0 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 9 Mar 2026 22:04:58 +0000 Subject: [PATCH 34/91] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- dev-tools/generate_baseline.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev-tools/generate_baseline.sh b/dev-tools/generate_baseline.sh index 3539be5c81..fa407d0cbc 100755 --- a/dev-tools/generate_baseline.sh +++ b/dev-tools/generate_baseline.sh @@ -124,4 +124,4 @@ echo "============================================================" if [ $COPIED -eq 0 ]; then echo "ERROR: No baseline files were created!" >&2 exit 1 -fi \ No newline at end of file +fi From 7c553cdb28524211e557e1bb5a795dce5ef4ad22 Mon Sep 17 00:00:00 2001 From: Elizabeth Teng Date: Mon, 9 Mar 2026 17:07:02 -0500 Subject: [PATCH 35/91] Move binaries_suite.py and binaries_params.ini to dev-tools root --- dev-tools/{script_data => }/binaries_params.ini | 0 dev-tools/{script_data => }/binaries_suite.py | 0 dev-tools/evolve_binaries.sh | 2 +- 3 files changed, 1 insertion(+), 1 deletion(-) rename dev-tools/{script_data => }/binaries_params.ini (100%) rename dev-tools/{script_data => }/binaries_suite.py (100%) diff --git a/dev-tools/script_data/binaries_params.ini b/dev-tools/binaries_params.ini similarity index 100% rename from dev-tools/script_data/binaries_params.ini rename to dev-tools/binaries_params.ini diff --git a/dev-tools/script_data/binaries_suite.py b/dev-tools/binaries_suite.py similarity index 100% rename from dev-tools/script_data/binaries_suite.py rename to dev-tools/binaries_suite.py diff --git a/dev-tools/evolve_binaries.sh b/dev-tools/evolve_binaries.sh index 30f7d7b745..e6b6a90c7e 100755 --- a/dev-tools/evolve_binaries.sh +++ b/dev-tools/evolve_binaries.sh @@ -106,7 +106,7 @@ echo "šŸ“¦ Installing POSYDON" pip install -e "$CLONE_DIR" -q 2>&1 | sed 's/^/ /' # ── Run Suite for Each Metallicity ──────────────────────────────────────── -SUITE_SCRIPT="$SCRIPT_DIR/script_data/binaries_suite.py" +SUITE_SCRIPT="$SCRIPT_DIR/binaries_suite.py" FAILED=0 for Z in $METALLICITIES; do From d51fbe4d4f29a9036d89f5acac54796e981edde4 Mon Sep 17 00:00:00 2001 From: Elizabeth Teng <41969755+elizabethteng@users.noreply.github.com> Date: Mon, 9 Mar 2026 17:10:29 -0500 Subject: [PATCH 36/91] Delete dev-tools/outputs/baseline.h5 --- dev-tools/outputs/baseline.h5 | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 dev-tools/outputs/baseline.h5 diff --git a/dev-tools/outputs/baseline.h5 b/dev-tools/outputs/baseline.h5 deleted file mode 100644 index e69de29bb2..0000000000 From 6301581f34a5b7dd077c22c1949c41e697c9f435 Mon Sep 17 00:00:00 2001 From: Elizabeth Teng <41969755+elizabethteng@users.noreply.github.com> Date: Mon, 9 Mar 2026 17:14:25 -0500 Subject: [PATCH 37/91] add readme --- dev-tools/README.md | 87 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) create mode 100644 dev-tools/README.md diff --git a/dev-tools/README.md b/dev-tools/README.md new file mode 100644 index 0000000000..7732d50af1 --- /dev/null +++ b/dev-tools/README.md @@ -0,0 +1,87 @@ +# dev-tools + +Validation suite for POSYDON binary evolution. Evolves a fixed set of test binaries on a candidate branch and compares results against a stored baseline to catch regressions. + +## Quick Start + +```bash +# 1. Generate a baseline from the main branch (once) +./generate_baseline.sh main + +# 2. Validate a candidate branch against that baseline +./validate_binaries.sh feature/my-branch +``` + +## Scripts + +### `validate_binaries.sh` + +Top-level entry point. Evolves test binaries on a candidate branch, then compares results against a baseline. + +```bash +./validate_binaries.sh [baseline_branch] [metallicities] [--loose] [--rtol VALUE] [--atol VALUE] +``` + +By default, comparison is exact (rtol=0, atol=0). Use `--loose` for relaxed floating-point tolerances (rtol=1e-12, atol=1e-15), or set `--rtol`/`--atol` explicitly. + +### `generate_baseline.sh` + +Generates baseline HDF5 files from a designated branch or tag. Can also promote existing outputs to baseline with `--promote`. + +```bash +./generate_baseline.sh [sha] [metallicities] +./generate_baseline.sh --promote [metallicities] +``` + +### `evolve_binaries.sh` + +Clones a POSYDON branch, creates a conda environment, installs POSYDON, and runs the binary suite at all requested metallicities. Called by `validate_binaries.sh` and `generate_baseline.sh`; can also be run standalone. + +```bash +./evolve_binaries.sh [sha] [metallicities] +``` + +### `binaries_suite.py` + +Defines and evolves the set of 44 test binaries at a given metallicity. Each binary targets a specific edge case or past bug fix (e.g., matching failures, oRLO2 looping, SN type errors, NaN spins). Results are saved to an HDF5 file. + +```bash +python binaries_suite.py --output results.h5 --metallicity 1 +``` + +### `compare_runs.py` + +Compares two HDF5 files produced by `binaries_suite.py`. Reports three categories of differences: structural (missing binaries, step count changes, new errors), qualitative (state/event/step name changes), and quantitative (numeric value changes). + +```bash +python compare_runs.py baseline.h5 candidate.h5 [--loose] [--rtol VALUE] [--atol VALUE] [--verbose] +``` + +### `binaries_params.ini` + +Configuration file for `SimulationProperties`. Defines the POSYDON evolution steps, supernova prescriptions, common envelope parameters, and output column selections. Metallicity is overridden at runtime by `binaries_suite.py`. + +## Directory Structure + +``` +dev-tools/ +ā”œā”€ā”€ README.md +ā”œā”€ā”€ validate_binaries.sh # full validation pipeline +ā”œā”€ā”€ generate_baseline.sh # create or promote baselines +ā”œā”€ā”€ evolve_binaries.sh # clone, install, and run suite +ā”œā”€ā”€ binaries_suite.py # test binary definitions and evolution +ā”œā”€ā”€ binaries_params.ini # SimulationProperties configuration +ā”œā”€ā”€ compare_runs.py # diff two HDF5 result files +ā”œā”€ā”€ baselines/ # stored baseline HDF5 files (per branch) +ā”œā”€ā”€ outputs/ # candidate evolution results (per branch) +ā”œā”€ā”€ logs/ # per-metallicity evolution logs (per branch) +└── workdirs/ # cloned repos and conda environments (per branch) +``` + +## Available Metallicities + +The suite supports metallicities (in solar units): 2, 1, 0.45, 0.2, 0.1, 0.01, 0.001, 0.0001. All are run by default; pass a quoted subset to limit, e.g. `"1 0.45"`. + +## Authors + +Max Briel, Elizabeth Teng From 22102ea9a19af9e9ae46a29199342d8109da1558 Mon Sep 17 00:00:00 2001 From: Elizabeth Teng <41969755+elizabethteng@users.noreply.github.com> Date: Mon, 9 Mar 2026 17:17:21 -0500 Subject: [PATCH 38/91] Update README.md --- dev-tools/README.md | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/dev-tools/README.md b/dev-tools/README.md index 7732d50af1..b75aa74fc0 100644 --- a/dev-tools/README.md +++ b/dev-tools/README.md @@ -1,5 +1,3 @@ -# dev-tools - Validation suite for POSYDON binary evolution. Evolves a fixed set of test binaries on a candidate branch and compares results against a stored baseline to catch regressions. ## Quick Start @@ -16,7 +14,7 @@ Validation suite for POSYDON binary evolution. Evolves a fixed set of test binar ### `validate_binaries.sh` -Top-level entry point. Evolves test binaries on a candidate branch, then compares results against a baseline. +Top-level entry point. Evolves test binaries on a candidate branch, then compares results against an existing baseline. ```bash ./validate_binaries.sh [baseline_branch] [metallicities] [--loose] [--rtol VALUE] [--atol VALUE] @@ -77,11 +75,3 @@ dev-tools/ ā”œā”€ā”€ logs/ # per-metallicity evolution logs (per branch) └── workdirs/ # cloned repos and conda environments (per branch) ``` - -## Available Metallicities - -The suite supports metallicities (in solar units): 2, 1, 0.45, 0.2, 0.1, 0.01, 0.001, 0.0001. All are run by default; pass a quoted subset to limit, e.g. `"1 0.45"`. - -## Authors - -Max Briel, Elizabeth Teng From d0eaf915cf9f6c5ab67263acb5537facb676c1b8 Mon Sep 17 00:00:00 2001 From: Elizabeth Teng <41969755+elizabethteng@users.noreply.github.com> Date: Mon, 9 Mar 2026 17:26:14 -0500 Subject: [PATCH 39/91] Update README.md --- dev-tools/README.md | 55 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 54 insertions(+), 1 deletion(-) diff --git a/dev-tools/README.md b/dev-tools/README.md index b75aa74fc0..4b74b1b1e5 100644 --- a/dev-tools/README.md +++ b/dev-tools/README.md @@ -10,6 +10,19 @@ Validation suite for POSYDON binary evolution. Evolves a fixed set of test binar ./validate_binaries.sh feature/my-branch ``` +Results are written to `outputs//`. After validation, check: + +- `outputs//comparison_summary.txt` for a pass/fail overview across all metallicities +- `outputs//comparison_Zsun.txt` for detailed per-metallicity diff reports +- `logs//evolve_Zsun.log` for the full evolution output of each metallicity + +By default, all eight POSYDON metallicities are run. To validate only a subset, pass a quoted space-separated list as the third argument: + +```bash +./generate_baseline.sh main "" "1 0.45" +./validate_binaries.sh feature/my-branch main "1 0.45" +``` + ## Scripts ### `validate_binaries.sh` @@ -49,7 +62,13 @@ python binaries_suite.py --output results.h5 --metallicity 1 ### `compare_runs.py` -Compares two HDF5 files produced by `binaries_suite.py`. Reports three categories of differences: structural (missing binaries, step count changes, new errors), qualitative (state/event/step name changes), and quantitative (numeric value changes). +Compares two HDF5 files produced by `binaries_suite.py` and reports differences in three categories: + +- **Structural**: missing or extra binaries, evolution step count changes, binaries that newly fail or newly pass, missing HDF5 tables. +- **Qualitative**: changes to categorical columns such as state, event, step name, SN type, interpolation class, and mass transfer history. +- **Quantitative**: changes to any numeric column. By default, comparison is exact (bitwise identical floats). Use `--loose` for slightly relaxed tolerances (rtol=1e-12, atol=1e-15), or set `--rtol`/`--atol` explicitly. + +The script also compares warning and error tables, reporting new, removed, or changed warnings per binary. ```bash python compare_runs.py baseline.h5 candidate.h5 [--loose] [--rtol VALUE] [--atol VALUE] [--verbose] @@ -59,6 +78,40 @@ python compare_runs.py baseline.h5 candidate.h5 [--loose] [--rtol VALUE] [--atol Configuration file for `SimulationProperties`. Defines the POSYDON evolution steps, supernova prescriptions, common envelope parameters, and output column selections. Metallicity is overridden at runtime by `binaries_suite.py`. +## Running Scripts Manually + +The shell scripts handle cloning, environment setup, and orchestration. If you already have POSYDON installed in your current environment, you can run the Python scripts directly. + +### Evolving binaries + +```bash +# Evolve all 44 test binaries at solar metallicity +python binaries_suite.py --output my_results.h5 --metallicity 1 + +# Evolve at a specific metallicity with verbose output +python binaries_suite.py --output my_results.h5 --metallicity 0.01 --verbose + +# Use a custom ini file +python binaries_suite.py --output my_results.h5 --metallicity 1 --ini /path/to/custom.ini +``` + +The output HDF5 contains three tables: `evolution` (per-step binary data), `errors` (binaries that failed), and `warnings` (warnings raised during evolution). + +### Comparing two result files + +```bash +# Exact comparison +python compare_runs.py file_a.h5 file_b.h5 + +# Relaxed tolerances +python compare_runs.py file_a.h5 file_b.h5 --loose + +# Custom tolerances with verbose diagnostics +python compare_runs.py file_a.h5 file_b.h5 --rtol 1e-8 --atol 1e-12 --verbose +``` + +The two files do not need to come from the shell pipeline; any pair of HDF5 files produced by `binaries_suite.py` can be compared. + ## Directory Structure ``` From 4c9643548d996bde08d6ffec5c6831e5cd468269 Mon Sep 17 00:00:00 2001 From: Elizabeth Teng <41969755+elizabethteng@users.noreply.github.com> Date: Thu, 18 Dec 2025 07:52:22 -0600 Subject: [PATCH 40/91] Create validate_binaries.sh --- dev-tools/validate_binaries.sh | 1 + 1 file changed, 1 insertion(+) create mode 100644 dev-tools/validate_binaries.sh diff --git a/dev-tools/validate_binaries.sh b/dev-tools/validate_binaries.sh new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/dev-tools/validate_binaries.sh @@ -0,0 +1 @@ + From 73e14659c30a05d49f73f8a427ae4cf2f2b11f5c Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Thu, 18 Dec 2025 13:52:47 +0000 Subject: [PATCH 41/91] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- dev-tools/validate_binaries.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/dev-tools/validate_binaries.sh b/dev-tools/validate_binaries.sh index 8b13789179..e69de29bb2 100644 --- a/dev-tools/validate_binaries.sh +++ b/dev-tools/validate_binaries.sh @@ -1 +0,0 @@ - From ebc2c8681346d6044b19c3a92b5179d7febb675d Mon Sep 17 00:00:00 2001 From: Elizabeth Teng <41969755+elizabethteng@users.noreply.github.com> Date: Thu, 18 Dec 2025 08:10:24 -0600 Subject: [PATCH 42/91] Create dummy file baseline.h5 --- dev-tools/outputs/baseline.h5 | 1 + 1 file changed, 1 insertion(+) create mode 100644 dev-tools/outputs/baseline.h5 diff --git a/dev-tools/outputs/baseline.h5 b/dev-tools/outputs/baseline.h5 new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/dev-tools/outputs/baseline.h5 @@ -0,0 +1 @@ + From e416fc8585e352aa5cf7fffb6779e8f80fd668af Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Thu, 18 Dec 2025 14:10:32 +0000 Subject: [PATCH 43/91] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- dev-tools/outputs/baseline.h5 | 1 - 1 file changed, 1 deletion(-) diff --git a/dev-tools/outputs/baseline.h5 b/dev-tools/outputs/baseline.h5 index 8b13789179..e69de29bb2 100644 --- a/dev-tools/outputs/baseline.h5 +++ b/dev-tools/outputs/baseline.h5 @@ -1 +0,0 @@ - From 47a0d37f1c05d6854bdfcd8084fe9892407125cc Mon Sep 17 00:00:00 2001 From: Elizabeth Teng <41969755+elizabethteng@users.noreply.github.com> Date: Thu, 18 Dec 2025 08:20:43 -0600 Subject: [PATCH 44/91] outline script --- dev-tools/validate_binaries.sh | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/dev-tools/validate_binaries.sh b/dev-tools/validate_binaries.sh index e69de29bb2..436b55647c 100644 --- a/dev-tools/validate_binaries.sh +++ b/dev-tools/validate_binaries.sh @@ -0,0 +1,29 @@ +#!/bin/bash + +# A script for validating the outputs of 100 binaries, +# which can be compared to a baseline to monitor changes to the code. + +# script usage: ./validate_binaries.sh --branch candidate-branch + +# run candidate binaries and save to file +# ./evolve_binaries.sh +# save to file + +# evaluate tolerance for quantitative values + +# evaluate qualitative differences + +# warnings and error tracking + +# structured output + +# compare +# python compare_runs.py baseline.json candidate.json + + + + + +# outputs/baseline.h5 +# outputs/candidate_branchname.h5 +# outputs/comparison_branchname.txt From ed95ed7f006f2b7545914577e44b8e985d497fc8 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Thu, 18 Dec 2025 14:20:52 +0000 Subject: [PATCH 45/91] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- dev-tools/validate_binaries.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev-tools/validate_binaries.sh b/dev-tools/validate_binaries.sh index 436b55647c..31b7c6d72a 100644 --- a/dev-tools/validate_binaries.sh +++ b/dev-tools/validate_binaries.sh @@ -1,6 +1,6 @@ #!/bin/bash -# A script for validating the outputs of 100 binaries, +# A script for validating the outputs of 100 binaries, # which can be compared to a baseline to monitor changes to the code. # script usage: ./validate_binaries.sh --branch candidate-branch From 578cd4c8a4137c9809bec839ae8de27e0febac2e Mon Sep 17 00:00:00 2001 From: Elizabeth Teng <41969755+elizabethteng@users.noreply.github.com> Date: Thu, 18 Dec 2025 08:28:17 -0600 Subject: [PATCH 46/91] Modify evolve_binaries.sh for saved output and logs in folder outputs --- dev-tools/evolve_binaries.sh | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/dev-tools/evolve_binaries.sh b/dev-tools/evolve_binaries.sh index fc7a20fb3b..051dafcd13 100755 --- a/dev-tools/evolve_binaries.sh +++ b/dev-tools/evolve_binaries.sh @@ -28,6 +28,15 @@ mkdir -p "$WORK_DIR" FULL_PATH="$(realpath "$WORK_DIR")" CLONE_DIR="$FULL_PATH/POSYDON" +OUTPUT_DIR="$FULL_PATH/outputs" +LOG_DIR="$FULL_PATH/logs" + +SAFE_BRANCH="${BRANCH//\//_}" +OUTPUT_FILE="$OUTPUT_DIR/candidate_${SAFE_BRANCH}.h5" +LOG_FILE="$LOG_DIR/evolve_${SAFE_BRANCH}.log" + +mkdir -p "$OUTPUT_DIR" "$LOG_DIR" + echo "šŸ“‹ Copying script_data folder" # copy the script_data folder cp -r "./script_data" "$WORK_DIR" @@ -79,6 +88,11 @@ pip install -e "$CLONE_DIR" -q 2>&1 | sed 's/^/ /' echo "šŸš€ Running evolve_binaries.py" # # Run the Python script and capture output (stdout and stderr) -python script_data/1Zsun_binaries_suite.py > $FULL_PATH/evolve_binaries_$BRANCH.out 2>&1 +python script_data/1Zsun_binaries_suite.py --output "$OUTPUT_FILE" > "$LOG_FILE" 2>&1 + +if [ ! -f "$OUTPUT_FILE" ]; then + echo "ERROR: Results file was not created: $OUTPUT_FILE" + exit 2 +fi -echo -e "āœ… Script completed. Output saved to \n$FULL_PATH/evolve_binaries_$BRANCH.out" +echo -e "āœ… Script completed. Output saved to \n$OUTPUT_FILE" From e4908e0c25bc9632e50c53ab09483843407fe95b Mon Sep 17 00:00:00 2001 From: Elizabeth Teng <41969755+elizabethteng@users.noreply.github.com> Date: Thu, 18 Dec 2025 08:57:20 -0600 Subject: [PATCH 47/91] Modify evolve_binary for HDF5 output and error handling --- dev-tools/script_data/1Zsun_binaries_suite.py | 63 ++++++++++++------- 1 file changed, 39 insertions(+), 24 deletions(-) diff --git a/dev-tools/script_data/1Zsun_binaries_suite.py b/dev-tools/script_data/1Zsun_binaries_suite.py index a896df8fe9..53c4010a76 100644 --- a/dev-tools/script_data/1Zsun_binaries_suite.py +++ b/dev-tools/script_data/1Zsun_binaries_suite.py @@ -116,7 +116,15 @@ def print_failed_binary(binary,e, max_error_lines=3): print("-" * line_length) -def evolve_binary(binary): +def evolve_binary(binary,h5file,binary_id): + """ + Evolves a single binary, prints its evolution, and saves to HDF5. + + Args: + binary: BinaryStar object + h5file: open h5py.File object for writing + binary_id: unique identifier for this binary + """ # Capture warnings during evolution captured_warnings = [] @@ -137,44 +145,49 @@ def warning_handler(message, category, filename, lineno, file=None, line=None): binary.evolve() # Display the evolution summary for successful evolution write_binary_to_screen(binary) - - # Show warnings if any were captured - if captured_warnings: - print(f"āš ļø {len(captured_warnings)} warning(s) raised during evolution:") - for i, warning in enumerate(captured_warnings[:3], 1): # Show max 3 warnings - print(f" {i}. {warning['category']}: {warning['message']}") - if len(captured_warnings) > 3: - print(f" ... and {len(captured_warnings) - 3} more warning(s)") - elif len(captured_warnings) <= 3: - for i in range(4-len(captured_warnings)): - print("") - else: - print(f"No warning(s) raised during evolution\n\n\n\n") - print("=" * line_length) + + # Save to HDF5 + df = binary.to_df(**{'extra_columns':{'step_names':'str'}}) + grp = h5file.create_group(f"binary_{binary_id}") + for col in df.columns: + grp.create_dataset(col, data=df[col].values) except Exception as e: - # turn off binary alarm in case of exception signal.alarm(0) print_failed_binary(binary, e) - # Show warnings if any were captured before the exception + err_grp = h5file.require_group(f"binary_{binary_id}/errors") + err_grp.attrs['exception_type'] = type(e).__name__ + err_grp.attrs['exception_message'] = str(e) + + finally: + # Always turn off binary alarm and restore warning handler + signal.alarm(0) + warnings.showwarning = old_showwarning + + # ensure binary group exists + grp = h5file.require_group(f"binary_{binary_id}") + + # Save warnings to h5 file if captured_warnings: - print(f"\nāš ļø {len(captured_warnings)} warning(s) raised before failure:") + warn_grp = grp.create_group("warnings") + for i, warning in enumerate(captured_warnings): + warn_subgrp = warn_grp.create_group(f"warning_{i}") + warn_subgrp.attrs['category'] = warning['category'] + warn_subgrp.attrs['message'] = warning['message'] + warn_subgrp.attrs['filename'] = warning['filename'] + warn_subgrp.attrs['lineno'] = warning['lineno'] + + print(f"āš ļø {len(captured_warnings)} warning(s) raised during evolution:") for i, warning in enumerate(captured_warnings[:3], 1): # Show max 3 warnings print(f" {i}. {warning['category']}: {warning['message']}") if len(captured_warnings) > 3: print(f" ... and {len(captured_warnings) - 3} more warning(s)") else: print(f"No warning(s) raised during evolution\n\n\n\n") - print("=" * line_length) - finally: - # Always turn off binary alarm and restore warning handler - signal.alarm(0) - warnings.showwarning = old_showwarning - def evolve_binaries(verbose): """Evolves a few binaries to validate their output @@ -833,6 +846,8 @@ def evolve_binaries(verbose): parser = argparse.ArgumentParser(description='Evolve binaries for validation.') parser.add_argument('--verbose', '-v', action='store_true', default=False, help='Enable verbose output (default: False)') + parser.add_argument("--output", type=str, required=True, + help="Path to save HDF5 output") args = parser.parse_args() evolve_binaries(verbose=args.verbose) From dc65854079bc7ccdbd1a2c65606f05d6c23bf786 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Thu, 18 Dec 2025 14:57:38 +0000 Subject: [PATCH 48/91] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- dev-tools/script_data/1Zsun_binaries_suite.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/dev-tools/script_data/1Zsun_binaries_suite.py b/dev-tools/script_data/1Zsun_binaries_suite.py index 53c4010a76..6e734e3352 100644 --- a/dev-tools/script_data/1Zsun_binaries_suite.py +++ b/dev-tools/script_data/1Zsun_binaries_suite.py @@ -145,7 +145,7 @@ def warning_handler(message, category, filename, lineno, file=None, line=None): binary.evolve() # Display the evolution summary for successful evolution write_binary_to_screen(binary) - + # Save to HDF5 df = binary.to_df(**{'extra_columns':{'step_names':'str'}}) grp = h5file.create_group(f"binary_{binary_id}") @@ -166,10 +166,10 @@ def warning_handler(message, category, filename, lineno, file=None, line=None): # Always turn off binary alarm and restore warning handler signal.alarm(0) warnings.showwarning = old_showwarning - + # ensure binary group exists grp = h5file.require_group(f"binary_{binary_id}") - + # Save warnings to h5 file if captured_warnings: warn_grp = grp.create_group("warnings") @@ -179,7 +179,7 @@ def warning_handler(message, category, filename, lineno, file=None, line=None): warn_subgrp.attrs['message'] = warning['message'] warn_subgrp.attrs['filename'] = warning['filename'] warn_subgrp.attrs['lineno'] = warning['lineno'] - + print(f"āš ļø {len(captured_warnings)} warning(s) raised during evolution:") for i, warning in enumerate(captured_warnings[:3], 1): # Show max 3 warnings print(f" {i}. {warning['category']}: {warning['message']}") @@ -846,7 +846,7 @@ def evolve_binaries(verbose): parser = argparse.ArgumentParser(description='Evolve binaries for validation.') parser.add_argument('--verbose', '-v', action='store_true', default=False, help='Enable verbose output (default: False)') - parser.add_argument("--output", type=str, required=True, + parser.add_argument("--output", type=str, required=True, help="Path to save HDF5 output") args = parser.parse_args() From 8a0d5bae1999146aee269305559eabd8433ed582 Mon Sep 17 00:00:00 2001 From: Elizabeth Teng <41969755+elizabethteng@users.noreply.github.com> Date: Thu, 18 Dec 2025 09:18:58 -0600 Subject: [PATCH 49/91] Update 1Zsun_binaries_suite.py to fix args in function calls --- dev-tools/script_data/1Zsun_binaries_suite.py | 1172 +++++++++-------- 1 file changed, 604 insertions(+), 568 deletions(-) diff --git a/dev-tools/script_data/1Zsun_binaries_suite.py b/dev-tools/script_data/1Zsun_binaries_suite.py index 6e734e3352..c18d2009fd 100644 --- a/dev-tools/script_data/1Zsun_binaries_suite.py +++ b/dev-tools/script_data/1Zsun_binaries_suite.py @@ -116,7 +116,7 @@ def print_failed_binary(binary,e, max_error_lines=3): print("-" * line_length) -def evolve_binary(binary,h5file,binary_id): +def evolve_binary(binary, h5file, binary_id): """ Evolves a single binary, prints its evolution, and saves to HDF5. @@ -189,588 +189,624 @@ def warning_handler(message, category, filename, lineno, file=None, line=None): print(f"No warning(s) raised during evolution\n\n\n\n") print("=" * line_length) -def evolve_binaries(verbose): +def evolve_binaries(verbose,output_path): """Evolves a few binaries to validate their output """ sim_prop = load_inlist(verbose) - ######################################## - # Failing binary in matching - ######################################## - star_1 = SingleStar(**{'mass': 11.948472796094759, 'state': 'H-rich_Core_H_burning','metallicity':1, - 'natal_kick_array': [231.97383621190582, 5.927334890264575, 1.5990566013567014, 6.137994236518587]}) - star_2 = SingleStar(**{'mass': 7.636958434479617, 'state': 'H-rich_Core_H_burning','metallicity':1, - 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) - binary = BinaryStar(star_1, star_2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', - 'orbital_period': 190925.99636740884,'eccentricity': 0.0}, properties = sim_prop) - evolve_binary(binary) - ######################################## - # Failing binary in matching - ######################################## - star_1 = SingleStar(**{'mass': 30.169861921689556, 'state': 'H-rich_Core_H_burning','metallicity':1, - 'natal_kick_array': [77.96834852144123, 0.05021460132555987, 2.3146518208348152, 1.733054979982291]}) - star_2 = SingleStar(**{'mass': 10.972734402996027, 'state': 'H-rich_Core_H_burning','metallicity':1, - 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) - binary = BinaryStar(star_1, star_2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', - 'orbital_period': 20479.71919353725,'eccentricity': 0.0}, properties = sim_prop) - evolve_binary(binary) - ######################################## - # flipped S1 and S2 ? - ######################################## - star_1 = SingleStar(**{'mass': 9.474917413943635, 'state': 'H-rich_Core_H_burning','metallicity':1, - 'natal_kick_array': [133.5713935237759, 4.398754864537542, 2.703102872841114, 1.4633904612711142]}) - star_2 = SingleStar(**{'mass': 9.311073918196263, 'state': 'H-rich_Core_H_burning','metallicity':1, - 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) - binary = BinaryStar(star_1, star_2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', - 'orbital_period': 18.605997832086413,'eccentricity': 0.0}, properties = sim_prop) + with h5py.File(output_path,'w') as h5file: + binary_id=0 - evolve_binary(binary) - ######################################## - # flipped S1 and S2 - ######################################## - star_1 = SingleStar(**{'mass': 10.438541, 'state': 'H-rich_Core_H_burning','metallicity':1, - 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) - star_2 = SingleStar(**{'mass': 1.400713, 'state': 'H-rich_Core_H_burning','metallicity':1, - 'natal_kick_array': [0.0, 4.190728383757787, 1.1521129697118118, 5.015343794234789]}) - binary = BinaryStar(star_1, star_2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', - 'orbital_period': 9.824025,'eccentricity': 0.0}, properties = sim_prop) - evolve_binary(binary) - ######################################## - # flipped S1 and S2 - ######################################## - star_1= SingleStar(**{'mass': 9.845907 , 'state': 'H-rich_Core_H_burning','metallicity':1, - 'natal_kick_array': [0.0, 4.190728383757787, 1.1521129697118118, 5.015343794234789]}) - star_2 = SingleStar(**{'mass': 9.611029, 'state': 'H-rich_Core_H_burning','metallicity':1, - 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) - binary = BinaryStar(star_1, star_2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', - 'orbital_period': 3.820571,'eccentricity': 0.0}, properties = sim_prop) - evolve_binary(binary) - ######################################## - # Normal binary evolution - ######################################## - star_1= SingleStar(**{'mass': 30.845907 , 'state': 'H-rich_Core_H_burning','metallicity':1, - 'natal_kick_array': [0.0, 4.190728383757787, 1.1521129697118118, 5.015343794234789]}) - star_2 = SingleStar(**{'mass': 30.611029, 'state': 'H-rich_Core_H_burning','metallicity':1, - 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) - binary = BinaryStar(star_1, star_2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', - 'orbital_period': 30.820571,'eccentricity': 0.0}, properties = sim_prop) - evolve_binary(binary) - ######################################## - # Normal binary - ######################################## - star_1= SingleStar(**{'mass': 9.213534679594247 , 'state': 'H-rich_Core_H_burning','metallicity':1, - 'natal_kick_array': [327.5906384501521, 1.7707176050073297, 1.573225822966838, 1.6757313876001914]}) - star_2 = SingleStar(**{'mass': 7.209878522799272, 'state': 'H-rich_Core_H_burning','metallicity':1, - 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) - binary = BinaryStar(star_1, star_2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', - 'orbital_period': 63123.74544474666,'eccentricity': 0.0}, properties = sim_prop) - evolve_binary(binary) - ######################################## - # Normal binary - ######################################## - star_1= SingleStar(**{'mass': 9.561158487732602 , 'state': 'H-rich_Core_H_burning','metallicity':1, - 'natal_kick_array': [317.5423844462847, 2.9095984678057603, 1.754121288652108, 2.3693917842468784]}) - star_2 = SingleStar(**{'mass': 9.382732464319286, 'state': 'H-rich_Core_H_burning','metallicity':1, - 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) - binary = BinaryStar(star_1, star_2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', - 'orbital_period': 27.77657038557851,'eccentricity': 0.0}, properties = sim_prop) - evolve_binary(binary) - ######################################## - # Normal binary - ######################################## - star1 = SingleStar(**{'mass': 7.552858,#29829485, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array': [40.91509926587841, 2.6295454150818256, 1.6718337470964977, 6.0408769315244895]}) - star2 = SingleStar(**{'mass': 6.742063, #481560266, - 'state': 'H-rich_Core_H_burning', + ######################################## + # Failing binary in matching + ######################################## + star_1 = SingleStar(**{'mass': 11.948472796094759, 'state': 'H-rich_Core_H_burning','metallicity':1, + 'natal_kick_array': [231.97383621190582, 5.927334890264575, 1.5990566013567014, 6.137994236518587]}) + star_2 = SingleStar(**{'mass': 7.636958434479617, 'state': 'H-rich_Core_H_burning','metallicity':1, 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) - binary = BinaryStar(star1, star2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', - 'orbital_period': 17.957531550841225, 'eccentricity': 0.0,}, - properties=sim_prop) - evolve_binary(binary) - ######################################## - # High BH spin options - ######################################## - star_1 = SingleStar(**{'mass': 31.616785, 'state': 'H-rich_Core_H_burning', - 'natal_kick_array': [10, 4.190728383757787, 1.1521129697118118, 5.015343794234789]}) - star_2 = SingleStar(**{'mass': 26.874267, 'state': 'H-rich_Core_H_burning', - 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) - binary = BinaryStar(star_1, star_2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', - 'orbital_period': 501.99252706449792,'eccentricity': 0.0}, properties = sim_prop) - evolve_binary(binary) - ######################################## - # Original a>1 spin error - ######################################## - star_1 = SingleStar(**{'mass': 18.107506844123645, 'state': 'H-rich_Core_H_burning', - 'natal_kick_array': [528.2970725443025, 4.190728383757787, 1.1521129697118118, 5.015343794234789]}) - star_2 = SingleStar(**{'mass': 15.641392951875442, 'state': 'H-rich_Core_H_burning', - 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) - binary = BinaryStar(star_1, star_2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', - 'orbital_period': 151.99252706449792,'eccentricity': 0.0}, properties = sim_prop) - ######################################## - # FIXED disrupted crash - ######################################## - STAR1 = SingleStar(**{'mass': 52.967313, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) - STAR2 = SingleStar(**{'mass': 36.306444, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) - BINARY = BinaryStar(STAR1, STAR2, - **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':12.877004, 'eccentricity': 0.0}, - properties = sim_prop) - evolve_binary(BINARY) - ######################################## - # FIXED error with SN type - ######################################## - STAR1 = SingleStar(**{'mass': 17.782576, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) - STAR2 = SingleStar(**{'mass':3.273864, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) - BINARY = BinaryStar(STAR1, STAR2, - **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':4513.150157, 'eccentricity': 0.0}, - properties = sim_prop) - evolve_binary(BINARY) - ######################################## - # FIXED oRLO2 looping - ######################################## - STAR1 = SingleStar(**{'mass': 170.638207, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array': [4.921294, 4.31745, 1.777768, 3.509656]}) - STAR2 = SingleStar(**{'mass':37.917852, - 'state': 'H-rich_Core_H_burning', + binary = BinaryStar(star_1, star_2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', + 'orbital_period': 190925.99636740884,'eccentricity': 0.0}, properties = sim_prop) + evolve_binary(binary, h5file, binary_id) + binary_id+=1 + ######################################## + # Failing binary in matching + ######################################## + star_1 = SingleStar(**{'mass': 30.169861921689556, 'state': 'H-rich_Core_H_burning','metallicity':1, + 'natal_kick_array': [77.96834852144123, 0.05021460132555987, 2.3146518208348152, 1.733054979982291]}) + star_2 = SingleStar(**{'mass': 10.972734402996027, 'state': 'H-rich_Core_H_burning','metallicity':1, 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) - - BINARY = BinaryStar(STAR1, STAR2, - **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':113.352736, 'eccentricity': 0.0}, - properties = sim_prop) - evolve_binary(BINARY) - ######################################## - # Redirect to step_CO_HeMS (H-rich non-burning?) - ######################################## - star_1 = SingleStar(**{'mass': 8.333579, 'state': 'H-rich_Core_H_burning',\ - 'natal_kick_array': [17.125568, 4.101834, 0.917541, 3.961291]}) - star_2 = SingleStar(**{'mass' : 8.208376, 'state' : 'H-rich_Core_H_burning', - 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - binary = BinaryStar(star_1, star_2, - **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period': 66.870417, 'eccentricity': 0.0}, - properties = sim_prop) - evolve_binary(binary) - ######################################## - # FIXED oRLO2 looping - ######################################## - star_1 = SingleStar(**{'mass': 16.921378, 'state': 'H-rich_Core_H_burning',\ - 'natal_kick_array': [268.837139, 5.773527, 2.568105, 2.519068]}) - star_2 = SingleStar(**{'mass' : 16.286318, 'state' : 'H-rich_Core_H_burning', - 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - binary = BinaryStar(star_1, star_2, - **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period': 37.958768, 'eccentricity': 0.0}, - properties = sim_prop) - evolve_binary(binary) - ######################################## - # FIXED? step_detached failure - ######################################## - STAR1 = SingleStar(**{'mass': 19.787769, 'state': 'H-rich_Core_H_burning', - 'natal_kick_array': [24.464803, 0.666314, 1.954698, 5.598975]}) - STAR2 = SingleStar(**{'mass': 7.638741, 'state': 'H-rich_Core_H_burning', - 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - BINARY = BinaryStar(STAR1, STAR2, - **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':3007.865561, 'eccentricity': 0.0}, - properties = sim_prop) - evolve_binary(BINARY) - ######################################## - # Disrupted binary - ######################################## - star_1 = SingleStar(**{'mass': 16.921378, 'state': 'H-rich_Core_H_burning',\ - 'natal_kick_array': [268.837139, 5.773527, 2.568105, 2.519068]}) - star_2 = SingleStar(**{'mass' : 16.286318, 'state' : 'H-rich_Core_H_burning', - 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - - BINARY = BinaryStar(star_1, star_2, - **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':3007.865561, 'eccentricity': 0.0}, - properties = sim_prop) - evolve_binary(BINARY) - ######################################## - # FIXED Detached binary failure (low mass) - ######################################## - STAR1 = SingleStar(**{'mass': 9, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - STAR2 = SingleStar(**{'mass':0.8, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - - BINARY = BinaryStar(STAR1, STAR2, - **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':4513.150157, 'eccentricity': 0.0}, - properties = sim_prop) - evolve_binary(BINARY) - ######################################## - # FIXED SN_TYPE = None crash - ######################################## - STAR1 = SingleStar(**{'mass': 17.782576, + binary = BinaryStar(star_1, star_2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', + 'orbital_period': 20479.71919353725,'eccentricity': 0.0}, properties = sim_prop) + evolve_binary(binary, h5file, binary_id) + binary_id+=1 + ######################################## + # flipped S1 and S2 ? + ######################################## + star_1 = SingleStar(**{'mass': 9.474917413943635, 'state': 'H-rich_Core_H_burning','metallicity':1, + 'natal_kick_array': [133.5713935237759, 4.398754864537542, 2.703102872841114, 1.4633904612711142]}) + star_2 = SingleStar(**{'mass': 9.311073918196263, 'state': 'H-rich_Core_H_burning','metallicity':1, + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) + binary = BinaryStar(star_1, star_2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', + 'orbital_period': 18.605997832086413,'eccentricity': 0.0}, properties = sim_prop) + + evolve_binary(binary, h5file, binary_id) + binary_id+=1 + ######################################## + # flipped S1 and S2 + ######################################## + star_1 = SingleStar(**{'mass': 10.438541, 'state': 'H-rich_Core_H_burning','metallicity':1, + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) + star_2 = SingleStar(**{'mass': 1.400713, 'state': 'H-rich_Core_H_burning','metallicity':1, + 'natal_kick_array': [0.0, 4.190728383757787, 1.1521129697118118, 5.015343794234789]}) + binary = BinaryStar(star_1, star_2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', + 'orbital_period': 9.824025,'eccentricity': 0.0}, properties = sim_prop) + evolve_binary(binary, h5file, binary_id) + binary_id+=1 + ######################################## + # flipped S1 and S2 + ######################################## + star_1= SingleStar(**{'mass': 9.845907 , 'state': 'H-rich_Core_H_burning','metallicity':1, + 'natal_kick_array': [0.0, 4.190728383757787, 1.1521129697118118, 5.015343794234789]}) + star_2 = SingleStar(**{'mass': 9.611029, 'state': 'H-rich_Core_H_burning','metallicity':1, + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) + binary = BinaryStar(star_1, star_2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', + 'orbital_period': 3.820571,'eccentricity': 0.0}, properties = sim_prop) + evolve_binary(binary, h5file, binary_id) + binary_id+=1 + ######################################## + # Normal binary evolution + ######################################## + star_1= SingleStar(**{'mass': 30.845907 , 'state': 'H-rich_Core_H_burning','metallicity':1, + 'natal_kick_array': [0.0, 4.190728383757787, 1.1521129697118118, 5.015343794234789]}) + star_2 = SingleStar(**{'mass': 30.611029, 'state': 'H-rich_Core_H_burning','metallicity':1, + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) + binary = BinaryStar(star_1, star_2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', + 'orbital_period': 30.820571,'eccentricity': 0.0}, properties = sim_prop) + evolve_binary(binary, h5file, binary_id) + binary_id+=1 + ######################################## + # Normal binary + ######################################## + star_1= SingleStar(**{'mass': 9.213534679594247 , 'state': 'H-rich_Core_H_burning','metallicity':1, + 'natal_kick_array': [327.5906384501521, 1.7707176050073297, 1.573225822966838, 1.6757313876001914]}) + star_2 = SingleStar(**{'mass': 7.209878522799272, 'state': 'H-rich_Core_H_burning','metallicity':1, + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) + binary = BinaryStar(star_1, star_2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', + 'orbital_period': 63123.74544474666,'eccentricity': 0.0}, properties = sim_prop) + evolve_binary(binary, h5file, binary_id) + binary_id+=1 + ######################################## + # Normal binary + ######################################## + star_1= SingleStar(**{'mass': 9.561158487732602 , 'state': 'H-rich_Core_H_burning','metallicity':1, + 'natal_kick_array': [317.5423844462847, 2.9095984678057603, 1.754121288652108, 2.3693917842468784]}) + star_2 = SingleStar(**{'mass': 9.382732464319286, 'state': 'H-rich_Core_H_burning','metallicity':1, + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) + binary = BinaryStar(star_1, star_2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', + 'orbital_period': 27.77657038557851,'eccentricity': 0.0}, properties = sim_prop) + evolve_binary(binary, h5file, binary_id) + binary_id+=1 + ######################################## + # Normal binary + ######################################## + star1 = SingleStar(**{'mass': 7.552858,#29829485, + 'state': 'H-rich_Core_H_burning', + 'natal_kick_array': [40.91509926587841, 2.6295454150818256, 1.6718337470964977, 6.0408769315244895]}) + star2 = SingleStar(**{'mass': 6.742063, #481560266, + 'state': 'H-rich_Core_H_burning', + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) + binary = BinaryStar(star1, star2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', + 'orbital_period': 17.957531550841225, 'eccentricity': 0.0,}, + properties=sim_prop) + evolve_binary(binary, h5file, binary_id) + binary_id+=1 + ######################################## + # High BH spin options + ######################################## + star_1 = SingleStar(**{'mass': 31.616785, 'state': 'H-rich_Core_H_burning', + 'natal_kick_array': [10, 4.190728383757787, 1.1521129697118118, 5.015343794234789]}) + star_2 = SingleStar(**{'mass': 26.874267, 'state': 'H-rich_Core_H_burning', + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) + binary = BinaryStar(star_1, star_2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', + 'orbital_period': 501.99252706449792,'eccentricity': 0.0}, properties = sim_prop) + evolve_binary(binary, h5file, binary_id) + binary_id+=1 + ######################################## + # Original a>1 spin error + ######################################## + star_1 = SingleStar(**{'mass': 18.107506844123645, 'state': 'H-rich_Core_H_burning', + 'natal_kick_array': [528.2970725443025, 4.190728383757787, 1.1521129697118118, 5.015343794234789]}) + star_2 = SingleStar(**{'mass': 15.641392951875442, 'state': 'H-rich_Core_H_burning', + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) + binary = BinaryStar(star_1, star_2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', + 'orbital_period': 151.99252706449792,'eccentricity': 0.0}, properties = sim_prop) + evolve_binary(binary, h5file, binary_id) + binary_id+=1 + ######################################## + # FIXED disrupted crash + ######################################## + star1 = SingleStar(**{'mass': 52.967313, + 'state': 'H-rich_Core_H_burning', + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) + star2 = SingleStar(**{'mass': 36.306444, + 'state': 'H-rich_Core_H_burning', + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) + binary = BinaryStar(star1, star2, + **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':12.877004, 'eccentricity': 0.0}, + properties = sim_prop) + evolve_binary(binary, h5file, binary_id) + binary_id+=1 + ######################################## + # FIXED error with SN type + ######################################## + star1 = SingleStar(**{'mass': 17.782576, 'state': 'H-rich_Core_H_burning', - 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - STAR2 = SingleStar(**{'mass':3.273864, + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) + star2 = SingleStar(**{'mass':3.273864, 'state': 'H-rich_Core_H_burning', - 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - - BINARY = BinaryStar(STAR1, STAR2, + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) + binary = BinaryStar(star1, star2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':4513.150157, 'eccentricity': 0.0}, properties = sim_prop) - evolve_binary(BINARY) - ######################################## - # FIXED SN_TYPE errors - ######################################## - STAR1 = SingleStar(**{'mass': 6.782576, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - STAR2 = SingleStar(**{'mass':3.273864, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - - BINARY = BinaryStar(STAR1, STAR2, - **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':4513.150157, 'eccentricity': 0.0}, - properties = sim_prop) - evolve_binary(BINARY) - ######################################## - # FIXED SN_TYPE errors - ######################################## - STAR1 = SingleStar(**{'mass': 40.638207, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array': [30.921294, 4.31745, 1.777768, 3.509656]}) - STAR2 = SingleStar(**{'mass':37.917852, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - - BINARY = BinaryStar(STAR1, STAR2, - **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':2113.352736, 'eccentricity': 0.0}, - properties = sim_prop) - evolve_binary(BINARY) - ######################################## - # FIXED ECSN errors? - ######################################## - STAR1 = SingleStar(**{'mass': 12.376778, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array': [80, 4.31745, 1.777768, 3.509656]}) - STAR2 = SingleStar(**{'mass': 9.711216, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - - - BINARY = BinaryStar(STAR1, STAR2, - **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':79.83702, 'eccentricity': 0.0}, - properties = sim_prop) - evolve_binary(BINARY) - ######################################## - # Interpolator masses?? - ######################################## - STAR1 = SingleStar(**{'mass': 7.592921, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - STAR2 = SingleStar(**{'mass':5.038679 , - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - - BINARY = BinaryStar(STAR1, STAR2, - **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':5.537807, 'eccentricity': 0.0}, - properties = sim_prop) - evolve_binary(BINARY) - ######################################## - # Interpolator masses? - ######################################## - star_1 = SingleStar(**{'mass': 38.741115, - 'state': 'H-rich_Core_H_burning',\ - 'natal_kick_array': [21.113771, 2.060135, 2.224789, 4.089729]}) - star_2 = SingleStar(**{'mass': 27.776178, - 'state': 'H-rich_Core_H_burning',\ - 'natal_kick_array': [282.712103, 0.296252, 1.628433, 5.623812]}) - - BINARY = BinaryStar(star_1, star_2, - **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period': 93.387072, 'eccentricity': 0.0}, - properties = sim_prop) - evolve_binary(BINARY) - ######################################## - # FIXED NaN spin - ######################################## - STAR1 = SingleStar(**{'mass': 70.066924, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array':[0.0, 0.0, 0.0, 0.0], - 'metallicity':1}) - STAR2 = SingleStar(**{'mass': 34.183110, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array':[0.0, 0.0, 0.0, 0.0], - 'metallicity':1}) - BINARY = BinaryStar(STAR1, STAR2, - **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':5.931492e+03, - 'separation': orbital_separation_from_period(5.931492e+03, STAR1.mass, STAR2.mass), - 'eccentricity': 0.0}, - properties = sim_prop) - evolve_binary(BINARY) - ######################################## - # FIXED NaN spin - ######################################## - STAR1 = SingleStar(**{'mass': 28.837286, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - STAR2 = SingleStar(**{'mass': 6.874867, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - - BINARY = BinaryStar(STAR1, STAR2, - **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':35.609894, - 'separation': orbital_separation_from_period(35.609894, STAR1.mass, STAR2.mass), - 'eccentricity': 0.0}, - properties = sim_prop) - evolve_binary(BINARY) - ######################################## - # oRLO2 issue - ######################################## - STAR1 = SingleStar(**{'mass':29.580210, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - STAR2 = SingleStar(**{'mass': 28.814626, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - - BINARY = BinaryStar(STAR1, STAR2, - **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':40.437993, 'eccentricity': 0.0}, - properties = sim_prop) - evolve_binary(BINARY) - - ######################################## - # oRLO2 issue - ######################################## - STAR1 = SingleStar(**{'mass':67.126795, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - STAR2 = SingleStar(**{'mass': 19.622908, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - - BINARY = BinaryStar(STAR1, STAR2, - **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':1484.768582, 'eccentricity': 0.0}, + evolve_binary(binary, h5file, binary_id) + binary_id+=1 + ######################################## + # FIXED oRLO2 looping + ######################################## + star1 = SingleStar(**{'mass': 170.638207, + 'state': 'H-rich_Core_H_burning', + 'natal_kick_array': [4.921294, 4.31745, 1.777768, 3.509656]}) + star2 = SingleStar(**{'mass':37.917852, + 'state': 'H-rich_Core_H_burning', + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) + + binary = BinaryStar(star1, star2, + **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':113.352736, 'eccentricity': 0.0}, + properties = sim_prop) + evolve_binary(binary, h5file, binary_id) + binary_id+=1 + ######################################## + # Redirect to step_CO_HeMS (H-rich non-burning?) + ######################################## + star_1 = SingleStar(**{'mass': 8.333579, 'state': 'H-rich_Core_H_burning',\ + 'natal_kick_array': [17.125568, 4.101834, 0.917541, 3.961291]}) + star_2 = SingleStar(**{'mass' : 8.208376, 'state' : 'H-rich_Core_H_burning', + 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) + binary = BinaryStar(star_1, star_2, + **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period': 66.870417, 'eccentricity': 0.0}, + properties = sim_prop) + evolve_binary(binary, h5file, binary_id) + binary_id+=1 + ######################################## + # FIXED oRLO2 looping + ######################################## + star_1 = SingleStar(**{'mass': 16.921378, 'state': 'H-rich_Core_H_burning',\ + 'natal_kick_array': [268.837139, 5.773527, 2.568105, 2.519068]}) + star_2 = SingleStar(**{'mass' : 16.286318, 'state' : 'H-rich_Core_H_burning', + 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) + binary = BinaryStar(star_1, star_2, + **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period': 37.958768, 'eccentricity': 0.0}, + properties = sim_prop) + evolve_binary(binary, h5file, binary_id) + binary_id+=1 + ######################################## + # FIXED? step_detached failure + ######################################## + star1 = SingleStar(**{'mass': 19.787769, 'state': 'H-rich_Core_H_burning', + 'natal_kick_array': [24.464803, 0.666314, 1.954698, 5.598975]}) + star2 = SingleStar(**{'mass': 7.638741, 'state': 'H-rich_Core_H_burning', + 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) + binary = BinaryStar(star1, star2, + **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':3007.865561, 'eccentricity': 0.0}, properties = sim_prop) - evolve_binary(BINARY) - - ######################################## - # oRLO2 issue - ######################################## - STAR1 = SingleStar(**{'mass': 58.947503, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - STAR2 = SingleStar(**{'mass': 56.660506, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - - BINARY = BinaryStar(STAR1, STAR2, - **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':2011.300659, 'eccentricity': 0.0}, - properties = sim_prop) - evolve_binary(BINARY) - - ######################################## - # oRLO2 issue - ######################################## - STAR1 = SingleStar(**{'mass': 170.638207, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array':[47.979957374424956, 5.317304576107798, 2.7259013166068145, 4.700929589520818]}) - STAR2 = SingleStar(**{'mass': 37.917852, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - - BINARY = BinaryStar(STAR1, STAR2, - **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':113.352736, 'eccentricity': 0.0}, + evolve_binary(binary, h5file, binary_id) + binary_id+=1 + ######################################## + # Disrupted binary + ######################################## + star_1 = SingleStar(**{'mass': 16.921378, 'state': 'H-rich_Core_H_burning',\ + 'natal_kick_array': [268.837139, 5.773527, 2.568105, 2.519068]}) + star_2 = SingleStar(**{'mass' : 16.286318, 'state' : 'H-rich_Core_H_burning', + 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) + + binary = BinaryStar(star_1, star_2, + **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':3007.865561, 'eccentricity': 0.0}, properties = sim_prop) - evolve_binary(BINARY) - - ######################################## - # oRLO2 issue - ######################################## - STAR1 = SingleStar(**{'mass': 109.540207, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - STAR2 = SingleStar(**{'mass': 84.344530, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - - BINARY = BinaryStar(STAR1, STAR2, - **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':5.651896, 'eccentricity': 0.0}, - properties = sim_prop) - evolve_binary(BINARY) - - ######################################## - # redirect - ######################################## - STAR1 = SingleStar(**{'mass': 13.889634, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - STAR2 = SingleStar(**{'mass':0.490231, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - - BINARY = BinaryStar(STAR1, STAR2, - **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':14513.150157, 'eccentricity': 0.0}, - properties = sim_prop) - evolve_binary(BINARY) - ######################################## - # redirect - ######################################## - STAR1 = SingleStar(**{'mass': 9, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - STAR2 = SingleStar(**{'mass':0.8, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - - BINARY = BinaryStar(STAR1, STAR2, + evolve_binary(binary, h5file, binary_id) + binary_id+=1 + ######################################## + # FIXED Detached binary failure (low mass) + ######################################## + star1 = SingleStar(**{'mass': 9, + 'state': 'H-rich_Core_H_burning', + 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) + star2 = SingleStar(**{'mass':0.8, + 'state': 'H-rich_Core_H_burning', + 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) + + binary = BinaryStar(star1, star2, + **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':4513.150157, 'eccentricity': 0.0}, + properties = sim_prop) + evolve_binary(binary, h5file, binary_id) + binary_id+=1 + ######################################## + # FIXED SN_TYPE = None crash + ######################################## + star1 = SingleStar(**{'mass': 17.782576, + 'state': 'H-rich_Core_H_burning', + 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) + star2 = SingleStar(**{'mass':3.273864, + 'state': 'H-rich_Core_H_burning', + 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) + + binary = BinaryStar(star1, star2, + **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':4513.150157, 'eccentricity': 0.0}, + properties = sim_prop) + evolve_binary(binary, h5file, binary_id) + binary_id+=1 + ######################################## + # FIXED SN_TYPE errors + ######################################## + star1 = SingleStar(**{'mass': 6.782576, + 'state': 'H-rich_Core_H_burning', + 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) + star2 = SingleStar(**{'mass':3.273864, + 'state': 'H-rich_Core_H_burning', + 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) + + binary = BinaryStar(star1, star2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':4513.150157, 'eccentricity': 0.0}, properties = sim_prop) - evolve_binary(BINARY) - ######################################## - # Max time - ######################################## - star_1 = SingleStar(**{'mass': 103.07996766780799, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array': [0.0, 0.2965418610971261, 2.0789170290719117, 3.207488023705968]}) - star_2 = SingleStar(**{'mass': 83.66522615073987, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) - binary = BinaryStar(star_1, star_2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', - 'orbital_period': 1449.1101985875678,'eccentricity': 0.0}, properties = sim_prop) - evolve_binary(binary) - ######################################## - # Max time - ######################################## - star_1 = SingleStar(**{'mass': 8.860934140643465, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array': [11.818027275431337, 2.812412688633058, 0.4998731824233789, 2.9272630485628643]}) - star_2 = SingleStar(**{'mass': 8.584716012668551, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) - binary = BinaryStar(star_1, star_2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', - 'orbital_period': 20.82030114750744,'eccentricity': 0.0}, properties = sim_prop) - evolve_binary(binary) - ######################################## - # PR421 - ######################################## - STAR1 = SingleStar(**{'mass': 24.035366, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - STAR2 = SingleStar(**{'mass': 23.187355, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - - BINARY = BinaryStar(STAR1, STAR2, - **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':18.865029, 'eccentricity': 0.0}, - properties = sim_prop) - evolve_binary(BINARY) - - ######################################## - # CE class - ######################################## - STAR1 = SingleStar(**{'mass':33.964274, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - STAR2 = SingleStar(**{'mass': 28.98149, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - - BINARY = BinaryStar(STAR1, STAR2, - **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':82.370989, 'eccentricity': 0.0}, - properties = sim_prop) - evolve_binary(BINARY) - - ######################################## - # PR574 - stepCE fix - ######################################## - STAR1 = SingleStar(**{'mass':29.580210, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - STAR2 = SingleStar(**{'mass': 28.814626*0.4, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - - BINARY = BinaryStar(STAR1, STAR2, - **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':300.437993, 'eccentricity': 0.0}, + evolve_binary(binary, h5file, binary_id) + binary_id+=1 + ######################################## + # FIXED SN_TYPE errors + ######################################## + star1 = SingleStar(**{'mass': 40.638207, + 'state': 'H-rich_Core_H_burning', + 'natal_kick_array': [30.921294, 4.31745, 1.777768, 3.509656]}) + star2 = SingleStar(**{'mass':37.917852, + 'state': 'H-rich_Core_H_burning', + 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) + + binary = BinaryStar(star1, star2, + **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':2113.352736, 'eccentricity': 0.0}, + properties = sim_prop) + evolve_binary(binary, h5file, binary_id) + binary_id+=1 + ######################################## + # FIXED ECSN errors? + ######################################## + star1 = SingleStar(**{'mass': 12.376778, + 'state': 'H-rich_Core_H_burning', + 'natal_kick_array': [80, 4.31745, 1.777768, 3.509656]}) + star2 = SingleStar(**{'mass': 9.711216, + 'state': 'H-rich_Core_H_burning', + 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) + + + binary = BinaryStar(star1, star2, + **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':79.83702, 'eccentricity': 0.0}, + properties = sim_prop) + evolve_binary(binary, h5file, binary_id) + binary_id+=1 + ######################################## + # Interpolator masses?? + ######################################## + star1 = SingleStar(**{'mass': 7.592921, + 'state': 'H-rich_Core_H_burning', + 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) + star2 = SingleStar(**{'mass':5.038679 , + 'state': 'H-rich_Core_H_burning', + 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) + + binary = BinaryStar(star1, star2, + **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':5.537807, 'eccentricity': 0.0}, properties = sim_prop) - evolve_binary(BINARY) - - ######################################## - # e_ZAMS error - ######################################## - star1 = SingleStar(**{'mass': 8.161885721822461, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) - star2 = SingleStar(**{'mass': 3.5907829421526154, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) - - binary = BinaryStar(star1, star2, - **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period': 36.873457164644144, 'eccentricity': 0.0}, - properties = sim_prop) - evolve_binary(binary) - - ######################################## - # e_ZAMS error - ######################################## - star1 = SingleStar(**{'mass': 35.24755025317775, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array': [19.755993125895806, 0.37149222852233904, 1.6588846085306563, - 1.434617029858906]}) - star2 = SingleStar(**{'mass': 30.000450298072902, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) - - binary = BinaryStar(star1, star2, - **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period': 24060.02101364665, 'eccentricity': 0.8085077857996965}, - properties = sim_prop) - evolve_binary(binary) - - ######################################## - # e_ZAMS error - ######################################## - star1 = SingleStar(**{'mass': 11.862930493162692, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) - star2 = SingleStar(**{'mass': 1.4739109294156703, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) - - binary = BinaryStar(star1, star2, - **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period': 4111.083887312003, 'eccentricity':0.0}, - properties = sim_prop) - evolve_binary(binary) - - ######################################## - # e_ZAMS error - ######################################## - star1 = SingleStar(**{'mass': 8.527361341212108, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) - star2 = SingleStar(**{'mass': 0.7061748406821822, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) - - binary = BinaryStar(star1, star2, - **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period': 2521.1927287891444, 'eccentricity':0.0}, - properties = sim_prop) - evolve_binary(binary) - - ######################################## - # e_ZAMS error - ######################################## - star1 = SingleStar(**{'mass': 13.661942533447398 ,#29829485, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) - star2 = SingleStar(**{'mass': 4.466151109802313 , #481560266, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) - - binary = BinaryStar(star1, star2, - **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':3110.1346707516914, 'eccentricity':0.0}, - properties = sim_prop) - evolve_binary(binary) + evolve_binary(binary, h5file, binary_id) + binary_id+=1 + ######################################## + # Interpolator masses? + ######################################## + star_1 = SingleStar(**{'mass': 38.741115, + 'state': 'H-rich_Core_H_burning',\ + 'natal_kick_array': [21.113771, 2.060135, 2.224789, 4.089729]}) + star_2 = SingleStar(**{'mass': 27.776178, + 'state': 'H-rich_Core_H_burning',\ + 'natal_kick_array': [282.712103, 0.296252, 1.628433, 5.623812]}) + + binary = BinaryStar(star_1, star_2, + **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period': 93.387072, 'eccentricity': 0.0}, + properties = sim_prop) + evolve_binary(binary, h5file, binary_id) + binary_id+=1 + ######################################## + # FIXED NaN spin + ######################################## + star1 = SingleStar(**{'mass': 70.066924, + 'state': 'H-rich_Core_H_burning', + 'natal_kick_array':[0.0, 0.0, 0.0, 0.0], + 'metallicity':1}) + star2 = SingleStar(**{'mass': 34.183110, + 'state': 'H-rich_Core_H_burning', + 'natal_kick_array':[0.0, 0.0, 0.0, 0.0], + 'metallicity':1}) + binary = BinaryStar(star1, star2, + **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':5.931492e+03, + 'separation': orbital_separation_from_period(5.931492e+03, star1.mass, star2.mass), + 'eccentricity': 0.0}, + properties = sim_prop) + evolve_binary(binary, h5file, binary_id) + binary_id+=1 + ######################################## + # FIXED NaN spin + ######################################## + star1 = SingleStar(**{'mass': 28.837286, + 'state': 'H-rich_Core_H_burning', + 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) + star2 = SingleStar(**{'mass': 6.874867, + 'state': 'H-rich_Core_H_burning', + 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) + + binary = BinaryStar(star1, star2, + **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':35.609894, + 'separation': orbital_separation_from_period(35.609894, star1.mass, star2.mass), + 'eccentricity': 0.0}, + properties = sim_prop) + evolve_binary(binary, h5file, binary_id) + binary_id+=1 + ######################################## + # oRLO2 issue + ######################################## + star1 = SingleStar(**{'mass':29.580210, + 'state': 'H-rich_Core_H_burning', + 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) + star2 = SingleStar(**{'mass': 28.814626, + 'state': 'H-rich_Core_H_burning', + 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) + + binary = BinaryStar(star1, star2, + **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':40.437993, 'eccentricity': 0.0}, + properties = sim_prop) + evolve_binary(binary, h5file, binary_id) + binary_id+=1 + ######################################## + # oRLO2 issue + ######################################## + star1 = SingleStar(**{'mass':67.126795, + 'state': 'H-rich_Core_H_burning', + 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) + star2 = SingleStar(**{'mass': 19.622908, + 'state': 'H-rich_Core_H_burning', + 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) + + binary = BinaryStar(star1, star2, + **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':1484.768582, 'eccentricity': 0.0}, + properties = sim_prop) + evolve_binary(binary, h5file, binary_id) + binary_id+=1 + ######################################## + # oRLO2 issue + ######################################## + star1 = SingleStar(**{'mass': 58.947503, + 'state': 'H-rich_Core_H_burning', + 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) + star2 = SingleStar(**{'mass': 56.660506, + 'state': 'H-rich_Core_H_burning', + 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) + + binary = BinaryStar(star1, star2, + **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':2011.300659, 'eccentricity': 0.0}, + properties = sim_prop) + evolve_binary(binary, h5file, binary_id) + binary_id+=1 + ######################################## + # oRLO2 issue + ######################################## + star1 = SingleStar(**{'mass': 170.638207, + 'state': 'H-rich_Core_H_burning', + 'natal_kick_array':[47.979957374424956, 5.317304576107798, 2.7259013166068145, 4.700929589520818]}) + star2 = SingleStar(**{'mass': 37.917852, + 'state': 'H-rich_Core_H_burning', + 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) + + binary = BinaryStar(star1, star2, + **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':113.352736, 'eccentricity': 0.0}, + properties = sim_prop) + evolve_binary(binary, h5file, binary_id) + binary_id+=1 + ######################################## + # oRLO2 issue + ######################################## + star1 = SingleStar(**{'mass': 109.540207, + 'state': 'H-rich_Core_H_burning', + 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) + star2 = SingleStar(**{'mass': 84.344530, + 'state': 'H-rich_Core_H_burning', + 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) + + binary = BinaryStar(star1, star2, + **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':5.651896, 'eccentricity': 0.0}, + properties = sim_prop) + evolve_binary(binary, h5file, binary_id) + binary_id+=1 + ######################################## + # redirect + ######################################## + star1 = SingleStar(**{'mass': 13.889634, + 'state': 'H-rich_Core_H_burning', + 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) + star2 = SingleStar(**{'mass':0.490231, + 'state': 'H-rich_Core_H_burning', + 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) + + binary = BinaryStar(star1, star2, + **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':14513.150157, 'eccentricity': 0.0}, + properties = sim_prop) + evolve_binary(binary, h5file, binary_id) + binary_id+=1 + ######################################## + # redirect + ######################################## + star1 = SingleStar(**{'mass': 9, + 'state': 'H-rich_Core_H_burning', + 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) + star2 = SingleStar(**{'mass':0.8, + 'state': 'H-rich_Core_H_burning', + 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) + + binary = BinaryStar(star1, star2, + **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':4513.150157, 'eccentricity': 0.0}, + properties = sim_prop) + evolve_binary(binary, h5file, binary_id) + binary_id+=1 + ######################################## + # Max time + ######################################## + star_1 = SingleStar(**{'mass': 103.07996766780799, + 'state': 'H-rich_Core_H_burning', + 'natal_kick_array': [0.0, 0.2965418610971261, 2.0789170290719117, 3.207488023705968]}) + star_2 = SingleStar(**{'mass': 83.66522615073987, + 'state': 'H-rich_Core_H_burning', + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) + binary = BinaryStar(star_1, star_2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', + 'orbital_period': 1449.1101985875678,'eccentricity': 0.0}, properties = sim_prop) + evolve_binary(binary, h5file, binary_id) + binary_id+=1 + ######################################## + # Max time + ######################################## + star_1 = SingleStar(**{'mass': 8.860934140643465, + 'state': 'H-rich_Core_H_burning', + 'natal_kick_array': [11.818027275431337, 2.812412688633058, 0.4998731824233789, 2.9272630485628643]}) + star_2 = SingleStar(**{'mass': 8.584716012668551, + 'state': 'H-rich_Core_H_burning', + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) + binary = BinaryStar(star_1, star_2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', + 'orbital_period': 20.82030114750744,'eccentricity': 0.0}, properties = sim_prop) + evolve_binary(binary, h5file, binary_id) + binary_id+=1 + ######################################## + # PR421 + ######################################## + star1 = SingleStar(**{'mass': 24.035366, + 'state': 'H-rich_Core_H_burning', + 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) + star2 = SingleStar(**{'mass': 23.187355, + 'state': 'H-rich_Core_H_burning', + 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) + + binary = BinaryStar(star1, star2, + **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':18.865029, 'eccentricity': 0.0}, + properties = sim_prop) + evolve_binary(binary, h5file, binary_id) + binary_id+=1 + ######################################## + # CE class + ######################################## + star1 = SingleStar(**{'mass':33.964274, + 'state': 'H-rich_Core_H_burning', + 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) + star2 = SingleStar(**{'mass': 28.98149, + 'state': 'H-rich_Core_H_burning', + 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) + + binary = BinaryStar(star1, star2, + **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':82.370989, 'eccentricity': 0.0}, + properties = sim_prop) + evolve_binary(binary, h5file, binary_id) + binary_id+=1 + ######################################## + # PR574 - stepCE fix + ######################################## + star1 = SingleStar(**{'mass':29.580210, + 'state': 'H-rich_Core_H_burning', + 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) + star2 = SingleStar(**{'mass': 28.814626*0.4, + 'state': 'H-rich_Core_H_burning', + 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) + + binary = BinaryStar(star1, star2, + **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':300.437993, 'eccentricity': 0.0}, + properties = sim_prop) + evolve_binary(binary, h5file, binary_id) + binary_id+=1 + ######################################## + # e_ZAMS error + ######################################## + star1 = SingleStar(**{'mass': 8.161885721822461, + 'state': 'H-rich_Core_H_burning', + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) + star2 = SingleStar(**{'mass': 3.5907829421526154, + 'state': 'H-rich_Core_H_burning', + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) + + binary = BinaryStar(star1, star2, + **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period': 36.873457164644144, 'eccentricity': 0.0}, + properties = sim_prop) + evolve_binary(binary, h5file, binary_id) + binary_id+=1 + ######################################## + # e_ZAMS error + ######################################## + star1 = SingleStar(**{'mass': 35.24755025317775, + 'state': 'H-rich_Core_H_burning', + 'natal_kick_array': [19.755993125895806, 0.37149222852233904, 1.6588846085306563, + 1.434617029858906]}) + star2 = SingleStar(**{'mass': 30.000450298072902, + 'state': 'H-rich_Core_H_burning', + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) + + binary = BinaryStar(star1, star2, + **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period': 24060.02101364665, 'eccentricity': 0.8085077857996965}, + properties = sim_prop) + evolve_binary(binary, h5file, binary_id) + binary_id+=1 + ######################################## + # e_ZAMS error + ######################################## + star1 = SingleStar(**{'mass': 11.862930493162692, + 'state': 'H-rich_Core_H_burning', + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) + star2 = SingleStar(**{'mass': 1.4739109294156703, + 'state': 'H-rich_Core_H_burning', + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) + + binary = BinaryStar(star1, star2, + **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period': 4111.083887312003, 'eccentricity':0.0}, + properties = sim_prop) + evolve_binary(binary, h5file, binary_id) + binary_id+=1 + ######################################## + # e_ZAMS error + ######################################## + star1 = SingleStar(**{'mass': 8.527361341212108, + 'state': 'H-rich_Core_H_burning', + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) + star2 = SingleStar(**{'mass': 0.7061748406821822, + 'state': 'H-rich_Core_H_burning', + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) + + binary = BinaryStar(star1, star2, + **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period': 2521.1927287891444, 'eccentricity':0.0}, + properties = sim_prop) + evolve_binary(binary, h5file, binary_id) + binary_id+=1 + ######################################## + # e_ZAMS error + ######################################## + star1 = SingleStar(**{'mass': 13.661942533447398 ,#29829485, + 'state': 'H-rich_Core_H_burning', + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) + star2 = SingleStar(**{'mass': 4.466151109802313 , #481560266, + 'state': 'H-rich_Core_H_burning', + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) + + binary = BinaryStar(star1, star2, + **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':3110.1346707516914, 'eccentricity':0.0}, + properties = sim_prop) + evolve_binary(binary, h5file, binary_id) + binary_id+=1 ######################################## # double CO step @@ -850,4 +886,4 @@ def evolve_binaries(verbose): help="Path to save HDF5 output") args = parser.parse_args() - evolve_binaries(verbose=args.verbose) + evolve_binaries(verbose=args.verbose, args.output) From 9da430dc3f3a79245a4e3c95dcf89c8f1a0aedf4 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Thu, 18 Dec 2025 15:19:07 +0000 Subject: [PATCH 50/91] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- dev-tools/script_data/1Zsun_binaries_suite.py | 142 +++++++++--------- 1 file changed, 71 insertions(+), 71 deletions(-) diff --git a/dev-tools/script_data/1Zsun_binaries_suite.py b/dev-tools/script_data/1Zsun_binaries_suite.py index c18d2009fd..a1ba0e92ed 100644 --- a/dev-tools/script_data/1Zsun_binaries_suite.py +++ b/dev-tools/script_data/1Zsun_binaries_suite.py @@ -206,7 +206,7 @@ def evolve_binaries(verbose,output_path): 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) binary = BinaryStar(star_1, star_2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period': 190925.99636740884,'eccentricity': 0.0}, properties = sim_prop) - evolve_binary(binary, h5file, binary_id) + evolve_binary(binary, h5file, binary_id) binary_id+=1 ######################################## # Failing binary in matching @@ -217,7 +217,7 @@ def evolve_binaries(verbose,output_path): 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) binary = BinaryStar(star_1, star_2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period': 20479.71919353725,'eccentricity': 0.0}, properties = sim_prop) - evolve_binary(binary, h5file, binary_id) + evolve_binary(binary, h5file, binary_id) binary_id+=1 ######################################## # flipped S1 and S2 ? @@ -228,8 +228,8 @@ def evolve_binaries(verbose,output_path): 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) binary = BinaryStar(star_1, star_2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period': 18.605997832086413,'eccentricity': 0.0}, properties = sim_prop) - - evolve_binary(binary, h5file, binary_id) + + evolve_binary(binary, h5file, binary_id) binary_id+=1 ######################################## # flipped S1 and S2 @@ -240,7 +240,7 @@ def evolve_binaries(verbose,output_path): 'natal_kick_array': [0.0, 4.190728383757787, 1.1521129697118118, 5.015343794234789]}) binary = BinaryStar(star_1, star_2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period': 9.824025,'eccentricity': 0.0}, properties = sim_prop) - evolve_binary(binary, h5file, binary_id) + evolve_binary(binary, h5file, binary_id) binary_id+=1 ######################################## # flipped S1 and S2 @@ -251,7 +251,7 @@ def evolve_binaries(verbose,output_path): 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) binary = BinaryStar(star_1, star_2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period': 3.820571,'eccentricity': 0.0}, properties = sim_prop) - evolve_binary(binary, h5file, binary_id) + evolve_binary(binary, h5file, binary_id) binary_id+=1 ######################################## # Normal binary evolution @@ -262,7 +262,7 @@ def evolve_binaries(verbose,output_path): 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) binary = BinaryStar(star_1, star_2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period': 30.820571,'eccentricity': 0.0}, properties = sim_prop) - evolve_binary(binary, h5file, binary_id) + evolve_binary(binary, h5file, binary_id) binary_id+=1 ######################################## # Normal binary @@ -273,7 +273,7 @@ def evolve_binaries(verbose,output_path): 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) binary = BinaryStar(star_1, star_2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period': 63123.74544474666,'eccentricity': 0.0}, properties = sim_prop) - evolve_binary(binary, h5file, binary_id) + evolve_binary(binary, h5file, binary_id) binary_id+=1 ######################################## # Normal binary @@ -284,7 +284,7 @@ def evolve_binaries(verbose,output_path): 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) binary = BinaryStar(star_1, star_2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period': 27.77657038557851,'eccentricity': 0.0}, properties = sim_prop) - evolve_binary(binary, h5file, binary_id) + evolve_binary(binary, h5file, binary_id) binary_id+=1 ######################################## # Normal binary @@ -298,7 +298,7 @@ def evolve_binaries(verbose,output_path): binary = BinaryStar(star1, star2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period': 17.957531550841225, 'eccentricity': 0.0,}, properties=sim_prop) - evolve_binary(binary, h5file, binary_id) + evolve_binary(binary, h5file, binary_id) binary_id+=1 ######################################## # High BH spin options @@ -309,7 +309,7 @@ def evolve_binaries(verbose,output_path): 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) binary = BinaryStar(star_1, star_2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period': 501.99252706449792,'eccentricity': 0.0}, properties = sim_prop) - evolve_binary(binary, h5file, binary_id) + evolve_binary(binary, h5file, binary_id) binary_id+=1 ######################################## # Original a>1 spin error @@ -320,7 +320,7 @@ def evolve_binaries(verbose,output_path): 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) binary = BinaryStar(star_1, star_2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period': 151.99252706449792,'eccentricity': 0.0}, properties = sim_prop) - evolve_binary(binary, h5file, binary_id) + evolve_binary(binary, h5file, binary_id) binary_id+=1 ######################################## # FIXED disrupted crash @@ -334,7 +334,7 @@ def evolve_binaries(verbose,output_path): binary = BinaryStar(star1, star2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':12.877004, 'eccentricity': 0.0}, properties = sim_prop) - evolve_binary(binary, h5file, binary_id) + evolve_binary(binary, h5file, binary_id) binary_id+=1 ######################################## # FIXED error with SN type @@ -348,7 +348,7 @@ def evolve_binaries(verbose,output_path): binary = BinaryStar(star1, star2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':4513.150157, 'eccentricity': 0.0}, properties = sim_prop) - evolve_binary(binary, h5file, binary_id) + evolve_binary(binary, h5file, binary_id) binary_id+=1 ######################################## # FIXED oRLO2 looping @@ -359,11 +359,11 @@ def evolve_binaries(verbose,output_path): star2 = SingleStar(**{'mass':37.917852, 'state': 'H-rich_Core_H_burning', 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) - + binary = BinaryStar(star1, star2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':113.352736, 'eccentricity': 0.0}, properties = sim_prop) - evolve_binary(binary, h5file, binary_id) + evolve_binary(binary, h5file, binary_id) binary_id+=1 ######################################## # Redirect to step_CO_HeMS (H-rich non-burning?) @@ -375,7 +375,7 @@ def evolve_binaries(verbose,output_path): binary = BinaryStar(star_1, star_2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period': 66.870417, 'eccentricity': 0.0}, properties = sim_prop) - evolve_binary(binary, h5file, binary_id) + evolve_binary(binary, h5file, binary_id) binary_id+=1 ######################################## # FIXED oRLO2 looping @@ -387,7 +387,7 @@ def evolve_binaries(verbose,output_path): binary = BinaryStar(star_1, star_2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period': 37.958768, 'eccentricity': 0.0}, properties = sim_prop) - evolve_binary(binary, h5file, binary_id) + evolve_binary(binary, h5file, binary_id) binary_id+=1 ######################################## # FIXED? step_detached failure @@ -399,7 +399,7 @@ def evolve_binaries(verbose,output_path): binary = BinaryStar(star1, star2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':3007.865561, 'eccentricity': 0.0}, properties = sim_prop) - evolve_binary(binary, h5file, binary_id) + evolve_binary(binary, h5file, binary_id) binary_id+=1 ######################################## # Disrupted binary @@ -408,11 +408,11 @@ def evolve_binaries(verbose,output_path): 'natal_kick_array': [268.837139, 5.773527, 2.568105, 2.519068]}) star_2 = SingleStar(**{'mass' : 16.286318, 'state' : 'H-rich_Core_H_burning', 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - + binary = BinaryStar(star_1, star_2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':3007.865561, 'eccentricity': 0.0}, properties = sim_prop) - evolve_binary(binary, h5file, binary_id) + evolve_binary(binary, h5file, binary_id) binary_id+=1 ######################################## # FIXED Detached binary failure (low mass) @@ -423,11 +423,11 @@ def evolve_binaries(verbose,output_path): star2 = SingleStar(**{'mass':0.8, 'state': 'H-rich_Core_H_burning', 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - + binary = BinaryStar(star1, star2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':4513.150157, 'eccentricity': 0.0}, properties = sim_prop) - evolve_binary(binary, h5file, binary_id) + evolve_binary(binary, h5file, binary_id) binary_id+=1 ######################################## # FIXED SN_TYPE = None crash @@ -438,11 +438,11 @@ def evolve_binaries(verbose,output_path): star2 = SingleStar(**{'mass':3.273864, 'state': 'H-rich_Core_H_burning', 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - + binary = BinaryStar(star1, star2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':4513.150157, 'eccentricity': 0.0}, properties = sim_prop) - evolve_binary(binary, h5file, binary_id) + evolve_binary(binary, h5file, binary_id) binary_id+=1 ######################################## # FIXED SN_TYPE errors @@ -453,11 +453,11 @@ def evolve_binaries(verbose,output_path): star2 = SingleStar(**{'mass':3.273864, 'state': 'H-rich_Core_H_burning', 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - + binary = BinaryStar(star1, star2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':4513.150157, 'eccentricity': 0.0}, properties = sim_prop) - evolve_binary(binary, h5file, binary_id) + evolve_binary(binary, h5file, binary_id) binary_id+=1 ######################################## # FIXED SN_TYPE errors @@ -468,11 +468,11 @@ def evolve_binaries(verbose,output_path): star2 = SingleStar(**{'mass':37.917852, 'state': 'H-rich_Core_H_burning', 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - + binary = BinaryStar(star1, star2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':2113.352736, 'eccentricity': 0.0}, properties = sim_prop) - evolve_binary(binary, h5file, binary_id) + evolve_binary(binary, h5file, binary_id) binary_id+=1 ######################################## # FIXED ECSN errors? @@ -483,12 +483,12 @@ def evolve_binaries(verbose,output_path): star2 = SingleStar(**{'mass': 9.711216, 'state': 'H-rich_Core_H_burning', 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - - + + binary = BinaryStar(star1, star2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':79.83702, 'eccentricity': 0.0}, properties = sim_prop) - evolve_binary(binary, h5file, binary_id) + evolve_binary(binary, h5file, binary_id) binary_id+=1 ######################################## # Interpolator masses?? @@ -499,11 +499,11 @@ def evolve_binaries(verbose,output_path): star2 = SingleStar(**{'mass':5.038679 , 'state': 'H-rich_Core_H_burning', 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - + binary = BinaryStar(star1, star2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':5.537807, 'eccentricity': 0.0}, properties = sim_prop) - evolve_binary(binary, h5file, binary_id) + evolve_binary(binary, h5file, binary_id) binary_id+=1 ######################################## # Interpolator masses? @@ -514,11 +514,11 @@ def evolve_binaries(verbose,output_path): star_2 = SingleStar(**{'mass': 27.776178, 'state': 'H-rich_Core_H_burning',\ 'natal_kick_array': [282.712103, 0.296252, 1.628433, 5.623812]}) - + binary = BinaryStar(star_1, star_2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period': 93.387072, 'eccentricity': 0.0}, properties = sim_prop) - evolve_binary(binary, h5file, binary_id) + evolve_binary(binary, h5file, binary_id) binary_id+=1 ######################################## # FIXED NaN spin @@ -536,7 +536,7 @@ def evolve_binaries(verbose,output_path): 'separation': orbital_separation_from_period(5.931492e+03, star1.mass, star2.mass), 'eccentricity': 0.0}, properties = sim_prop) - evolve_binary(binary, h5file, binary_id) + evolve_binary(binary, h5file, binary_id) binary_id+=1 ######################################## # FIXED NaN spin @@ -547,13 +547,13 @@ def evolve_binaries(verbose,output_path): star2 = SingleStar(**{'mass': 6.874867, 'state': 'H-rich_Core_H_burning', 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - + binary = BinaryStar(star1, star2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':35.609894, 'separation': orbital_separation_from_period(35.609894, star1.mass, star2.mass), 'eccentricity': 0.0}, properties = sim_prop) - evolve_binary(binary, h5file, binary_id) + evolve_binary(binary, h5file, binary_id) binary_id+=1 ######################################## # oRLO2 issue @@ -564,11 +564,11 @@ def evolve_binaries(verbose,output_path): star2 = SingleStar(**{'mass': 28.814626, 'state': 'H-rich_Core_H_burning', 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - + binary = BinaryStar(star1, star2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':40.437993, 'eccentricity': 0.0}, properties = sim_prop) - evolve_binary(binary, h5file, binary_id) + evolve_binary(binary, h5file, binary_id) binary_id+=1 ######################################## # oRLO2 issue @@ -579,11 +579,11 @@ def evolve_binaries(verbose,output_path): star2 = SingleStar(**{'mass': 19.622908, 'state': 'H-rich_Core_H_burning', 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - + binary = BinaryStar(star1, star2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':1484.768582, 'eccentricity': 0.0}, properties = sim_prop) - evolve_binary(binary, h5file, binary_id) + evolve_binary(binary, h5file, binary_id) binary_id+=1 ######################################## # oRLO2 issue @@ -594,11 +594,11 @@ def evolve_binaries(verbose,output_path): star2 = SingleStar(**{'mass': 56.660506, 'state': 'H-rich_Core_H_burning', 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - + binary = BinaryStar(star1, star2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':2011.300659, 'eccentricity': 0.0}, properties = sim_prop) - evolve_binary(binary, h5file, binary_id) + evolve_binary(binary, h5file, binary_id) binary_id+=1 ######################################## # oRLO2 issue @@ -609,11 +609,11 @@ def evolve_binaries(verbose,output_path): star2 = SingleStar(**{'mass': 37.917852, 'state': 'H-rich_Core_H_burning', 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - + binary = BinaryStar(star1, star2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':113.352736, 'eccentricity': 0.0}, properties = sim_prop) - evolve_binary(binary, h5file, binary_id) + evolve_binary(binary, h5file, binary_id) binary_id+=1 ######################################## # oRLO2 issue @@ -624,11 +624,11 @@ def evolve_binaries(verbose,output_path): star2 = SingleStar(**{'mass': 84.344530, 'state': 'H-rich_Core_H_burning', 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - + binary = BinaryStar(star1, star2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':5.651896, 'eccentricity': 0.0}, properties = sim_prop) - evolve_binary(binary, h5file, binary_id) + evolve_binary(binary, h5file, binary_id) binary_id+=1 ######################################## # redirect @@ -639,11 +639,11 @@ def evolve_binaries(verbose,output_path): star2 = SingleStar(**{'mass':0.490231, 'state': 'H-rich_Core_H_burning', 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - + binary = BinaryStar(star1, star2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':14513.150157, 'eccentricity': 0.0}, properties = sim_prop) - evolve_binary(binary, h5file, binary_id) + evolve_binary(binary, h5file, binary_id) binary_id+=1 ######################################## # redirect @@ -654,11 +654,11 @@ def evolve_binaries(verbose,output_path): star2 = SingleStar(**{'mass':0.8, 'state': 'H-rich_Core_H_burning', 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - + binary = BinaryStar(star1, star2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':4513.150157, 'eccentricity': 0.0}, properties = sim_prop) - evolve_binary(binary, h5file, binary_id) + evolve_binary(binary, h5file, binary_id) binary_id+=1 ######################################## # Max time @@ -671,7 +671,7 @@ def evolve_binaries(verbose,output_path): 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) binary = BinaryStar(star_1, star_2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period': 1449.1101985875678,'eccentricity': 0.0}, properties = sim_prop) - evolve_binary(binary, h5file, binary_id) + evolve_binary(binary, h5file, binary_id) binary_id+=1 ######################################## # Max time @@ -684,7 +684,7 @@ def evolve_binaries(verbose,output_path): 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) binary = BinaryStar(star_1, star_2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period': 20.82030114750744,'eccentricity': 0.0}, properties = sim_prop) - evolve_binary(binary, h5file, binary_id) + evolve_binary(binary, h5file, binary_id) binary_id+=1 ######################################## # PR421 @@ -695,11 +695,11 @@ def evolve_binaries(verbose,output_path): star2 = SingleStar(**{'mass': 23.187355, 'state': 'H-rich_Core_H_burning', 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - + binary = BinaryStar(star1, star2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':18.865029, 'eccentricity': 0.0}, properties = sim_prop) - evolve_binary(binary, h5file, binary_id) + evolve_binary(binary, h5file, binary_id) binary_id+=1 ######################################## # CE class @@ -710,11 +710,11 @@ def evolve_binaries(verbose,output_path): star2 = SingleStar(**{'mass': 28.98149, 'state': 'H-rich_Core_H_burning', 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - + binary = BinaryStar(star1, star2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':82.370989, 'eccentricity': 0.0}, properties = sim_prop) - evolve_binary(binary, h5file, binary_id) + evolve_binary(binary, h5file, binary_id) binary_id+=1 ######################################## # PR574 - stepCE fix @@ -725,11 +725,11 @@ def evolve_binaries(verbose,output_path): star2 = SingleStar(**{'mass': 28.814626*0.4, 'state': 'H-rich_Core_H_burning', 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - + binary = BinaryStar(star1, star2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':300.437993, 'eccentricity': 0.0}, properties = sim_prop) - evolve_binary(binary, h5file, binary_id) + evolve_binary(binary, h5file, binary_id) binary_id+=1 ######################################## # e_ZAMS error @@ -740,11 +740,11 @@ def evolve_binaries(verbose,output_path): star2 = SingleStar(**{'mass': 3.5907829421526154, 'state': 'H-rich_Core_H_burning', 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) - + binary = BinaryStar(star1, star2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period': 36.873457164644144, 'eccentricity': 0.0}, properties = sim_prop) - evolve_binary(binary, h5file, binary_id) + evolve_binary(binary, h5file, binary_id) binary_id+=1 ######################################## # e_ZAMS error @@ -756,11 +756,11 @@ def evolve_binaries(verbose,output_path): star2 = SingleStar(**{'mass': 30.000450298072902, 'state': 'H-rich_Core_H_burning', 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) - + binary = BinaryStar(star1, star2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period': 24060.02101364665, 'eccentricity': 0.8085077857996965}, properties = sim_prop) - evolve_binary(binary, h5file, binary_id) + evolve_binary(binary, h5file, binary_id) binary_id+=1 ######################################## # e_ZAMS error @@ -771,11 +771,11 @@ def evolve_binaries(verbose,output_path): star2 = SingleStar(**{'mass': 1.4739109294156703, 'state': 'H-rich_Core_H_burning', 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) - + binary = BinaryStar(star1, star2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period': 4111.083887312003, 'eccentricity':0.0}, properties = sim_prop) - evolve_binary(binary, h5file, binary_id) + evolve_binary(binary, h5file, binary_id) binary_id+=1 ######################################## # e_ZAMS error @@ -786,11 +786,11 @@ def evolve_binaries(verbose,output_path): star2 = SingleStar(**{'mass': 0.7061748406821822, 'state': 'H-rich_Core_H_burning', 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) - + binary = BinaryStar(star1, star2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period': 2521.1927287891444, 'eccentricity':0.0}, properties = sim_prop) - evolve_binary(binary, h5file, binary_id) + evolve_binary(binary, h5file, binary_id) binary_id+=1 ######################################## # e_ZAMS error @@ -801,11 +801,11 @@ def evolve_binaries(verbose,output_path): star2 = SingleStar(**{'mass': 4.466151109802313 , #481560266, 'state': 'H-rich_Core_H_burning', 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) - + binary = BinaryStar(star1, star2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':3110.1346707516914, 'eccentricity':0.0}, properties = sim_prop) - evolve_binary(binary, h5file, binary_id) + evolve_binary(binary, h5file, binary_id) binary_id+=1 ######################################## From 7a3bd52bf3e2460a40763f633faebbe7e04a5406 Mon Sep 17 00:00:00 2001 From: Elizabeth Teng <41969755+elizabethteng@users.noreply.github.com> Date: Thu, 18 Dec 2025 09:19:47 -0600 Subject: [PATCH 51/91] Update authors --- dev-tools/script_data/1Zsun_binaries_suite.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev-tools/script_data/1Zsun_binaries_suite.py b/dev-tools/script_data/1Zsun_binaries_suite.py index a1ba0e92ed..73834b8151 100644 --- a/dev-tools/script_data/1Zsun_binaries_suite.py +++ b/dev-tools/script_data/1Zsun_binaries_suite.py @@ -3,7 +3,7 @@ Script to evolve a few binaries. Used for validation of the branch. -Author: Max Briel +Authors: Max Briel, Elizabeth Teng """ import argparse From 02d10a2e8acb437c79da7a89f3ca2a2e14e95a07 Mon Sep 17 00:00:00 2001 From: Elizabeth Teng <41969755+elizabethteng@users.noreply.github.com> Date: Thu, 18 Dec 2025 09:22:08 -0600 Subject: [PATCH 52/91] remove alarm calls that were never set Removed signal alarm handling in exception block. --- dev-tools/script_data/1Zsun_binaries_suite.py | 5 ----- 1 file changed, 5 deletions(-) diff --git a/dev-tools/script_data/1Zsun_binaries_suite.py b/dev-tools/script_data/1Zsun_binaries_suite.py index 73834b8151..bb95922bb4 100644 --- a/dev-tools/script_data/1Zsun_binaries_suite.py +++ b/dev-tools/script_data/1Zsun_binaries_suite.py @@ -153,9 +153,6 @@ def warning_handler(message, category, filename, lineno, file=None, line=None): grp.create_dataset(col, data=df[col].values) except Exception as e: - # turn off binary alarm in case of exception - signal.alarm(0) - print_failed_binary(binary, e) err_grp = h5file.require_group(f"binary_{binary_id}/errors") @@ -163,8 +160,6 @@ def warning_handler(message, category, filename, lineno, file=None, line=None): err_grp.attrs['exception_message'] = str(e) finally: - # Always turn off binary alarm and restore warning handler - signal.alarm(0) warnings.showwarning = old_showwarning # ensure binary group exists From 5cbf4baeada023d4a2570bda305ce7011e18c4a9 Mon Sep 17 00:00:00 2001 From: Elizabeth Teng <41969755+elizabethteng@users.noreply.github.com> Date: Thu, 18 Dec 2025 09:30:54 -0600 Subject: [PATCH 53/91] Enhance evolve_binaries.sh for better logging and error handling Updated the script to log output and check for errors. --- dev-tools/evolve_binaries.sh | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/dev-tools/evolve_binaries.sh b/dev-tools/evolve_binaries.sh index 051dafcd13..ee5dec4306 100755 --- a/dev-tools/evolve_binaries.sh +++ b/dev-tools/evolve_binaries.sh @@ -88,11 +88,16 @@ pip install -e "$CLONE_DIR" -q 2>&1 | sed 's/^/ /' echo "šŸš€ Running evolve_binaries.py" # # Run the Python script and capture output (stdout and stderr) -python script_data/1Zsun_binaries_suite.py --output "$OUTPUT_FILE" > "$LOG_FILE" 2>&1 +python script_data/1Zsun_binaries_suite.py --output "$OUTPUT_FILE" 2>&1 | tee "$LOG_FILE" if [ ! -f "$OUTPUT_FILE" ]; then echo "ERROR: Results file was not created: $OUTPUT_FILE" exit 2 fi +if [ $? -ne 0 ]; then + echo "ERROR: Python script exited with an error. Check $LOG_FILE for details." + exit 3 +fi + echo -e "āœ… Script completed. Output saved to \n$OUTPUT_FILE" From 621be97bb4cf9009d71129a106cef210c038b8de Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Thu, 18 Dec 2025 15:31:21 +0000 Subject: [PATCH 54/91] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- dev-tools/evolve_binaries.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev-tools/evolve_binaries.sh b/dev-tools/evolve_binaries.sh index ee5dec4306..5e8e60183f 100755 --- a/dev-tools/evolve_binaries.sh +++ b/dev-tools/evolve_binaries.sh @@ -88,7 +88,7 @@ pip install -e "$CLONE_DIR" -q 2>&1 | sed 's/^/ /' echo "šŸš€ Running evolve_binaries.py" # # Run the Python script and capture output (stdout and stderr) -python script_data/1Zsun_binaries_suite.py --output "$OUTPUT_FILE" 2>&1 | tee "$LOG_FILE" +python script_data/1Zsun_binaries_suite.py --output "$OUTPUT_FILE" 2>&1 | tee "$LOG_FILE" if [ ! -f "$OUTPUT_FILE" ]; then echo "ERROR: Results file was not created: $OUTPUT_FILE" From c3256b534aa4165fd0f11bbde745ee3fe2ca47bf Mon Sep 17 00:00:00 2001 From: Elizabeth Teng <41969755+elizabethteng@users.noreply.github.com> Date: Thu, 18 Dec 2025 09:34:36 -0600 Subject: [PATCH 55/91] Fix argument passing for evolve_binaries function --- dev-tools/script_data/1Zsun_binaries_suite.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev-tools/script_data/1Zsun_binaries_suite.py b/dev-tools/script_data/1Zsun_binaries_suite.py index bb95922bb4..c0a89cb4ad 100644 --- a/dev-tools/script_data/1Zsun_binaries_suite.py +++ b/dev-tools/script_data/1Zsun_binaries_suite.py @@ -881,4 +881,4 @@ def evolve_binaries(verbose,output_path): help="Path to save HDF5 output") args = parser.parse_args() - evolve_binaries(verbose=args.verbose, args.output) + evolve_binaries(verbose=args.verbose, output_path=args.output) From e4dedbe2ffa9889a89c523ebb984a834aea9a016 Mon Sep 17 00:00:00 2001 From: Elizabeth Teng <41969755+elizabethteng@users.noreply.github.com> Date: Thu, 18 Dec 2025 09:46:05 -0600 Subject: [PATCH 56/91] fill in all code for validate_binaries.sh Updated script to accept branch and suffix as arguments, streamlined output file naming. --- dev-tools/validate_binaries.sh | 35 ++++++++++++++++------------------ 1 file changed, 16 insertions(+), 19 deletions(-) diff --git a/dev-tools/validate_binaries.sh b/dev-tools/validate_binaries.sh index 31b7c6d72a..04a041af06 100644 --- a/dev-tools/validate_binaries.sh +++ b/dev-tools/validate_binaries.sh @@ -3,27 +3,24 @@ # A script for validating the outputs of 100 binaries, # which can be compared to a baseline to monitor changes to the code. -# script usage: ./validate_binaries.sh --branch candidate-branch - -# run candidate binaries and save to file -# ./evolve_binaries.sh -# save to file - -# evaluate tolerance for quantitative values - -# evaluate qualitative differences - -# warnings and error tracking - -# structured output - -# compare -# python compare_runs.py baseline.json candidate.json +# script usage: ./validate_binaries.sh --branch candidate_branch +BRANCH=$1 +SUFFIX=$2 +# run candidate binaries and save to file +./evolve_binaries.sh "$BRANCH" +# compare quantitative, qualitative, warnings/errors, structured output +# create outputs/comparison_branchname.txt +SAFE_BRANCH="${BRANCH//\//_}" +CANDIDATE_FILE="outputs/candidate_${SAFE_BRANCH}.h5" +COMPARISON_FILE="outputs/comparison_${SAFE_BRANCH}${SUFFIX:+_$SUFFIX}.txt" +python compare_runs.py baseline.h5 "$CANDIDATE_FILE" > "$COMPARISON_FILE" +if [ $? -ne 0 ]; then + echo "Error: compare_runs.py failed. Check $COMPARISON_FILE" + exit 1 +fi -# outputs/baseline.h5 -# outputs/candidate_branchname.h5 -# outputs/comparison_branchname.txt +echo "Binary evolution comparison saved to $COMPARISON_FILE" From d66cf6ea6c26ab6b99bcbcd857f30df1920ac78f Mon Sep 17 00:00:00 2001 From: Elizabeth Teng <41969755+elizabethteng@users.noreply.github.com> Date: Thu, 18 Dec 2025 09:52:48 -0600 Subject: [PATCH 57/91] starting point of compare_runs.py for comparing two h5 files --- dev-tools/compare_runs.py | 73 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) create mode 100644 dev-tools/compare_runs.py diff --git a/dev-tools/compare_runs.py b/dev-tools/compare_runs.py new file mode 100644 index 0000000000..8444d08a88 --- /dev/null +++ b/dev-tools/compare_runs.py @@ -0,0 +1,73 @@ +#!/usr/bin/env python3 + +""" +Compare evolution outcomes of set of binaries saved to file with script_data/1Zsun_binaries_suite.py +Used for validation of the branch. + +Author: Elizabeth Teng +""" + + +import sys +import h5py +import numpy as np + +def compare_datasets(base, cand, path="/"): + """ + Recursively compare HDF5 datasets. + Returns a list of strings with differences. + """ + differences = [] + + for key in base.keys(): + base_item = base[key] + if key not in cand: + differences.append(f"{path}{key} missing in candidate") + continue + + cand_item = cand[key] + + if isinstance(base_item, h5py.Dataset): + base_data = base_item[()] + cand_data = cand_item[()] + + if np.issubdtype(base_data.dtype, np.number): + if not np.allclose(base_data, cand_data, rtol=1e-5, atol=1e-8): + differences.append(f"{path}{key} numeric mismatch") + else: + if not np.array_equal(base_data, cand_data): + differences.append(f"{path}{key} non-numeric mismatch") + + elif isinstance(base_item, h5py.Group): + differences.extend(compare_datasets(base_item, cand_item, path=f"{path}{key}/")) + + # Check for extra keys in candidate + for key in cand.keys(): + if key not in base: + differences.append(f"{path}{key} extra in candidate") + + return differences + + +def main(): + if len(sys.argv) != 3: + print("Usage: compare_runs.py baseline.h5 candidate.h5") + sys.exit(1) + + baseline_file = sys.argv[1] + candidate_file = sys.argv[2] + + with h5py.File(baseline_file, 'r') as base, h5py.File(candidate_file, 'r') as cand: + diffs = compare_datasets(base, cand) + + if diffs: + print("Differences found:") + for diff in diffs: + print(" -", diff) + sys.exit(1) + else: + print("No differences detected between baseline and candidate.") + + +if __name__ == "__main__": + main() From 46cdc5a560cf860df9d13a6a7e5ade556897ec85 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Thu, 18 Dec 2025 15:52:57 +0000 Subject: [PATCH 58/91] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- dev-tools/compare_runs.py | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/dev-tools/compare_runs.py b/dev-tools/compare_runs.py index 8444d08a88..6ff28d81e2 100644 --- a/dev-tools/compare_runs.py +++ b/dev-tools/compare_runs.py @@ -9,43 +9,45 @@ import sys + import h5py import numpy as np + def compare_datasets(base, cand, path="/"): """ Recursively compare HDF5 datasets. Returns a list of strings with differences. """ differences = [] - + for key in base.keys(): base_item = base[key] if key not in cand: differences.append(f"{path}{key} missing in candidate") continue - + cand_item = cand[key] if isinstance(base_item, h5py.Dataset): base_data = base_item[()] cand_data = cand_item[()] - + if np.issubdtype(base_data.dtype, np.number): if not np.allclose(base_data, cand_data, rtol=1e-5, atol=1e-8): differences.append(f"{path}{key} numeric mismatch") else: if not np.array_equal(base_data, cand_data): differences.append(f"{path}{key} non-numeric mismatch") - + elif isinstance(base_item, h5py.Group): differences.extend(compare_datasets(base_item, cand_item, path=f"{path}{key}/")) - + # Check for extra keys in candidate for key in cand.keys(): if key not in base: differences.append(f"{path}{key} extra in candidate") - + return differences @@ -53,7 +55,7 @@ def main(): if len(sys.argv) != 3: print("Usage: compare_runs.py baseline.h5 candidate.h5") sys.exit(1) - + baseline_file = sys.argv[1] candidate_file = sys.argv[2] From b89ff379529439d5e87c218231dee28f5a918438 Mon Sep 17 00:00:00 2001 From: Elizabeth Teng <41969755+elizabethteng@users.noreply.github.com> Date: Fri, 9 Jan 2026 15:07:18 -0600 Subject: [PATCH 59/91] Add conda source detection in evolve_binaries.sh --- dev-tools/evolve_binaries.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/dev-tools/evolve_binaries.sh b/dev-tools/evolve_binaries.sh index 5e8e60183f..2021995bff 100755 --- a/dev-tools/evolve_binaries.sh +++ b/dev-tools/evolve_binaries.sh @@ -52,6 +52,9 @@ elif [ -f "$HOME/anaconda3/etc/profile.d/conda.sh" ]; then source "$HOME/anaconda3/etc/profile.d/conda.sh" elif [ -f "/opt/homebrew/Caskroom/miniconda/base/etc/profile.d/conda.sh" ]; then source "/opt/homebrew/Caskroom/miniconda/base/etc/profile.d/conda.sh" +elif command -v conda >/dev/null 2>&1; then + CONDA_BASE=$(conda info --base) + source "${CONDA_BASE}/etc/profile.d/conda.sh" else echo -e "\033[31mError: Could not find conda installation. Please check your conda setup.\033[0m" exit 1 From 1529d76ee7638c71dffccbf867dd9f0a3f50471f Mon Sep 17 00:00:00 2001 From: Elizabeth Teng <41969755+elizabethteng@users.noreply.github.com> Date: Fri, 9 Jan 2026 15:19:30 -0600 Subject: [PATCH 60/91] Add h5py import to 1Zsun_binaries_suite.py --- dev-tools/script_data/1Zsun_binaries_suite.py | 1 + 1 file changed, 1 insertion(+) diff --git a/dev-tools/script_data/1Zsun_binaries_suite.py b/dev-tools/script_data/1Zsun_binaries_suite.py index c0a89cb4ad..288f37890c 100644 --- a/dev-tools/script_data/1Zsun_binaries_suite.py +++ b/dev-tools/script_data/1Zsun_binaries_suite.py @@ -11,6 +11,7 @@ import signal import sys import warnings +import h5py from posydon.binary_evol.binarystar import BinaryStar, SingleStar from posydon.binary_evol.simulationproperties import SimulationProperties From 7cb3922ae4838294ba22dde63b15cd677df2a162 Mon Sep 17 00:00:00 2001 From: Elizabeth Teng Date: Thu, 26 Feb 2026 04:09:34 -0600 Subject: [PATCH 61/91] refactor binary validation suite: multi metallicity support, bug fixes, generate baseline, add more specificity to compare_runs --- dev-tools/.gitignore | 14 + dev-tools/check_outputs.ipynb | 512 ++++++++++ dev-tools/compare_runs.py | 429 ++++++++- dev-tools/evolve_binaries.sh | 185 ++-- dev-tools/generate_baseline.sh | 96 ++ dev-tools/script_data/1Zsun_binaries_suite.py | 885 ------------------ ...inaries_params.ini => binaries_params.ini} | 2 + dev-tools/script_data/binaries_suite.py | 694 ++++++++++++++ dev-tools/validate_binaries.sh | 170 +++- 9 files changed, 1961 insertions(+), 1026 deletions(-) create mode 100644 dev-tools/.gitignore create mode 100644 dev-tools/check_outputs.ipynb create mode 100644 dev-tools/generate_baseline.sh delete mode 100644 dev-tools/script_data/1Zsun_binaries_suite.py rename dev-tools/script_data/{1Zsun_binaries_params.ini => binaries_params.ini} (99%) create mode 100644 dev-tools/script_data/binaries_suite.py diff --git a/dev-tools/.gitignore b/dev-tools/.gitignore new file mode 100644 index 0000000000..1cea72efc6 --- /dev/null +++ b/dev-tools/.gitignore @@ -0,0 +1,14 @@ +# Remove the accidentally staged clone +git rm --cached -r workdirs/ + +# Create .gitignore +cat > .gitignore << 'EOF' +workdirs/ +outputs/ +logs/ +baselines/ +test_*.h5 +EOF + +git add .gitignore + diff --git a/dev-tools/check_outputs.ipynb b/dev-tools/check_outputs.ipynb new file mode 100644 index 0000000000..c0073df835 --- /dev/null +++ b/dev-tools/check_outputs.ipynb @@ -0,0 +1,512 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "id": "7e9791d3", + "metadata": {}, + "outputs": [], + "source": [ + "import argparse\n", + "import os\n", + "import signal\n", + "import sys\n", + "import warnings\n", + "import h5py\n", + "import pandas as pd\n", + "\n", + "from posydon.binary_evol.binarystar import BinaryStar, SingleStar\n", + "from posydon.binary_evol.simulationproperties import SimulationProperties\n", + "from posydon.popsyn.io import simprop_kwargs_from_ini\n", + "from posydon.utils.common_functions import orbital_separation_from_period" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "327be9fe", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "env: PATH_TO_POSYDON=/projects/b1119/eteng/software/valid/POSYDON/\n", + "env: PATH_TO_POSYDON_DATA=/projects/b1119/POSYDON_popsynth_data/v2/250520_newSNe/\n" + ] + } + ], + "source": [ + "%env PATH_TO_POSYDON=/projects/b1119/eteng/software/valid/POSYDON/\n", + "%env PATH_TO_POSYDON_DATA=/projects/b1119/POSYDON_popsynth_data/v2/250520_newSNe/" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "994f6ebf", + "metadata": {}, + "outputs": [ + { + "ename": "HDF5ExtError", + "evalue": "HDF5 error back trace\n\n File \"H5F.c\", line 836, in H5Fopen\n unable to synchronously open file\n File \"H5F.c\", line 796, in H5F__open_api_common\n unable to open file\n File \"H5VLcallback.c\", line 3863, in H5VL_file_open\n open failed\n File \"H5VLcallback.c\", line 3675, in H5VL__file_open\n open failed\n File \"H5VLnative_file.c\", line 128, in H5VL__native_file_open\n unable to open file\n File \"H5Fint.c\", line 2018, in H5F_open\n unable to read superblock\n File \"H5Fsuper.c\", line 600, in H5F__super_read\n truncated file: eof = 96, sblock->base_addr = 0, stored_eof = 2048\n\nEnd of HDF5 error back trace\n\nUnable to open/create file './POSYDON_main/outputs/candidate_main.h5'", + "output_type": "error", + "traceback": [ + "\u001b[31m---------------------------------------------------------------------------\u001b[39m", + "\u001b[31mHDF5ExtError\u001b[39m Traceback (most recent call last)", + "\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[4]\u001b[39m\u001b[32m, line 1\u001b[39m\n\u001b[32m----> \u001b[39m\u001b[32m1\u001b[39m df = \u001b[43mpd\u001b[49m\u001b[43m.\u001b[49m\u001b[43mread_hdf\u001b[49m\u001b[43m(\u001b[49m\u001b[33;43m'\u001b[39;49m\u001b[33;43m./POSYDON_main/outputs/candidate_main.h5\u001b[39;49m\u001b[33;43m'\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[33;43m\"\u001b[39;49m\u001b[33;43mevolution\u001b[39;49m\u001b[33;43m\"\u001b[39;49m\u001b[43m)\u001b[49m\n\u001b[32m 2\u001b[39m warnings = pd.read_hdf(\u001b[33m'\u001b[39m\u001b[33m./POSYDON_main/outputs/candidate_main.h5\u001b[39m\u001b[33m'\u001b[39m, \u001b[33m\"\u001b[39m\u001b[33mwarnings\u001b[39m\u001b[33m\"\u001b[39m)\n", + "\u001b[36mFile \u001b[39m\u001b[32m~/.conda/envs/valid/lib/python3.11/site-packages/pandas/io/pytables.py:426\u001b[39m, in \u001b[36mread_hdf\u001b[39m\u001b[34m(path_or_buf, key, mode, errors, where, start, stop, columns, iterator, chunksize, **kwargs)\u001b[39m\n\u001b[32m 423\u001b[39m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m exists:\n\u001b[32m 424\u001b[39m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mFileNotFoundError\u001b[39;00m(\u001b[33mf\u001b[39m\u001b[33m\"\u001b[39m\u001b[33mFile \u001b[39m\u001b[38;5;132;01m{\u001b[39;00mpath_or_buf\u001b[38;5;132;01m}\u001b[39;00m\u001b[33m does not exist\u001b[39m\u001b[33m\"\u001b[39m)\n\u001b[32m--> \u001b[39m\u001b[32m426\u001b[39m store = \u001b[43mHDFStore\u001b[49m\u001b[43m(\u001b[49m\u001b[43mpath_or_buf\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mmode\u001b[49m\u001b[43m=\u001b[49m\u001b[43mmode\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43merrors\u001b[49m\u001b[43m=\u001b[49m\u001b[43merrors\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43m*\u001b[49m\u001b[43m*\u001b[49m\u001b[43mkwargs\u001b[49m\u001b[43m)\u001b[49m\n\u001b[32m 427\u001b[39m \u001b[38;5;66;03m# can't auto open/close if we are using an iterator\u001b[39;00m\n\u001b[32m 428\u001b[39m \u001b[38;5;66;03m# so delegate to the iterator\u001b[39;00m\n\u001b[32m 429\u001b[39m auto_close = \u001b[38;5;28;01mTrue\u001b[39;00m\n", + "\u001b[36mFile \u001b[39m\u001b[32m~/.conda/envs/valid/lib/python3.11/site-packages/pandas/io/pytables.py:585\u001b[39m, in \u001b[36mHDFStore.__init__\u001b[39m\u001b[34m(self, path, mode, complevel, complib, fletcher32, **kwargs)\u001b[39m\n\u001b[32m 583\u001b[39m \u001b[38;5;28mself\u001b[39m._fletcher32 = fletcher32\n\u001b[32m 584\u001b[39m \u001b[38;5;28mself\u001b[39m._filters = \u001b[38;5;28;01mNone\u001b[39;00m\n\u001b[32m--> \u001b[39m\u001b[32m585\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[43m.\u001b[49m\u001b[43mopen\u001b[49m\u001b[43m(\u001b[49m\u001b[43mmode\u001b[49m\u001b[43m=\u001b[49m\u001b[43mmode\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43m*\u001b[49m\u001b[43m*\u001b[49m\u001b[43mkwargs\u001b[49m\u001b[43m)\u001b[49m\n", + "\u001b[36mFile \u001b[39m\u001b[32m~/.conda/envs/valid/lib/python3.11/site-packages/pandas/io/pytables.py:745\u001b[39m, in \u001b[36mHDFStore.open\u001b[39m\u001b[34m(self, mode, **kwargs)\u001b[39m\n\u001b[32m 739\u001b[39m msg = (\n\u001b[32m 740\u001b[39m \u001b[33m\"\u001b[39m\u001b[33mCannot open HDF5 file, which is already opened, \u001b[39m\u001b[33m\"\u001b[39m\n\u001b[32m 741\u001b[39m \u001b[33m\"\u001b[39m\u001b[33meven in read-only mode.\u001b[39m\u001b[33m\"\u001b[39m\n\u001b[32m 742\u001b[39m )\n\u001b[32m 743\u001b[39m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mValueError\u001b[39;00m(msg)\n\u001b[32m--> \u001b[39m\u001b[32m745\u001b[39m \u001b[38;5;28mself\u001b[39m._handle = \u001b[43mtables\u001b[49m\u001b[43m.\u001b[49m\u001b[43mopen_file\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[43m.\u001b[49m\u001b[43m_path\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[43m.\u001b[49m\u001b[43m_mode\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43m*\u001b[49m\u001b[43m*\u001b[49m\u001b[43mkwargs\u001b[49m\u001b[43m)\u001b[49m\n", + "\u001b[36mFile \u001b[39m\u001b[32m~/.conda/envs/valid/lib/python3.11/site-packages/tables/file.py:296\u001b[39m, in \u001b[36mopen_file\u001b[39m\u001b[34m(filename, mode, title, root_uep, filters, **kwargs)\u001b[39m\n\u001b[32m 291\u001b[39m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mValueError\u001b[39;00m(\n\u001b[32m 292\u001b[39m \u001b[33m\"\u001b[39m\u001b[33mThe file \u001b[39m\u001b[33m'\u001b[39m\u001b[38;5;132;01m%s\u001b[39;00m\u001b[33m'\u001b[39m\u001b[33m is already opened. Please \u001b[39m\u001b[33m\"\u001b[39m\n\u001b[32m 293\u001b[39m \u001b[33m\"\u001b[39m\u001b[33mclose it before reopening in write mode.\u001b[39m\u001b[33m\"\u001b[39m % filename)\n\u001b[32m 295\u001b[39m \u001b[38;5;66;03m# Finally, create the File instance, and return it\u001b[39;00m\n\u001b[32m--> \u001b[39m\u001b[32m296\u001b[39m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43mFile\u001b[49m\u001b[43m(\u001b[49m\u001b[43mfilename\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mmode\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mtitle\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mroot_uep\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mfilters\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43m*\u001b[49m\u001b[43m*\u001b[49m\u001b[43mkwargs\u001b[49m\u001b[43m)\u001b[49m\n", + "\u001b[36mFile \u001b[39m\u001b[32m~/.conda/envs/valid/lib/python3.11/site-packages/tables/file.py:746\u001b[39m, in \u001b[36mFile.__init__\u001b[39m\u001b[34m(self, filename, mode, title, root_uep, filters, **kwargs)\u001b[39m\n\u001b[32m 743\u001b[39m \u001b[38;5;28mself\u001b[39m.params = params\n\u001b[32m 745\u001b[39m \u001b[38;5;66;03m# Now, it is time to initialize the File extension\u001b[39;00m\n\u001b[32m--> \u001b[39m\u001b[32m746\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[43m.\u001b[49m\u001b[43m_g_new\u001b[49m\u001b[43m(\u001b[49m\u001b[43mfilename\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mmode\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43m*\u001b[49m\u001b[43m*\u001b[49m\u001b[43mparams\u001b[49m\u001b[43m)\u001b[49m\n\u001b[32m 748\u001b[39m \u001b[38;5;66;03m# Check filters and set PyTables format version for new files.\u001b[39;00m\n\u001b[32m 749\u001b[39m new = \u001b[38;5;28mself\u001b[39m._v_new\n", + "\u001b[36mFile \u001b[39m\u001b[32m~/.conda/envs/valid/lib/python3.11/site-packages/tables/hdf5extension.pyx:514\u001b[39m, in \u001b[36mtables.hdf5extension.File._g_new\u001b[39m\u001b[34m()\u001b[39m\n", + "\u001b[31mHDF5ExtError\u001b[39m: HDF5 error back trace\n\n File \"H5F.c\", line 836, in H5Fopen\n unable to synchronously open file\n File \"H5F.c\", line 796, in H5F__open_api_common\n unable to open file\n File \"H5VLcallback.c\", line 3863, in H5VL_file_open\n open failed\n File \"H5VLcallback.c\", line 3675, in H5VL__file_open\n open failed\n File \"H5VLnative_file.c\", line 128, in H5VL__native_file_open\n unable to open file\n File \"H5Fint.c\", line 2018, in H5F_open\n unable to read superblock\n File \"H5Fsuper.c\", line 600, in H5F__super_read\n truncated file: eof = 96, sblock->base_addr = 0, stored_eof = 2048\n\nEnd of HDF5 error back trace\n\nUnable to open/create file './POSYDON_main/outputs/candidate_main.h5'" + ] + } + ], + "source": [ + "df = pd.read_hdf('./POSYDON_main/outputs/candidate_main.h5', \"evolution\")\n", + "warnings = pd.read_hdf('./POSYDON_main/outputs/candidate_main.h5', \"warnings\")" + ] + }, + { + "cell_type": "code", + "execution_count": 56, + "id": "7028a060", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Index(['state', 'event', 'time', 'separation', 'orbital_period',\n", + " 'eccentricity', 'rl_relative_overflow_1', 'rl_relative_overflow_2',\n", + " 'lg_mtransfer_rate', 'mass_transfer_case',\n", + " ...\n", + " 'S2_mass_conv_reg_fortides', 'S2_thickness_conv_reg_fortides',\n", + " 'S2_radius_conv_reg_fortides', 'S2_lambda_CE_1cent',\n", + " 'S2_lambda_CE_10cent', 'S2_lambda_CE_30cent',\n", + " 'S2_lambda_CE_pure_He_star_10cent', 'S2_total_mass_h1',\n", + " 'S2_total_mass_he4', 'binary_id'],\n", + " dtype='object', length=134)\n" + ] + } + ], + "source": [ + "print(df.keys())" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "id": "76233b25", + "metadata": { + "collapsed": true + }, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
binary_idexception_typeexception_message
01ValueErrorTrying to store a string with len [27] in [S1_...
02ValueErrorTrying to store a string with len [12] in [sta...
03ValueErrorTrying to store a string with len [9] in [even...
04ValueErrorTrying to store a string with len [9] in [even...
05ValueErrorTrying to store a string with len [9] in [even...
07ValueErrorTrying to store a string with len [27] in [S1_...
08ValueErrorTrying to store a string with len [10] in [eve...
09ValueErrorTrying to store a string with len [7] in [even...
010ValueErrorTrying to store a string with len [27] in [S1_...
011ValueErrorTrying to store a string with len [7] in [even...
012ValueErrorTrying to store a string with len [7] in [even...
013ValueErrorTrying to store a string with len [7] in [even...
014ValueErrorTrying to store a string with len [23] in [S1_...
015ValueErrorTrying to store a string with len [9] in [even...
016ValueErrorTrying to store a string with len [9] in [even...
018ValueErrorTrying to store a string with len [7] in [even...
019ValueErrorTrying to store a string with len [7] in [even...
020ValueErrorTrying to store a string with len [7] in [even...
021ValueErrorTrying to store a string with len [7] in [even...
022ValueErrorTrying to store a string with len [9] in [even...
023ValueErrorTrying to store a string with len [9] in [even...
024ValueErrorTrying to store a string with len [9] in [even...
025ValueErrorTrying to store a string with len [7] in [even...
026ValueErrorTrying to store a string with len [9] in [even...
027ValueErrorTrying to store a string with len [7] in [even...
028ValueErrorTrying to store a string with len [7] in [even...
029ValueErrorTrying to store a string with len [7] in [even...
030ValueErrorTrying to store a string with len [7] in [even...
031ValueErrorTrying to store a string with len [7] in [even...
032ValueErrorTrying to store a string with len [7] in [even...
033ValueErrorTrying to store a string with len [7] in [even...
034ValueErrorTrying to store a string with len [7] in [even...
035ValueErrorTrying to store a string with len [9] in [even...
036ValueErrorTrying to store a string with len [7] in [even...
037ValueErrorTrying to store a string with len [10] in [eve...
038ValueErrorTrying to store a string with len [9] in [even...
039MatchingErrorGrid matching failed for merged binary. \\nseco...
040ClassificationErrorBinary is in the detached step but has stable ...
041ValueErrorTrying to store a string with len [7] in [even...
042FlowErrorEvolution of H-rich/He-rich stars in RLO onto ...
043ValueErrorTrying to store a string with len [7] in [even...
\n", + "
" + ], + "text/plain": [ + " binary_id exception_type \\\n", + "0 1 ValueError \n", + "0 2 ValueError \n", + "0 3 ValueError \n", + "0 4 ValueError \n", + "0 5 ValueError \n", + "0 7 ValueError \n", + "0 8 ValueError \n", + "0 9 ValueError \n", + "0 10 ValueError \n", + "0 11 ValueError \n", + "0 12 ValueError \n", + "0 13 ValueError \n", + "0 14 ValueError \n", + "0 15 ValueError \n", + "0 16 ValueError \n", + "0 18 ValueError \n", + "0 19 ValueError \n", + "0 20 ValueError \n", + "0 21 ValueError \n", + "0 22 ValueError \n", + "0 23 ValueError \n", + "0 24 ValueError \n", + "0 25 ValueError \n", + "0 26 ValueError \n", + "0 27 ValueError \n", + "0 28 ValueError \n", + "0 29 ValueError \n", + "0 30 ValueError \n", + "0 31 ValueError \n", + "0 32 ValueError \n", + "0 33 ValueError \n", + "0 34 ValueError \n", + "0 35 ValueError \n", + "0 36 ValueError \n", + "0 37 ValueError \n", + "0 38 ValueError \n", + "0 39 MatchingError \n", + "0 40 ClassificationError \n", + "0 41 ValueError \n", + "0 42 FlowError \n", + "0 43 ValueError \n", + "\n", + " exception_message \n", + "0 Trying to store a string with len [27] in [S1_... \n", + "0 Trying to store a string with len [12] in [sta... \n", + "0 Trying to store a string with len [9] in [even... \n", + "0 Trying to store a string with len [9] in [even... \n", + "0 Trying to store a string with len [9] in [even... \n", + "0 Trying to store a string with len [27] in [S1_... \n", + "0 Trying to store a string with len [10] in [eve... \n", + "0 Trying to store a string with len [7] in [even... \n", + "0 Trying to store a string with len [27] in [S1_... \n", + "0 Trying to store a string with len [7] in [even... \n", + "0 Trying to store a string with len [7] in [even... \n", + "0 Trying to store a string with len [7] in [even... \n", + "0 Trying to store a string with len [23] in [S1_... \n", + "0 Trying to store a string with len [9] in [even... \n", + "0 Trying to store a string with len [9] in [even... \n", + "0 Trying to store a string with len [7] in [even... \n", + "0 Trying to store a string with len [7] in [even... \n", + "0 Trying to store a string with len [7] in [even... \n", + "0 Trying to store a string with len [7] in [even... \n", + "0 Trying to store a string with len [9] in [even... \n", + "0 Trying to store a string with len [9] in [even... \n", + "0 Trying to store a string with len [9] in [even... \n", + "0 Trying to store a string with len [7] in [even... \n", + "0 Trying to store a string with len [9] in [even... \n", + "0 Trying to store a string with len [7] in [even... \n", + "0 Trying to store a string with len [7] in [even... \n", + "0 Trying to store a string with len [7] in [even... \n", + "0 Trying to store a string with len [7] in [even... \n", + "0 Trying to store a string with len [7] in [even... \n", + "0 Trying to store a string with len [7] in [even... \n", + "0 Trying to store a string with len [7] in [even... \n", + "0 Trying to store a string with len [7] in [even... \n", + "0 Trying to store a string with len [9] in [even... \n", + "0 Trying to store a string with len [7] in [even... \n", + "0 Trying to store a string with len [10] in [eve... \n", + "0 Trying to store a string with len [9] in [even... \n", + "0 Grid matching failed for merged binary. \\nseco... \n", + "0 Binary is in the detached step but has stable ... \n", + "0 Trying to store a string with len [7] in [even... \n", + "0 Evolution of H-rich/He-rich stars in RLO onto ... \n", + "0 Trying to store a string with len [7] in [even... " + ] + }, + "execution_count": 20, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "errors" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "68d4d8a8", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "valid", + "language": "python", + "name": "valid" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.11.14" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/dev-tools/compare_runs.py b/dev-tools/compare_runs.py index 6ff28d81e2..0d2fe2df7e 100644 --- a/dev-tools/compare_runs.py +++ b/dev-tools/compare_runs.py @@ -1,75 +1,412 @@ #!/usr/bin/env python3 - """ -Compare evolution outcomes of set of binaries saved to file with script_data/1Zsun_binaries_suite.py -Used for validation of the branch. +Compare evolution outcomes of test binaries saved by binaries_suite.py. -Author: Elizabeth Teng -""" +Reports three categories of differences: + 1. QUANTITATIVE: any numeric difference beyond floating-point representation + 2. QUALITATIVE: changes to categorical/string columns (states, events, step names, SN types, etc.) + 3. WARNINGS & ERRORS: changes to warnings raised or binaries that error out +By default, uses exact comparison (atol=0, rtol=0). The --loose flag enables +a small tolerance for cases where minor floating-point differences are expected. -import sys +Usage: + python compare_runs.py baseline.h5 candidate.h5 + python compare_runs.py baseline.h5 candidate.h5 --verbose + python compare_runs.py baseline.h5 candidate.h5 --loose + +Authors: Elizabeth Teng +""" -import h5py +import argparse +import sys +import os import numpy as np +import pandas as pd -def compare_datasets(base, cand, path="/"): - """ - Recursively compare HDF5 datasets. - Returns a list of strings with differences. +# Columns that represent qualitative (categorical) evolution properties. +# Any column matching these names will be compared as exact string matches +# and reported under "QUALITATIVE" differences. +QUALITATIVE_COLUMNS = { + 'state', 'event', 'step_names', 'S1_state', 'S2_state', + 'SN_type', 'S1_SN_type', 'S2_SN_type', + 'interp_class_HMS_HMS', 'interp_class_CO_HMS_RLO', + 'interp_class_CO_HeMS', 'interp_class_CO_HeMS_RLO', + 'mt_history_HMS_HMS', 'mt_history_CO_HMS_RLO', + 'mt_history_CO_HeMS', 'mt_history_CO_HeMS_RLO', + 'mass_transfer_case', +} + + +def classify_column(col, dtype): + """Classify a column as 'qualitative' or 'quantitative'.""" + if col in QUALITATIVE_COLUMNS: + return 'qualitative' + if pd.api.types.is_numeric_dtype(dtype): + return 'quantitative' + # Catch-all: treat remaining object/string columns as qualitative + return 'qualitative' + + +def compare_evolution_tables(base_df, cand_df, rtol, atol): + """Compare two evolution DataFrames, reporting per-binary diffs. + + Returns: + dict with keys 'quantitative', 'qualitative', 'structural' + each mapping to a list of diff strings. """ - differences = [] + quant_diffs = [] + qual_diffs = [] + struct_diffs = [] + + # Check that binary_id columns exist + if 'binary_id' not in base_df.columns or 'binary_id' not in cand_df.columns: + struct_diffs.append("'binary_id' column missing; cannot do per-binary comparison") + return {'quantitative': quant_diffs, 'qualitative': qual_diffs, 'structural': struct_diffs} + + base_ids = set(base_df['binary_id'].unique()) + cand_ids = set(cand_df['binary_id'].unique()) + + # Missing/extra binaries + for bid in sorted(base_ids - cand_ids): + struct_diffs.append(f"Binary {bid}: MISSING in candidate") + for bid in sorted(cand_ids - base_ids): + struct_diffs.append(f"Binary {bid}: EXTRA in candidate") + + common_ids = sorted(base_ids & cand_ids) - for key in base.keys(): - base_item = base[key] - if key not in cand: - differences.append(f"{path}{key} missing in candidate") + for bid in common_ids: + b = base_df[base_df['binary_id'] == bid].reset_index(drop=True) + c = cand_df[cand_df['binary_id'] == bid].reset_index(drop=True) + + # ── Error status changes ────────────────────────────────────── + base_failed = 'exception_type' in b.columns and b['exception_type'].notna().any() + cand_failed = 'exception_type' in c.columns and c['exception_type'].notna().any() + + if base_failed != cand_failed: + if cand_failed: + exc = c['exception_type'].dropna().iloc[0] if 'exception_type' in c.columns else "unknown" + msg = c['exception_message'].dropna().iloc[0] if 'exception_message' in c.columns else "" + struct_diffs.append(f"Binary {bid}: NEWLY FAILING ({exc}: {msg})") + else: + struct_diffs.append(f"Binary {bid}: NEWLY PASSING (was failing in baseline)") + continue + + if base_failed and cand_failed: + b_exc = str(b['exception_type'].dropna().iloc[0]) if 'exception_type' in b.columns else "" + c_exc = str(c['exception_type'].dropna().iloc[0]) if 'exception_type' in c.columns else "" + b_msg = str(b['exception_message'].dropna().iloc[0]) if 'exception_message' in b.columns else "" + c_msg = str(c['exception_message'].dropna().iloc[0]) if 'exception_message' in c.columns else "" + if b_exc != c_exc: + struct_diffs.append(f"Binary {bid}: error type changed ('{b_exc}' -> '{c_exc}')") + if b_msg != c_msg: + struct_diffs.append(f"Binary {bid}: error message changed ('{b_msg}' -> '{c_msg}')") continue - cand_item = cand[key] + # ── Step count ──────────────────────────────────────────────── + if len(b) != len(c): + struct_diffs.append( + f"Binary {bid}: evolution step count differs " + f"(baseline={len(b)}, candidate={len(c)})" + ) + + # ── Column presence ─────────────────────────────────────────── + base_only_cols = set(b.columns) - set(c.columns) - {'binary_id'} + cand_only_cols = set(c.columns) - set(b.columns) - {'binary_id'} + if base_only_cols: + struct_diffs.append(f"Binary {bid}: columns only in baseline: {sorted(base_only_cols)}") + if cand_only_cols: + struct_diffs.append(f"Binary {bid}: columns only in candidate: {sorted(cand_only_cols)}") + + # ── Per-column comparison ───────────────────────────────────── + common_cols = sorted(set(b.columns) & set(c.columns) - {'binary_id'}) + min_rows = min(len(b), len(c)) + + for col in common_cols: + b_col = b[col].iloc[:min_rows] + c_col = c[col].iloc[:min_rows] + col_type = classify_column(col, b_col.dtype) - if isinstance(base_item, h5py.Dataset): - base_data = base_item[()] - cand_data = cand_item[()] + if col_type == 'quantitative': + b_arr = b_col.to_numpy(dtype=float) + c_arr = c_col.to_numpy(dtype=float) + + # NaN handling: both NaN = match, one NaN = mismatch + both_nan = np.isnan(b_arr) & np.isnan(c_arr) + one_nan = np.isnan(b_arr) ^ np.isnan(c_arr) + + if one_nan.any(): + nan_steps = np.where(one_nan)[0].tolist() + direction = [] + for s in nan_steps[:5]: + bv = "NaN" if np.isnan(b_arr[s]) else f"{b_arr[s]:.6g}" + cv = "NaN" if np.isnan(c_arr[s]) else f"{c_arr[s]:.6g}" + direction.append(f"step {s}: {bv} -> {cv}") + quant_diffs.append( + f"Binary {bid}, '{col}': NaN mismatch at {len(nan_steps)} step(s): " + + "; ".join(direction) + ) + + # Compare non-NaN values + valid = ~(np.isnan(b_arr) | np.isnan(c_arr)) + if valid.any(): + b_valid = b_arr[valid] + c_valid = c_arr[valid] + not_equal = b_valid != c_valid + + if rtol == 0 and atol == 0: + # Exact comparison + if not_equal.any(): + diff_indices = np.where(valid)[0][not_equal] + abs_diff = np.abs(b_valid[not_equal] - c_valid[not_equal]) + worst = np.argmax(abs_diff) + worst_step = diff_indices[worst] + quant_diffs.append( + f"Binary {bid}, '{col}': {not_equal.sum()} value(s) differ. " + f"Largest abs diff = {abs_diff[worst]:.6e} " + f"at step {worst_step} " + f"(baseline={b_valid[not_equal][worst]:.15g}, " + f"candidate={c_valid[not_equal][worst]:.15g})" + ) + else: + # Tolerance-based comparison + if not np.allclose(b_valid, c_valid, rtol=rtol, atol=atol): + abs_diff = np.abs(b_valid - c_valid) + with np.errstate(divide='ignore', invalid='ignore'): + denom = np.maximum(np.abs(b_valid), atol) + rel_diff = abs_diff / denom + worst = np.argmax(abs_diff) + worst_step = np.where(valid)[0][worst] + quant_diffs.append( + f"Binary {bid}, '{col}': numeric mismatch " + f"(max abs diff = {abs_diff[worst]:.6e}, " + f"max rel diff = {rel_diff[worst]:.6e}, " + f"at step {worst_step}, " + f"baseline={b_valid[worst]:.15g}, " + f"candidate={c_valid[worst]:.15g})" + ) - if np.issubdtype(base_data.dtype, np.number): - if not np.allclose(base_data, cand_data, rtol=1e-5, atol=1e-8): - differences.append(f"{path}{key} numeric mismatch") else: - if not np.array_equal(base_data, cand_data): - differences.append(f"{path}{key} non-numeric mismatch") + # Qualitative comparison: exact string match + b_str = b_col.astype(str).values + c_str = c_col.astype(str).values + mismatches = np.where(b_str != c_str)[0] + if len(mismatches) > 0: + details = [] + for s in mismatches[:5]: + details.append(f"step {s}: '{b_str[s]}' -> '{c_str[s]}'") + qual_diffs.append( + f"Binary {bid}, '{col}': {len(mismatches)} step(s) differ: " + + "; ".join(details) + ) - elif isinstance(base_item, h5py.Group): - differences.extend(compare_datasets(base_item, cand_item, path=f"{path}{key}/")) + return {'quantitative': quant_diffs, 'qualitative': qual_diffs, 'structural': struct_diffs} - # Check for extra keys in candidate - for key in cand.keys(): - if key not in base: - differences.append(f"{path}{key} extra in candidate") - return differences +def compare_warnings_tables(base_df, cand_df): + """Compare warning tables between baseline and candidate. + + Returns list of diff strings. + """ + diffs = [] + + if base_df is None and cand_df is None: + return diffs + if base_df is None: + diffs.append(f"Candidate has {len(cand_df)} warning(s), baseline has none") + return diffs + if cand_df is None: + diffs.append(f"Baseline has {len(base_df)} warning(s), candidate has none") + return diffs + + if len(base_df) != len(cand_df): + diffs.append(f"Total warning count differs (baseline={len(base_df)}, candidate={len(cand_df)})") + + # Per-binary warning comparison + if 'binary_id' in base_df.columns and 'binary_id' in cand_df.columns: + base_grouped = base_df.groupby('binary_id') + cand_grouped = cand_df.groupby('binary_id') + all_ids = sorted(set(base_df['binary_id'].unique()) | set(cand_df['binary_id'].unique())) + + for bid in all_ids: + b_warnings = base_grouped.get_group(bid) if bid in base_grouped.groups else pd.DataFrame() + c_warnings = cand_grouped.get_group(bid) if bid in cand_grouped.groups else pd.DataFrame() + + b_count = len(b_warnings) + c_count = len(c_warnings) + + if b_count == 0 and c_count > 0: + cats = c_warnings['category'].unique().tolist() if 'category' in c_warnings.columns else ['unknown'] + diffs.append(f"Binary {bid}: {c_count} NEW warning(s) in candidate ({', '.join(str(c) for c in cats)})") + elif b_count > 0 and c_count == 0: + diffs.append(f"Binary {bid}: {b_count} warning(s) REMOVED in candidate") + elif b_count != c_count: + diffs.append(f"Binary {bid}: warning count changed ({b_count} -> {c_count})") + elif b_count > 0: + # Same count — check if warning categories or messages changed + if 'category' in b_warnings.columns and 'category' in c_warnings.columns: + b_cats = sorted(b_warnings['category'].astype(str).tolist()) + c_cats = sorted(c_warnings['category'].astype(str).tolist()) + if b_cats != c_cats: + diffs.append(f"Binary {bid}: warning categories changed ({b_cats} -> {c_cats})") + + if 'message' in b_warnings.columns and 'message' in c_warnings.columns: + b_msgs = sorted(b_warnings['message'].astype(str).tolist()) + c_msgs = sorted(c_warnings['message'].astype(str).tolist()) + if b_msgs != c_msgs: + diffs.append(f"Binary {bid}: warning messages changed") + + return diffs + + +def read_table_safe(store, key): + """Read a table from HDFStore, returning None if it doesn't exist.""" + try: + if key in store: + return store[key] + except Exception: + pass + return None def main(): - if len(sys.argv) != 3: - print("Usage: compare_runs.py baseline.h5 candidate.h5") - sys.exit(1) + parser = argparse.ArgumentParser( + description="Compare baseline and candidate binary evolution HDF5 files.", + formatter_class=argparse.RawDescriptionHelpFormatter, + epilog=""" +By default, uses EXACT comparison (any numeric difference is reported). +Use --loose to allow small floating-point tolerances (rtol=1e-12, atol=1e-15). + """, + ) + parser.add_argument("baseline", help="Path to baseline HDF5 file") + parser.add_argument("candidate", help="Path to candidate HDF5 file") + parser.add_argument("--loose", action="store_true", + help="Allow small floating-point tolerance (rtol=1e-12, atol=1e-15)") + parser.add_argument("--rtol", type=float, default=None, + help="Override relative tolerance (default: 0, or 1e-12 with --loose)") + parser.add_argument("--atol", type=float, default=None, + help="Override absolute tolerance (default: 0, or 1e-15 with --loose)") + parser.add_argument("--verbose", "-v", action="store_true", + help="Print extra diagnostic info") + args = parser.parse_args() - baseline_file = sys.argv[1] - candidate_file = sys.argv[2] + # Set tolerances + if args.loose: + rtol = args.rtol if args.rtol is not None else 1e-12 + atol = args.atol if args.atol is not None else 1e-15 + else: + rtol = args.rtol if args.rtol is not None else 0.0 + atol = args.atol if args.atol is not None else 0.0 - with h5py.File(baseline_file, 'r') as base, h5py.File(candidate_file, 'r') as cand: - diffs = compare_datasets(base, cand) + for f in [args.baseline, args.candidate]: + if not os.path.exists(f): + print(f"ERROR: File not found: {f}", file=sys.stderr) + sys.exit(2) - if diffs: - print("Differences found:") - for diff in diffs: - print(" -", diff) - sys.exit(1) + quant_diffs = [] + qual_diffs = [] + struct_diffs = [] + warn_diffs = [] + + try: + with pd.HDFStore(args.baseline, mode='r') as base_store, \ + pd.HDFStore(args.candidate, mode='r') as cand_store: + + base_keys = set(base_store.keys()) + cand_keys = set(cand_store.keys()) + + if args.verbose: + print(f"Baseline keys: {sorted(base_keys)}") + print(f"Candidate keys: {sorted(cand_keys)}") + + # ── Evolution table ─────────────────────────────────────── + base_evol = read_table_safe(base_store, '/evolution') + cand_evol = read_table_safe(cand_store, '/evolution') + + if base_evol is None and cand_evol is None: + struct_diffs.append("Neither file contains an 'evolution' table") + elif base_evol is None: + struct_diffs.append("Baseline missing 'evolution' table") + elif cand_evol is None: + struct_diffs.append("Candidate missing 'evolution' table") + else: + if args.verbose: + n_base = base_evol['binary_id'].nunique() if 'binary_id' in base_evol.columns else '?' + n_cand = cand_evol['binary_id'].nunique() if 'binary_id' in cand_evol.columns else '?' + print(f"Baseline: {n_base} binaries, {len(base_evol)} total rows") + print(f"Candidate: {n_cand} binaries, {len(cand_evol)} total rows") + + evol_results = compare_evolution_tables(base_evol, cand_evol, rtol, atol) + quant_diffs.extend(evol_results['quantitative']) + qual_diffs.extend(evol_results['qualitative']) + struct_diffs.extend(evol_results['structural']) + + # ── Warnings table ──────────────────────────────────────── + base_warn = read_table_safe(base_store, '/warnings') + cand_warn = read_table_safe(cand_store, '/warnings') + warn_diffs.extend(compare_warnings_tables(base_warn, cand_warn)) + + # ── Extra/missing top-level keys ────────────────────────── + for k in sorted(base_keys - cand_keys): + if k not in ['/evolution', '/warnings', '/metadata']: + struct_diffs.append(f"Table '{k}' missing in candidate") + for k in sorted(cand_keys - base_keys): + if k not in ['/evolution', '/warnings', '/metadata']: + struct_diffs.append(f"Table '{k}' extra in candidate") + + except Exception as e: + print(f"ERROR reading HDF5 files: {e}", file=sys.stderr) + sys.exit(2) + + # ── Report ──────────────────────────────────────────────────────────── + total_diffs = len(quant_diffs) + len(qual_diffs) + len(struct_diffs) + len(warn_diffs) + tol_label = f"rtol={rtol}, atol={atol}" if rtol > 0 or atol > 0 else "EXACT (rtol=0, atol=0)" + + print("=" * 70) + print("POSYDON Binary Validation — Comparison Report") + print(f" Baseline: {args.baseline}") + print(f" Candidate: {args.candidate}") + print(f" Tolerances: {tol_label}") + print("=" * 70) + + if struct_diffs: + print(f"\n--- STRUCTURAL ({len(struct_diffs)}) ---") + print(" (missing/extra binaries, step count changes, newly failing/passing, errors)\n") + for d in struct_diffs: + print(f" - {d}") + + if qual_diffs: + print(f"\n--- QUALITATIVE ({len(qual_diffs)}) ---") + print(" (state, event, step name, SN type, interpolation class changes)\n") + for d in qual_diffs: + print(f" - {d}") + + if quant_diffs: + print(f"\n--- QUANTITATIVE ({len(quant_diffs)}) ---") + print(" (any numeric value change)\n") + for d in quant_diffs: + print(f" - {d}") + + if warn_diffs: + print(f"\n--- WARNINGS ({len(warn_diffs)}) ---") + print(" (new, removed, or changed warnings)\n") + for d in warn_diffs: + print(f" - {d}") + + print("\n" + "=" * 70) + if total_diffs == 0: + print("RESULT: IDENTICAL — candidate matches baseline exactly.") + sys.exit(0) else: - print("No differences detected between baseline and candidate.") + print(f"RESULT: {total_diffs} DIFFERENCE(S) DETECTED") + print(f" Structural: {len(struct_diffs)}") + print(f" Qualitative: {len(qual_diffs)}") + print(f" Quantitative: {len(quant_diffs)}") + print(f" Warnings: {len(warn_diffs)}") + print("=" * 70) + sys.exit(1) if __name__ == "__main__": - main() + main() \ No newline at end of file diff --git a/dev-tools/evolve_binaries.sh b/dev-tools/evolve_binaries.sh index 2021995bff..8bfcceef2a 100755 --- a/dev-tools/evolve_binaries.sh +++ b/dev-tools/evolve_binaries.sh @@ -1,69 +1,86 @@ #!/bin/bash -# Script usage: ./evolve_binaries.sh -# This script clones the POSYDON repo to the specified branch (defaults to 'main'), -# copies evolve_binaries.py, runs it, and saves output to evolve_binaries.out - -# Set default branch to 'main' if not provided -BRANCH=${1:-main} -REPO_URL="https://github.com/POSYDON-code/POSYDON" - -if [[ -n "$2" ]]; then - SHA=$2 - WORK_DIR="POSYDON_${BRANCH}_${SHA}" -else - WORK_DIR="POSYDON_$BRANCH" -fi - -# Remove existing directory if it exists -if [ -d "$WORK_DIR" ]; then - echo "šŸ—‘ļø Removing existing directory: $WORK_DIR" - rm -rf "$WORK_DIR" +# ============================================================================= +# evolve_binaries.sh — Clone a POSYDON branch, install it, and run the +# binary validation suite at all requested metallicities. +# +# Usage: +# ./evolve_binaries.sh [sha] [metallicities] +# +# Examples: +# ./evolve_binaries.sh main # all metallicities +# ./evolve_binaries.sh feature/my-fix abc123f # specific commit +# ./evolve_binaries.sh main "" "1 0.45 0.1" # subset of metallicities +# +# Output structure: +# outputs//candidate_Zsun.h5 — evolution results per metallicity +# logs//evolve_Zsun.log — log per metallicity +# workdirs/POSYDON_/ — cloned repo + conda env +# ============================================================================= + +set -euo pipefail +# Load git if needed +if ! command -v git >/dev/null 2>&1; then + if command -v module >/dev/null 2>&1; then + module load git + fi fi -echo "šŸ“ Creating working directory: $WORK_DIR" -# Create the working directory -mkdir -p "$WORK_DIR" +# ── Configuration ────────────────────────────────────────────────────────── +ALL_METALLICITIES="2 1 0.45 0.2 0.1 0.01 0.001 0.0001" -FULL_PATH="$(realpath "$WORK_DIR")" -CLONE_DIR="$FULL_PATH/POSYDON" +BRANCH=${1:-main} +SHA=${2:-} +METALLICITIES=${3:-$ALL_METALLICITIES} -OUTPUT_DIR="$FULL_PATH/outputs" -LOG_DIR="$FULL_PATH/logs" +REPO_URL="https://github.com/POSYDON-code/POSYDON" +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +# Sanitize branch name for filesystem SAFE_BRANCH="${BRANCH//\//_}" -OUTPUT_FILE="$OUTPUT_DIR/candidate_${SAFE_BRANCH}.h5" -LOG_FILE="$LOG_DIR/evolve_${SAFE_BRANCH}.log" -mkdir -p "$OUTPUT_DIR" "$LOG_DIR" -echo "šŸ“‹ Copying script_data folder" -# copy the script_data folder -cp -r "./script_data" "$WORK_DIR" +# Directories (all relative to SCRIPT_DIR, the dev-tools root) +WORK_DIR="$SCRIPT_DIR/workdirs/POSYDON_${SAFE_BRANCH}" +OUTPUT_DIR="$SCRIPT_DIR/outputs/${SAFE_BRANCH}" +LOG_DIR="$SCRIPT_DIR/logs/${SAFE_BRANCH}" +CLONE_DIR="$WORK_DIR/POSYDON" -cd "$WORK_DIR" +mkdir -p "$OUTPUT_DIR" "$LOG_DIR" -# Initialize conda for bash +# ── Conda Setup ──────────────────────────────────────────────────────────── echo "šŸ”§ Initializing conda" -# Source conda's shell integration -if [ -f "$HOME/miniconda3/etc/profile.d/conda.sh" ]; then - source "$HOME/miniconda3/etc/profile.d/conda.sh" -elif [ -f "$HOME/anaconda3/etc/profile.d/conda.sh" ]; then - source "$HOME/anaconda3/etc/profile.d/conda.sh" -elif [ -f "/opt/homebrew/Caskroom/miniconda/base/etc/profile.d/conda.sh" ]; then - source "/opt/homebrew/Caskroom/miniconda/base/etc/profile.d/conda.sh" -elif command -v conda >/dev/null 2>&1; then - CONDA_BASE=$(conda info --base) - source "${CONDA_BASE}/etc/profile.d/conda.sh" -else - echo -e "\033[31mError: Could not find conda installation. Please check your conda setup.\033[0m" - exit 1 +CONDA_SH="" +for candidate in \ + "$HOME/miniconda3/etc/profile.d/conda.sh" \ + "$HOME/anaconda3/etc/profile.d/conda.sh" \ + "/opt/homebrew/Caskroom/miniconda/base/etc/profile.d/conda.sh"; do + if [ -f "$candidate" ]; then + CONDA_SH="$candidate" + break + fi +done + +if [ -z "$CONDA_SH" ]; then + if command -v conda >/dev/null 2>&1; then + CONDA_SH="$(conda info --base)/etc/profile.d/conda.sh" + else + echo "ERROR: Could not find conda installation." >&2 + exit 1 + fi fi +source "$CONDA_SH" + +# ── Clone Repository ────────────────────────────────────────────────────── +if [ -d "$WORK_DIR" ]; then + echo "šŸ—‘ļø Removing existing work directory: $WORK_DIR" + rm -rf "$WORK_DIR" +fi +mkdir -p "$WORK_DIR" -# Clone the repository to the specified branch echo "šŸ”„ Cloning POSYDON repository (branch: $BRANCH)" -if ! git clone -b "$BRANCH" "$REPO_URL" "$CLONE_DIR" 2>&1 | sed 's/^/ /'; then - echo -e "\033[31mError: Failed to clone branch '$BRANCH'. Please check if the branch exists.\033[0m" +if ! git clone -b "$BRANCH" "$REPO_URL" "$CLONE_DIR" 2>&1 | sed 's/^/ /'; then + echo "ERROR: Failed to clone branch '$BRANCH'." >&2 exit 1 fi @@ -78,29 +95,59 @@ if [[ -n "$SHA" ]]; then cd - fi -# Create conda environment for POSYDON v2 -echo "šŸ Creating conda environment" -conda create --prefix="$FULL_PATH/conda_env" python=3.11 -y -q 2>&1 | sed 's/^/ /' +# ── Create Conda Environment ───────────────────────────────────────────── +ENV_PREFIX="$WORK_DIR/conda_env" -echo "⚔ Activating conda environment" -conda activate "$FULL_PATH/conda_env" +echo "šŸ Creating conda environment at $ENV_PREFIX" +conda create --prefix="$ENV_PREFIX" python=3.11 -y -q 2>&1 | sed 's/^/ /' +conda activate "$ENV_PREFIX" -# install POSYDON manually echo "šŸ“¦ Installing POSYDON" -pip install -e "$CLONE_DIR" -q 2>&1 | sed 's/^/ /' - -echo "šŸš€ Running evolve_binaries.py" -# # Run the Python script and capture output (stdout and stderr) -python script_data/1Zsun_binaries_suite.py --output "$OUTPUT_FILE" 2>&1 | tee "$LOG_FILE" +pip install -e "$CLONE_DIR" -q 2>&1 | sed 's/^/ /' + +# ── Run Suite for Each Metallicity ──────────────────────────────────────── +SUITE_SCRIPT="$SCRIPT_DIR/script_data/binaries_suite.py" +FAILED=0 + +for Z in $METALLICITIES; do + OUTPUT_FILE="$OUTPUT_DIR/candidate_${Z}Zsun.h5" + LOG_FILE="$LOG_DIR/evolve_${Z}Zsun.log" + + echo "" + echo "============================================================" + echo " šŸš€ Evolving binaries for Z = ${Z} Zsun" + echo " Output: $OUTPUT_FILE" + echo " Log: $LOG_FILE" + echo "============================================================" + + if python "$SUITE_SCRIPT" \ + --metallicity "$Z" \ + --output "$OUTPUT_FILE" \ + 2>&1 | tee "$LOG_FILE"; then + + if [ ! -f "$OUTPUT_FILE" ]; then + echo "WARNING: Output file not created for Z=${Z}" >&2 + FAILED=$((FAILED + 1)) + else + echo " Z=${Z} Zsun complete." + fi + else + echo "WARNING: Suite failed for Z=${Z}. Check $LOG_FILE" >&2 + FAILED=$((FAILED + 1)) + fi +done -if [ ! -f "$OUTPUT_FILE" ]; then - echo "ERROR: Results file was not created: $OUTPUT_FILE" - exit 2 -fi +# ── Deactivate Environment ──────────────────────────────────────────────── +conda deactivate -if [ $? -ne 0 ]; then - echo "ERROR: Python script exited with an error. Check $LOG_FILE for details." - exit 3 +echo "" +echo "============================================================" +if [ $FAILED -eq 0 ]; then + echo "āœ… All metallicities completed successfully." +else + echo "Completed with $FAILED failure(s)." fi +echo " Outputs in: $OUTPUT_DIR/" +echo "============================================================" -echo -e "āœ… Script completed. Output saved to \n$OUTPUT_FILE" +exit $FAILED \ No newline at end of file diff --git a/dev-tools/generate_baseline.sh b/dev-tools/generate_baseline.sh new file mode 100644 index 0000000000..a4e31534a7 --- /dev/null +++ b/dev-tools/generate_baseline.sh @@ -0,0 +1,96 @@ +#!/bin/bash +# ============================================================================= +# generate_baseline.sh — Generate baseline HDF5 files from a designated branch. +# +# This runs the binary validation suite against a chosen branch (or commit) +# and saves the results as the baseline for future comparisons. +# +# Usage: +# ./generate_baseline.sh [sha] [metallicities] +# +# Examples: +# ./generate_baseline.sh main # baseline from main, all Z +# ./generate_baseline.sh v2.1.0 # baseline from a release tag +# ./generate_baseline.sh main abc123f # baseline from a specific commit +# ./generate_baseline.sh main "" "1 0.45" # baseline for subset of Z +# +# Output: +# baselines//baseline_Zsun.h5 — one file per metallicity +# baselines//baseline_info.txt — records branch, commit SHA, date +# ============================================================================= + +set -euo pipefail + +BRANCH=${1:-main} +SHA=${2:-} +METALLICITIES=${3:-"2 1 0.45 0.2 0.1 0.01 0.001 0.0001"} + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +SAFE_BRANCH="${BRANCH//\//_}" +BASELINE_DIR="$SCRIPT_DIR/baselines/${SAFE_BRANCH}" + +echo "============================================================" +echo " POSYDON Binary Validation — Generating Baseline" +echo " Branch: $BRANCH" +echo " SHA: ${SHA:-HEAD}" +echo " Metallicities: $METALLICITIES" +echo " Output dir: $BASELINE_DIR" +echo "============================================================" + +# ── Step 1: Evolve binaries for the baseline branch ────────────────────── +echo "" +echo "Step 1: Evolving binaries on branch '$BRANCH'..." +"$SCRIPT_DIR/evolve_binaries.sh" "$BRANCH" "$SHA" "$METALLICITIES" + +# ── Step 2: Copy results into the baselines directory ──────────────────── +echo "" +echo "Step 2: Copying results to baseline directory..." + +mkdir -p "$BASELINE_DIR" + +CANDIDATE_DIR="$SCRIPT_DIR/outputs/${SAFE_BRANCH}" +COPIED=0 + +for Z in $METALLICITIES; do + SRC="$CANDIDATE_DIR/candidate_${Z}Zsun.h5" + DST="$BASELINE_DIR/baseline_${Z}Zsun.h5" + + if [ -f "$SRC" ]; then + cp "$SRC" "$DST" + echo " Saved: $DST" + COPIED=$((COPIED + 1)) + else + echo " WARNING: Missing output for Z=${Z}: $SRC" >&2 + fi +done + +# ── Step 3: Record baseline metadata ───────────────────────────────────── +CLONE_DIR="$SCRIPT_DIR/workdirs/POSYDON_${SAFE_BRANCH}/POSYDON" +ACTUAL_SHA="" +if [ -d "$CLONE_DIR" ]; then + ACTUAL_SHA=$(cd "$CLONE_DIR" && git rev-parse HEAD 2>/dev/null || echo "unknown") +fi + +INFO_FILE="$BASELINE_DIR/baseline_info.txt" +cat > "$INFO_FILE" << EOF +POSYDON Binary Validation Baseline +=================================== +Branch: $BRANCH +Commit SHA: ${ACTUAL_SHA:-unknown} +Requested SHA: ${SHA:-HEAD} +Generated: $(date -u '+%Y-%m-%d %H:%M:%S UTC') +Metallicities: $METALLICITIES +Files: $COPIED +EOF + +echo "" +echo "============================================================" +echo " Baseline generated: $COPIED file(s)" +echo " Info: $INFO_FILE" +echo " Directory: $BASELINE_DIR" +echo "============================================================" + +if [ $COPIED -eq 0 ]; then + echo "ERROR: No baseline files were created!" >&2 + exit 1 +fi \ No newline at end of file diff --git a/dev-tools/script_data/1Zsun_binaries_suite.py b/dev-tools/script_data/1Zsun_binaries_suite.py deleted file mode 100644 index 288f37890c..0000000000 --- a/dev-tools/script_data/1Zsun_binaries_suite.py +++ /dev/null @@ -1,885 +0,0 @@ -#!/usr/bin/env python3 -""" -Script to evolve a few binaries. -Used for validation of the branch. - -Authors: Max Briel, Elizabeth Teng -""" - -import argparse -import os -import signal -import sys -import warnings -import h5py - -from posydon.binary_evol.binarystar import BinaryStar, SingleStar -from posydon.binary_evol.simulationproperties import SimulationProperties -from posydon.popsyn.io import simprop_kwargs_from_ini -from posydon.utils.common_functions import orbital_separation_from_period - -target_rows = 12 -line_length = 140 -columns_to_show = ['step_names', 'state', 'event', 'S1_state', 'S1_mass', 'S2_state', 'S2_mass', 'orbital_period', 'time'] - -def load_inlist(verbose): - - sim_kwargs = simprop_kwargs_from_ini('script_data/1Zsun_binaries_params.ini', verbose=verbose) - metallicity = {'metallicity':1, 'verbose':verbose} - - sim_kwargs['step_HMS_HMS'][1].update(metallicity) - sim_kwargs['step_CO_HeMS'][1].update(metallicity) - sim_kwargs['step_CO_HMS_RLO'][1].update(metallicity) - sim_kwargs['step_CO_HeMS_RLO'][1].update(metallicity) - sim_kwargs['step_detached'][1].update(metallicity) - sim_kwargs['step_disrupted'][1].update(metallicity) - sim_kwargs['step_merged'][1].update(metallicity) - sim_kwargs['step_initially_single'][1].update(metallicity) - - sim_prop = SimulationProperties(**sim_kwargs) - - sim_prop.load_steps(verbose=verbose) - return sim_prop - -def write_binary_to_screen(binary): - """Writes a binary DataFrame prettily to the screen - - Args: - binary: BinaryStar object with evolved data - """ - df = binary.to_df(**{'extra_columns':{'step_names':'str'}}) - - # Filter to only existing columns - available_columns = [col for col in columns_to_show if col in df.columns] - df_filtered = df[available_columns] - - # Reset index to use a counter instead of NaN - df_filtered = df_filtered.reset_index(drop=True) - - print("=" * line_length) - - # Print the DataFrame - df_string = df_filtered.to_string(index=True, float_format='%.3f') - print(df_string) - - # Add empty lines to reach exactly 10 rows of output - current_rows = len(df_filtered) + 1 # add one for header - - if current_rows < target_rows: - # Calculate the width of the output to print empty lines of the same width - lines = df_string.split('\n') - if len(lines) > 1: - # Use the width of the data lines (skip header) - empty_lines_needed = target_rows - current_rows - for i in range(empty_lines_needed): - print("") - - print("-" * line_length) - - -def print_failed_binary(binary,e, max_error_lines=3): - - print("=" * line_length) - print(f"🚨 Binary Evolution Failed!") - print(f"Exception: {type(e).__name__}") - print(f"Message: {e}") - - # Get the binary's current state and limit output - try: - df = binary.to_df(**{'extra_columns':{'step_names':'str'}}) - if len(df) > 0: - # Select only the desired columns - - available_columns = [col for col in columns_to_show if col in df.columns] - df_filtered = df[available_columns] - - # Reset index to use a counter instead of NaN - df_filtered = df_filtered.reset_index(drop=True) - - # Limit to max_error_lines - if len(df_filtered) > max_error_lines: - df_filtered = df_filtered.tail(max_error_lines) - print(f"\nShowing last {max_error_lines} evolution steps before failure:") - else: - print(f"\nEvolution steps before failure ({len(df_filtered)} steps):") - - df_string = df_filtered.to_string(index=True, float_format='%.3f') - print(df_string) - - current_rows = len(df_filtered) + 1 + 5 # add one for header - empty_lines_needed = target_rows - current_rows - for i in range(empty_lines_needed): - print("") - else: - print("\nNo evolution steps recorded before failure.") - except Exception as inner_e: - print(f"\nCould not retrieve binary state: {inner_e}") - - print("-" * line_length) - -def evolve_binary(binary, h5file, binary_id): - """ - Evolves a single binary, prints its evolution, and saves to HDF5. - - Args: - binary: BinaryStar object - h5file: open h5py.File object for writing - binary_id: unique identifier for this binary - """ - - # Capture warnings during evolution - captured_warnings = [] - - def warning_handler(message, category, filename, lineno, file=None, line=None): - captured_warnings.append({ - 'message': str(message), - 'category': category.__name__, - 'filename': filename, - 'lineno': lineno - }) - - # Set up warning capture - old_showwarning = warnings.showwarning - warnings.showwarning = warning_handler - - try: - binary.evolve() - # Display the evolution summary for successful evolution - write_binary_to_screen(binary) - - # Save to HDF5 - df = binary.to_df(**{'extra_columns':{'step_names':'str'}}) - grp = h5file.create_group(f"binary_{binary_id}") - for col in df.columns: - grp.create_dataset(col, data=df[col].values) - - except Exception as e: - print_failed_binary(binary, e) - - err_grp = h5file.require_group(f"binary_{binary_id}/errors") - err_grp.attrs['exception_type'] = type(e).__name__ - err_grp.attrs['exception_message'] = str(e) - - finally: - warnings.showwarning = old_showwarning - - # ensure binary group exists - grp = h5file.require_group(f"binary_{binary_id}") - - # Save warnings to h5 file - if captured_warnings: - warn_grp = grp.create_group("warnings") - for i, warning in enumerate(captured_warnings): - warn_subgrp = warn_grp.create_group(f"warning_{i}") - warn_subgrp.attrs['category'] = warning['category'] - warn_subgrp.attrs['message'] = warning['message'] - warn_subgrp.attrs['filename'] = warning['filename'] - warn_subgrp.attrs['lineno'] = warning['lineno'] - - print(f"āš ļø {len(captured_warnings)} warning(s) raised during evolution:") - for i, warning in enumerate(captured_warnings[:3], 1): # Show max 3 warnings - print(f" {i}. {warning['category']}: {warning['message']}") - if len(captured_warnings) > 3: - print(f" ... and {len(captured_warnings) - 3} more warning(s)") - else: - print(f"No warning(s) raised during evolution\n\n\n\n") - print("=" * line_length) - -def evolve_binaries(verbose,output_path): - """Evolves a few binaries to validate their output - """ - sim_prop = load_inlist(verbose) - - with h5py.File(output_path,'w') as h5file: - binary_id=0 - - ######################################## - # Failing binary in matching - ######################################## - star_1 = SingleStar(**{'mass': 11.948472796094759, 'state': 'H-rich_Core_H_burning','metallicity':1, - 'natal_kick_array': [231.97383621190582, 5.927334890264575, 1.5990566013567014, 6.137994236518587]}) - star_2 = SingleStar(**{'mass': 7.636958434479617, 'state': 'H-rich_Core_H_burning','metallicity':1, - 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) - binary = BinaryStar(star_1, star_2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', - 'orbital_period': 190925.99636740884,'eccentricity': 0.0}, properties = sim_prop) - evolve_binary(binary, h5file, binary_id) - binary_id+=1 - ######################################## - # Failing binary in matching - ######################################## - star_1 = SingleStar(**{'mass': 30.169861921689556, 'state': 'H-rich_Core_H_burning','metallicity':1, - 'natal_kick_array': [77.96834852144123, 0.05021460132555987, 2.3146518208348152, 1.733054979982291]}) - star_2 = SingleStar(**{'mass': 10.972734402996027, 'state': 'H-rich_Core_H_burning','metallicity':1, - 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) - binary = BinaryStar(star_1, star_2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', - 'orbital_period': 20479.71919353725,'eccentricity': 0.0}, properties = sim_prop) - evolve_binary(binary, h5file, binary_id) - binary_id+=1 - ######################################## - # flipped S1 and S2 ? - ######################################## - star_1 = SingleStar(**{'mass': 9.474917413943635, 'state': 'H-rich_Core_H_burning','metallicity':1, - 'natal_kick_array': [133.5713935237759, 4.398754864537542, 2.703102872841114, 1.4633904612711142]}) - star_2 = SingleStar(**{'mass': 9.311073918196263, 'state': 'H-rich_Core_H_burning','metallicity':1, - 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) - binary = BinaryStar(star_1, star_2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', - 'orbital_period': 18.605997832086413,'eccentricity': 0.0}, properties = sim_prop) - - evolve_binary(binary, h5file, binary_id) - binary_id+=1 - ######################################## - # flipped S1 and S2 - ######################################## - star_1 = SingleStar(**{'mass': 10.438541, 'state': 'H-rich_Core_H_burning','metallicity':1, - 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) - star_2 = SingleStar(**{'mass': 1.400713, 'state': 'H-rich_Core_H_burning','metallicity':1, - 'natal_kick_array': [0.0, 4.190728383757787, 1.1521129697118118, 5.015343794234789]}) - binary = BinaryStar(star_1, star_2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', - 'orbital_period': 9.824025,'eccentricity': 0.0}, properties = sim_prop) - evolve_binary(binary, h5file, binary_id) - binary_id+=1 - ######################################## - # flipped S1 and S2 - ######################################## - star_1= SingleStar(**{'mass': 9.845907 , 'state': 'H-rich_Core_H_burning','metallicity':1, - 'natal_kick_array': [0.0, 4.190728383757787, 1.1521129697118118, 5.015343794234789]}) - star_2 = SingleStar(**{'mass': 9.611029, 'state': 'H-rich_Core_H_burning','metallicity':1, - 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) - binary = BinaryStar(star_1, star_2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', - 'orbital_period': 3.820571,'eccentricity': 0.0}, properties = sim_prop) - evolve_binary(binary, h5file, binary_id) - binary_id+=1 - ######################################## - # Normal binary evolution - ######################################## - star_1= SingleStar(**{'mass': 30.845907 , 'state': 'H-rich_Core_H_burning','metallicity':1, - 'natal_kick_array': [0.0, 4.190728383757787, 1.1521129697118118, 5.015343794234789]}) - star_2 = SingleStar(**{'mass': 30.611029, 'state': 'H-rich_Core_H_burning','metallicity':1, - 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) - binary = BinaryStar(star_1, star_2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', - 'orbital_period': 30.820571,'eccentricity': 0.0}, properties = sim_prop) - evolve_binary(binary, h5file, binary_id) - binary_id+=1 - ######################################## - # Normal binary - ######################################## - star_1= SingleStar(**{'mass': 9.213534679594247 , 'state': 'H-rich_Core_H_burning','metallicity':1, - 'natal_kick_array': [327.5906384501521, 1.7707176050073297, 1.573225822966838, 1.6757313876001914]}) - star_2 = SingleStar(**{'mass': 7.209878522799272, 'state': 'H-rich_Core_H_burning','metallicity':1, - 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) - binary = BinaryStar(star_1, star_2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', - 'orbital_period': 63123.74544474666,'eccentricity': 0.0}, properties = sim_prop) - evolve_binary(binary, h5file, binary_id) - binary_id+=1 - ######################################## - # Normal binary - ######################################## - star_1= SingleStar(**{'mass': 9.561158487732602 , 'state': 'H-rich_Core_H_burning','metallicity':1, - 'natal_kick_array': [317.5423844462847, 2.9095984678057603, 1.754121288652108, 2.3693917842468784]}) - star_2 = SingleStar(**{'mass': 9.382732464319286, 'state': 'H-rich_Core_H_burning','metallicity':1, - 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) - binary = BinaryStar(star_1, star_2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', - 'orbital_period': 27.77657038557851,'eccentricity': 0.0}, properties = sim_prop) - evolve_binary(binary, h5file, binary_id) - binary_id+=1 - ######################################## - # Normal binary - ######################################## - star1 = SingleStar(**{'mass': 7.552858,#29829485, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array': [40.91509926587841, 2.6295454150818256, 1.6718337470964977, 6.0408769315244895]}) - star2 = SingleStar(**{'mass': 6.742063, #481560266, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) - binary = BinaryStar(star1, star2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', - 'orbital_period': 17.957531550841225, 'eccentricity': 0.0,}, - properties=sim_prop) - evolve_binary(binary, h5file, binary_id) - binary_id+=1 - ######################################## - # High BH spin options - ######################################## - star_1 = SingleStar(**{'mass': 31.616785, 'state': 'H-rich_Core_H_burning', - 'natal_kick_array': [10, 4.190728383757787, 1.1521129697118118, 5.015343794234789]}) - star_2 = SingleStar(**{'mass': 26.874267, 'state': 'H-rich_Core_H_burning', - 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) - binary = BinaryStar(star_1, star_2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', - 'orbital_period': 501.99252706449792,'eccentricity': 0.0}, properties = sim_prop) - evolve_binary(binary, h5file, binary_id) - binary_id+=1 - ######################################## - # Original a>1 spin error - ######################################## - star_1 = SingleStar(**{'mass': 18.107506844123645, 'state': 'H-rich_Core_H_burning', - 'natal_kick_array': [528.2970725443025, 4.190728383757787, 1.1521129697118118, 5.015343794234789]}) - star_2 = SingleStar(**{'mass': 15.641392951875442, 'state': 'H-rich_Core_H_burning', - 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) - binary = BinaryStar(star_1, star_2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', - 'orbital_period': 151.99252706449792,'eccentricity': 0.0}, properties = sim_prop) - evolve_binary(binary, h5file, binary_id) - binary_id+=1 - ######################################## - # FIXED disrupted crash - ######################################## - star1 = SingleStar(**{'mass': 52.967313, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) - star2 = SingleStar(**{'mass': 36.306444, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) - binary = BinaryStar(star1, star2, - **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':12.877004, 'eccentricity': 0.0}, - properties = sim_prop) - evolve_binary(binary, h5file, binary_id) - binary_id+=1 - ######################################## - # FIXED error with SN type - ######################################## - star1 = SingleStar(**{'mass': 17.782576, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) - star2 = SingleStar(**{'mass':3.273864, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) - binary = BinaryStar(star1, star2, - **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':4513.150157, 'eccentricity': 0.0}, - properties = sim_prop) - evolve_binary(binary, h5file, binary_id) - binary_id+=1 - ######################################## - # FIXED oRLO2 looping - ######################################## - star1 = SingleStar(**{'mass': 170.638207, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array': [4.921294, 4.31745, 1.777768, 3.509656]}) - star2 = SingleStar(**{'mass':37.917852, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) - - binary = BinaryStar(star1, star2, - **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':113.352736, 'eccentricity': 0.0}, - properties = sim_prop) - evolve_binary(binary, h5file, binary_id) - binary_id+=1 - ######################################## - # Redirect to step_CO_HeMS (H-rich non-burning?) - ######################################## - star_1 = SingleStar(**{'mass': 8.333579, 'state': 'H-rich_Core_H_burning',\ - 'natal_kick_array': [17.125568, 4.101834, 0.917541, 3.961291]}) - star_2 = SingleStar(**{'mass' : 8.208376, 'state' : 'H-rich_Core_H_burning', - 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - binary = BinaryStar(star_1, star_2, - **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period': 66.870417, 'eccentricity': 0.0}, - properties = sim_prop) - evolve_binary(binary, h5file, binary_id) - binary_id+=1 - ######################################## - # FIXED oRLO2 looping - ######################################## - star_1 = SingleStar(**{'mass': 16.921378, 'state': 'H-rich_Core_H_burning',\ - 'natal_kick_array': [268.837139, 5.773527, 2.568105, 2.519068]}) - star_2 = SingleStar(**{'mass' : 16.286318, 'state' : 'H-rich_Core_H_burning', - 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - binary = BinaryStar(star_1, star_2, - **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period': 37.958768, 'eccentricity': 0.0}, - properties = sim_prop) - evolve_binary(binary, h5file, binary_id) - binary_id+=1 - ######################################## - # FIXED? step_detached failure - ######################################## - star1 = SingleStar(**{'mass': 19.787769, 'state': 'H-rich_Core_H_burning', - 'natal_kick_array': [24.464803, 0.666314, 1.954698, 5.598975]}) - star2 = SingleStar(**{'mass': 7.638741, 'state': 'H-rich_Core_H_burning', - 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - binary = BinaryStar(star1, star2, - **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':3007.865561, 'eccentricity': 0.0}, - properties = sim_prop) - evolve_binary(binary, h5file, binary_id) - binary_id+=1 - ######################################## - # Disrupted binary - ######################################## - star_1 = SingleStar(**{'mass': 16.921378, 'state': 'H-rich_Core_H_burning',\ - 'natal_kick_array': [268.837139, 5.773527, 2.568105, 2.519068]}) - star_2 = SingleStar(**{'mass' : 16.286318, 'state' : 'H-rich_Core_H_burning', - 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - - binary = BinaryStar(star_1, star_2, - **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':3007.865561, 'eccentricity': 0.0}, - properties = sim_prop) - evolve_binary(binary, h5file, binary_id) - binary_id+=1 - ######################################## - # FIXED Detached binary failure (low mass) - ######################################## - star1 = SingleStar(**{'mass': 9, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - star2 = SingleStar(**{'mass':0.8, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - - binary = BinaryStar(star1, star2, - **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':4513.150157, 'eccentricity': 0.0}, - properties = sim_prop) - evolve_binary(binary, h5file, binary_id) - binary_id+=1 - ######################################## - # FIXED SN_TYPE = None crash - ######################################## - star1 = SingleStar(**{'mass': 17.782576, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - star2 = SingleStar(**{'mass':3.273864, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - - binary = BinaryStar(star1, star2, - **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':4513.150157, 'eccentricity': 0.0}, - properties = sim_prop) - evolve_binary(binary, h5file, binary_id) - binary_id+=1 - ######################################## - # FIXED SN_TYPE errors - ######################################## - star1 = SingleStar(**{'mass': 6.782576, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - star2 = SingleStar(**{'mass':3.273864, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - - binary = BinaryStar(star1, star2, - **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':4513.150157, 'eccentricity': 0.0}, - properties = sim_prop) - evolve_binary(binary, h5file, binary_id) - binary_id+=1 - ######################################## - # FIXED SN_TYPE errors - ######################################## - star1 = SingleStar(**{'mass': 40.638207, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array': [30.921294, 4.31745, 1.777768, 3.509656]}) - star2 = SingleStar(**{'mass':37.917852, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - - binary = BinaryStar(star1, star2, - **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':2113.352736, 'eccentricity': 0.0}, - properties = sim_prop) - evolve_binary(binary, h5file, binary_id) - binary_id+=1 - ######################################## - # FIXED ECSN errors? - ######################################## - star1 = SingleStar(**{'mass': 12.376778, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array': [80, 4.31745, 1.777768, 3.509656]}) - star2 = SingleStar(**{'mass': 9.711216, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - - - binary = BinaryStar(star1, star2, - **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':79.83702, 'eccentricity': 0.0}, - properties = sim_prop) - evolve_binary(binary, h5file, binary_id) - binary_id+=1 - ######################################## - # Interpolator masses?? - ######################################## - star1 = SingleStar(**{'mass': 7.592921, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - star2 = SingleStar(**{'mass':5.038679 , - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - - binary = BinaryStar(star1, star2, - **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':5.537807, 'eccentricity': 0.0}, - properties = sim_prop) - evolve_binary(binary, h5file, binary_id) - binary_id+=1 - ######################################## - # Interpolator masses? - ######################################## - star_1 = SingleStar(**{'mass': 38.741115, - 'state': 'H-rich_Core_H_burning',\ - 'natal_kick_array': [21.113771, 2.060135, 2.224789, 4.089729]}) - star_2 = SingleStar(**{'mass': 27.776178, - 'state': 'H-rich_Core_H_burning',\ - 'natal_kick_array': [282.712103, 0.296252, 1.628433, 5.623812]}) - - binary = BinaryStar(star_1, star_2, - **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period': 93.387072, 'eccentricity': 0.0}, - properties = sim_prop) - evolve_binary(binary, h5file, binary_id) - binary_id+=1 - ######################################## - # FIXED NaN spin - ######################################## - star1 = SingleStar(**{'mass': 70.066924, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array':[0.0, 0.0, 0.0, 0.0], - 'metallicity':1}) - star2 = SingleStar(**{'mass': 34.183110, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array':[0.0, 0.0, 0.0, 0.0], - 'metallicity':1}) - binary = BinaryStar(star1, star2, - **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':5.931492e+03, - 'separation': orbital_separation_from_period(5.931492e+03, star1.mass, star2.mass), - 'eccentricity': 0.0}, - properties = sim_prop) - evolve_binary(binary, h5file, binary_id) - binary_id+=1 - ######################################## - # FIXED NaN spin - ######################################## - star1 = SingleStar(**{'mass': 28.837286, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - star2 = SingleStar(**{'mass': 6.874867, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - - binary = BinaryStar(star1, star2, - **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':35.609894, - 'separation': orbital_separation_from_period(35.609894, star1.mass, star2.mass), - 'eccentricity': 0.0}, - properties = sim_prop) - evolve_binary(binary, h5file, binary_id) - binary_id+=1 - ######################################## - # oRLO2 issue - ######################################## - star1 = SingleStar(**{'mass':29.580210, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - star2 = SingleStar(**{'mass': 28.814626, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - - binary = BinaryStar(star1, star2, - **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':40.437993, 'eccentricity': 0.0}, - properties = sim_prop) - evolve_binary(binary, h5file, binary_id) - binary_id+=1 - ######################################## - # oRLO2 issue - ######################################## - star1 = SingleStar(**{'mass':67.126795, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - star2 = SingleStar(**{'mass': 19.622908, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - - binary = BinaryStar(star1, star2, - **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':1484.768582, 'eccentricity': 0.0}, - properties = sim_prop) - evolve_binary(binary, h5file, binary_id) - binary_id+=1 - ######################################## - # oRLO2 issue - ######################################## - star1 = SingleStar(**{'mass': 58.947503, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - star2 = SingleStar(**{'mass': 56.660506, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - - binary = BinaryStar(star1, star2, - **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':2011.300659, 'eccentricity': 0.0}, - properties = sim_prop) - evolve_binary(binary, h5file, binary_id) - binary_id+=1 - ######################################## - # oRLO2 issue - ######################################## - star1 = SingleStar(**{'mass': 170.638207, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array':[47.979957374424956, 5.317304576107798, 2.7259013166068145, 4.700929589520818]}) - star2 = SingleStar(**{'mass': 37.917852, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - - binary = BinaryStar(star1, star2, - **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':113.352736, 'eccentricity': 0.0}, - properties = sim_prop) - evolve_binary(binary, h5file, binary_id) - binary_id+=1 - ######################################## - # oRLO2 issue - ######################################## - star1 = SingleStar(**{'mass': 109.540207, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - star2 = SingleStar(**{'mass': 84.344530, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - - binary = BinaryStar(star1, star2, - **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':5.651896, 'eccentricity': 0.0}, - properties = sim_prop) - evolve_binary(binary, h5file, binary_id) - binary_id+=1 - ######################################## - # redirect - ######################################## - star1 = SingleStar(**{'mass': 13.889634, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - star2 = SingleStar(**{'mass':0.490231, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - - binary = BinaryStar(star1, star2, - **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':14513.150157, 'eccentricity': 0.0}, - properties = sim_prop) - evolve_binary(binary, h5file, binary_id) - binary_id+=1 - ######################################## - # redirect - ######################################## - star1 = SingleStar(**{'mass': 9, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - star2 = SingleStar(**{'mass':0.8, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - - binary = BinaryStar(star1, star2, - **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':4513.150157, 'eccentricity': 0.0}, - properties = sim_prop) - evolve_binary(binary, h5file, binary_id) - binary_id+=1 - ######################################## - # Max time - ######################################## - star_1 = SingleStar(**{'mass': 103.07996766780799, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array': [0.0, 0.2965418610971261, 2.0789170290719117, 3.207488023705968]}) - star_2 = SingleStar(**{'mass': 83.66522615073987, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) - binary = BinaryStar(star_1, star_2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', - 'orbital_period': 1449.1101985875678,'eccentricity': 0.0}, properties = sim_prop) - evolve_binary(binary, h5file, binary_id) - binary_id+=1 - ######################################## - # Max time - ######################################## - star_1 = SingleStar(**{'mass': 8.860934140643465, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array': [11.818027275431337, 2.812412688633058, 0.4998731824233789, 2.9272630485628643]}) - star_2 = SingleStar(**{'mass': 8.584716012668551, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) - binary = BinaryStar(star_1, star_2, **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', - 'orbital_period': 20.82030114750744,'eccentricity': 0.0}, properties = sim_prop) - evolve_binary(binary, h5file, binary_id) - binary_id+=1 - ######################################## - # PR421 - ######################################## - star1 = SingleStar(**{'mass': 24.035366, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - star2 = SingleStar(**{'mass': 23.187355, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - - binary = BinaryStar(star1, star2, - **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':18.865029, 'eccentricity': 0.0}, - properties = sim_prop) - evolve_binary(binary, h5file, binary_id) - binary_id+=1 - ######################################## - # CE class - ######################################## - star1 = SingleStar(**{'mass':33.964274, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - star2 = SingleStar(**{'mass': 28.98149, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - - binary = BinaryStar(star1, star2, - **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':82.370989, 'eccentricity': 0.0}, - properties = sim_prop) - evolve_binary(binary, h5file, binary_id) - binary_id+=1 - ######################################## - # PR574 - stepCE fix - ######################################## - star1 = SingleStar(**{'mass':29.580210, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - star2 = SingleStar(**{'mass': 28.814626*0.4, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array':[0.0, 0.0, 0.0, 0.0]}) - - binary = BinaryStar(star1, star2, - **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':300.437993, 'eccentricity': 0.0}, - properties = sim_prop) - evolve_binary(binary, h5file, binary_id) - binary_id+=1 - ######################################## - # e_ZAMS error - ######################################## - star1 = SingleStar(**{'mass': 8.161885721822461, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) - star2 = SingleStar(**{'mass': 3.5907829421526154, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) - - binary = BinaryStar(star1, star2, - **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period': 36.873457164644144, 'eccentricity': 0.0}, - properties = sim_prop) - evolve_binary(binary, h5file, binary_id) - binary_id+=1 - ######################################## - # e_ZAMS error - ######################################## - star1 = SingleStar(**{'mass': 35.24755025317775, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array': [19.755993125895806, 0.37149222852233904, 1.6588846085306563, - 1.434617029858906]}) - star2 = SingleStar(**{'mass': 30.000450298072902, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) - - binary = BinaryStar(star1, star2, - **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period': 24060.02101364665, 'eccentricity': 0.8085077857996965}, - properties = sim_prop) - evolve_binary(binary, h5file, binary_id) - binary_id+=1 - ######################################## - # e_ZAMS error - ######################################## - star1 = SingleStar(**{'mass': 11.862930493162692, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) - star2 = SingleStar(**{'mass': 1.4739109294156703, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) - - binary = BinaryStar(star1, star2, - **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period': 4111.083887312003, 'eccentricity':0.0}, - properties = sim_prop) - evolve_binary(binary, h5file, binary_id) - binary_id+=1 - ######################################## - # e_ZAMS error - ######################################## - star1 = SingleStar(**{'mass': 8.527361341212108, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) - star2 = SingleStar(**{'mass': 0.7061748406821822, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) - - binary = BinaryStar(star1, star2, - **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period': 2521.1927287891444, 'eccentricity':0.0}, - properties = sim_prop) - evolve_binary(binary, h5file, binary_id) - binary_id+=1 - ######################################## - # e_ZAMS error - ######################################## - star1 = SingleStar(**{'mass': 13.661942533447398 ,#29829485, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) - star2 = SingleStar(**{'mass': 4.466151109802313 , #481560266, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) - - binary = BinaryStar(star1, star2, - **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', 'orbital_period':3110.1346707516914, 'eccentricity':0.0}, - properties = sim_prop) - evolve_binary(binary, h5file, binary_id) - binary_id+=1 - - ######################################## - # double CO step - ######################################## - # NS + WD example - star1 = SingleStar(**{'mass': 7.939736047577677, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) - star1 = SingleStar(**{'mass': 6.661421823348241, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) - - binary = BinaryStar(star1, star2, - **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', - 'orbital_period': 28.576933942881404, 'eccentricity': 0.0}, - properties = sim_prop) - evolve_binary(binary) - # BH + NS example - star1 = SingleStar(**{'mass': 22.69609546427504, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array': [0.0, 2.051704135150374, 1.73468853754093, 3.299716078528058]}) - star2 = SingleStar(**{'mass': 16.39690317352072, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array': [0.0, 5.934599002039066, 2.4331072903106974, 1.9933166215820504]}) - - binary = BinaryStar(star1, star2, - **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', - 'orbital_period': 70.37960820393167, 'eccentricity': 0.0}, - properties = sim_prop) - evolve_binary(binary) - # WD + WD example - star1 = SingleStar(**{'mass': 6.661421823348241, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) - star2 = SingleStar(**{'mass': 6.661421823348241, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}) - - binary = BinaryStar(star1, star2, - **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', - 'orbital_period': 28.576933942881404, 'eccentricity': 0.0}, - properties = sim_prop) - evolve_binary(binary) - # NS + NS example - star1 = SingleStar(**{'mass': 16.458995075687447, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array': [0.0, 3.661376360771944, 0.7219969332243381, 4.919284439555057]}) - star2 = SingleStar(**{'mass': 12.580980419413521, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array': [0.0, 4.944467687452352, 1.2845384190953326, 1.6806849171480245]}) - - binary = BinaryStar(star1, star2, - **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', - 'orbital_period': 247.4244399689946, 'eccentricity': 0.0}, - properties = sim_prop) - evolve_binary(binary) - - # BH + BH - star1 = SingleStar(**{'mass': 31.077951593283725, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array': [0.0, 1.9047595342945016, 0.7097181927314352, 2.892753852818733]}) - star2 = SingleStar(**{'mass': 27.8239810278115, - 'state': 'H-rich_Core_H_burning', - 'natal_kick_array': [0.0, 4.004970175991886, 2.2544428565691472, 3.420828590003044]}) - - binary = BinaryStar(star1, star2, - **{'time': 0.0, 'state': 'detached', 'event': 'ZAMS', - 'orbital_period': 27.429155057946318, 'eccentricity': 0.0}, - properties = sim_prop) - evolve_binary(binary) - -if __name__ == "__main__": - parser = argparse.ArgumentParser(description='Evolve binaries for validation.') - parser.add_argument('--verbose', '-v', action='store_true', default=False, - help='Enable verbose output (default: False)') - parser.add_argument("--output", type=str, required=True, - help="Path to save HDF5 output") - args = parser.parse_args() - - evolve_binaries(verbose=args.verbose, output_path=args.output) diff --git a/dev-tools/script_data/1Zsun_binaries_params.ini b/dev-tools/script_data/binaries_params.ini similarity index 99% rename from dev-tools/script_data/1Zsun_binaries_params.ini rename to dev-tools/script_data/binaries_params.ini index f5400f3117..c001928c2b 100644 --- a/dev-tools/script_data/1Zsun_binaries_params.ini +++ b/dev-tools/script_data/binaries_params.ini @@ -1,4 +1,6 @@ # POSYDON default BinaryPopulation inifile, use ConfigParser syntax +# This ini is used ONLY for SimulationProperties configuration. +# Metallicity is overridden at runtime by binaries_suite.py. [environment_variables] PATH_TO_POSYDON = '' diff --git a/dev-tools/script_data/binaries_suite.py b/dev-tools/script_data/binaries_suite.py new file mode 100644 index 0000000000..08e0365dd9 --- /dev/null +++ b/dev-tools/script_data/binaries_suite.py @@ -0,0 +1,694 @@ +#!/usr/bin/env python3 +""" +Script to evolve a set of test binaries at a given metallicity. +Used for validation of POSYDON branches. + +Usage: + python binaries_suite.py --output results.h5 --metallicity 1 + python binaries_suite.py --output results.h5 --metallicity 0.45 --verbose + +Authors: Max Briel, Elizabeth Teng +""" + +import argparse +import os +import sys +import warnings +import pandas as pd + +from posydon.binary_evol.binarystar import BinaryStar, SingleStar +from posydon.binary_evol.simulationproperties import SimulationProperties +from posydon.popsyn.io import simprop_kwargs_from_ini +from posydon.utils.common_functions import orbital_separation_from_period + +AVAILABLE_METALLICITIES = [2., 1., 0.45, 0.2, 0.1, 0.01, 0.001, 0.0001] + +# Display settings +TARGET_ROWS = 12 +LINE_LENGTH = 80 +COLUMNS_TO_SHOW = ['step_names', 'state', 'event', + 'S1_state', 'S1_mass', + 'S2_state', 'S2_mass', 'orbital_period'] + +def load_inlist(metallicity, verbose, ini_path=None): + """Load simulation properties from ini file and configure for given metallicity. + + Args: + metallicity: float, metallicity in solar units + verbose: bool + ini_path: str, path to ini file (auto-detected if None) + + Returns: + SimulationProperties object with loaded steps + """ + if ini_path is None: + script_dir = os.path.dirname(os.path.abspath(__file__)) + ini_path = os.path.join(script_dir, 'binaries_params.ini') + + if not os.path.exists(ini_path): + raise FileNotFoundError(f"INI file not found: {ini_path}") + + sim_kwargs = simprop_kwargs_from_ini(ini_path, verbose=verbose) + + metallicity_kwargs = {'metallicity': metallicity, 'verbose': verbose} + + metallicity_steps = ['step_HMS_HMS', 'step_CO_HeMS', 'step_CO_HMS_RLO', + 'step_CO_HeMS_RLO', 'step_detached', 'step_disrupted', + 'step_merged', 'step_initially_single'] + for step_name in metallicity_steps: + if step_name in sim_kwargs: + sim_kwargs[step_name][1].update(metallicity_kwargs) + + sim_prop = SimulationProperties(**sim_kwargs) + sim_prop.load_steps(verbose=verbose) + return sim_prop + +def write_binary_to_screen(binary): + """Writes a binary DataFrame to screen.""" + df = binary.to_df(**{'extra_columns':{'step_names':'str'}}) + + # Filter to only existing columns + available_columns = [col for col in COLUMNS_TO_SHOW if col in df.columns] + df_filtered = df[available_columns].reset_index(drop=True) + + print("=" * LINE_LENGTH) + + # Print the DataFrame + df_string = df_filtered.to_string(index=True, float_format='%.3f') + print(df_string) + + # Add empty lines to reach exactly 10 rows of output + current_rows = len(df_filtered) + 1 # add one for header + + if current_rows < TARGET_ROWS: + for _ in range(TARGET_ROWS - current_rows): + print("") + + print("-" * LINE_LENGTH) + + +def print_failed_binary(binary,e, max_error_lines=3): + """Print information about a binary that failed to evolve.""" + + print("=" * LINE_LENGTH) + print(f"🚨 Binary Evolution Failed!") + print(f"Exception: {type(e).__name__}") + print(f"Message: {e}") + + # Get the binary's current state and limit output + try: + df = binary.to_df(**{'extra_columns':{'step_names':'str'}}) + if len(df) > 0: + # Select only the desired columns + + available_columns = [col for col in COLUMNS_TO_SHOW if col in df.columns] + df_filtered = df[available_columns].reset_index(drop=True) + + # Limit to max_error_lines + if len(df_filtered) > max_error_lines: + df_filtered = df_filtered.tail(max_error_lines) + print(f"\nShowing last {max_error_lines} evolution steps before failure:") + else: + print(f"\nEvolution steps before failure ({len(df_filtered)} steps):") + + df_string = df_filtered.to_string(index=True, float_format='%.3f') + print(df_string) + + current_rows = len(df_filtered) + 1 + 5 # add one for header + empty_lines_needed = TARGET_ROWS - current_rows + for _ in range(max(0, empty_lines_needed)): + print("") + else: + print("\nNo evolution steps recorded before failure.") + except Exception as inner_e: + print(f"\nCould not retrieve binary state: {inner_e}") + + print("-" * LINE_LENGTH) + +def evolve_binary(binary, h5file, binary_id): + """ + Evolves a single binary, prints its evolution, and saves to HDF5. + + Args: + binary: BinaryStar object + h5file: open pd.HDFStore object for writing + binary_id: unique identifier for this binary + """ + + # Capture warnings during evolution + captured_warnings = [] + + def warning_handler(message, category, filename, lineno, file=None, line=None): + captured_warnings.append({ + "binary_id": int(binary_id), + "category": category.__name__, + "message": str(message), + "filename": filename, + "lineno": lineno + }) + + # Set up warning capture + old_showwarning = warnings.showwarning + warnings.showwarning = warning_handler + + print(f"Binary {binary_id}") + evolution_df = None + + try: + binary.evolve() + write_binary_to_screen(binary) + evolution_df = binary.to_df(extra_columns={'step_names':'str'}) + + except Exception as e: + print_failed_binary(binary, e) + + # If evolution fails, create a minimal df with error info + evolution_df = pd.DataFrame([{ + "binary_id": int(binary_id), + "exception_type": type(e).__name__, + "exception_message": str(e) + }]) + + finally: + warnings.showwarning = old_showwarning + + # Ensure we always have a dataframe + if evolution_df is not None: + # Decode bytes columns if needed + for col in evolution_df.select_dtypes([object]): + if evolution_df[col].apply(lambda x: isinstance(x, bytes)).any(): + evolution_df[col] = evolution_df[col].apply( + lambda x: x.decode('utf-8') if isinstance(x, bytes) else x + ) + + # Always ensure binary_id exists + if "binary_id" not in evolution_df.columns: + evolution_df["binary_id"] = int(binary_id) + + # Defragment + evolution_df = evolution_df.copy() + + # Determine min_itemsize from the dataframe we're actually saving + string_cols = evolution_df.select_dtypes([object]).columns + min_itemsize = {col: 100 for col in string_cols} + h5file.append("evolution", evolution_df, format="table", + data_columns=True, min_itemsize=min_itemsize) + + # Save warnings + if captured_warnings: + warn_df = pd.DataFrame(captured_warnings) + # Ensure consistent string column sizes for warnings table + warn_string_cols = warn_df.select_dtypes([object]).columns + warn_min_itemsize = {col: 200 for col in warn_string_cols} + h5file.append("warnings", warn_df, format="table", + min_itemsize=warn_min_itemsize) + print(f"āš ļø {len(captured_warnings)} warning(s) raised during evolution:") + for i, w in enumerate(captured_warnings[:3], 1): + print(f" {i}. {w['category']}: {w['message'][:80]}") + if len(captured_warnings) > 3: + print(f" ... and {len(captured_warnings) - 3} more warning(s)") + else: + print(f" No warning(s) raised during evolution") + + print(f"āœ… Finished binary {binary_id}") + print("=" * LINE_LENGTH) + + + +def get_test_binaries(metallicity, sim_prop): + """Return the list of test binaries as (star1_kwargs, star2_kwargs, binary_kwargs, description) tuples. + + All binaries use the specified metallicity. + """ + Z = metallicity + + binaries = [ + # 0: Failing binary in matching + ({'mass': 11.948472796094759, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [231.97383621190582, 5.927334890264575, 1.5990566013567014, 6.137994236518587]}, + {'mass': 7.636958434479617, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}, + {'time': 0.0, 'state': 'detached', 'event': 'ZAMS', + 'orbital_period': 190925.99636740884, 'eccentricity': 0.0}, + "Failing binary in matching"), + + # 1: Failing binary in matching + ({'mass': 30.169861921689556, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [77.96834852144123, 0.05021460132555987, 2.3146518208348152, 1.733054979982291]}, + {'mass': 10.972734402996027, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}, + {'time': 0.0, 'state': 'detached', 'event': 'ZAMS', + 'orbital_period': 20479.71919353725, 'eccentricity': 0.0}, + "Failing binary in matching"), + + # 2: Flipped S1 and S2 (near-equal mass) + ({'mass': 9.474917413943635, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [133.5713935237759, 4.398754864537542, 2.703102872841114, 1.4633904612711142]}, + {'mass': 9.311073918196263, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}, + {'time': 0.0, 'state': 'detached', 'event': 'ZAMS', + 'orbital_period': 18.605997832086413, 'eccentricity': 0.0}, + "Flipped S1 and S2 (near-equal mass)"), + + # 3: Flipped S1 and S2 (high mass ratio) + ({'mass': 10.438541, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}, + {'mass': 1.400713, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [0.0, 4.190728383757787, 1.1521129697118118, 5.015343794234789]}, + {'time': 0.0, 'state': 'detached', 'event': 'ZAMS', + 'orbital_period': 9.824025, 'eccentricity': 0.0}, + "Flipped S1 and S2 (high mass ratio)"), + + # 4: Flipped S1 and S2 + ({'mass': 9.845907, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [0.0, 4.190728383757787, 1.1521129697118118, 5.015343794234789]}, + {'mass': 9.611029, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}, + {'time': 0.0, 'state': 'detached', 'event': 'ZAMS', + 'orbital_period': 3.820571, 'eccentricity': 0.0}, + "Flipped S1 and S2"), + + # 5: Normal binary evolution (high mass) + ({'mass': 30.845907, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [0.0, 4.190728383757787, 1.1521129697118118, 5.015343794234789]}, + {'mass': 30.611029, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}, + {'time': 0.0, 'state': 'detached', 'event': 'ZAMS', + 'orbital_period': 30.820571, 'eccentricity': 0.0}, + "Normal binary evolution (high mass)"), + + # 6: Normal binary (wide orbit) + ({'mass': 9.213534679594247, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [327.5906384501521, 1.7707176050073297, 1.573225822966838, 1.6757313876001914]}, + {'mass': 7.209878522799272, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}, + {'time': 0.0, 'state': 'detached', 'event': 'ZAMS', + 'orbital_period': 63123.74544474666, 'eccentricity': 0.0}, + "Normal binary (wide orbit)"), + + # 7: Normal binary (near-equal mass, close) + ({'mass': 9.561158487732602, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [317.5423844462847, 2.9095984678057603, 1.754121288652108, 2.3693917842468784]}, + {'mass': 9.382732464319286, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}, + {'time': 0.0, 'state': 'detached', 'event': 'ZAMS', + 'orbital_period': 27.77657038557851, 'eccentricity': 0.0}, + "Normal binary (near-equal mass, close)"), + + # 8: Normal binary + ({'mass': 7.552858, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [40.91509926587841, 2.6295454150818256, 1.6718337470964977, 6.0408769315244895]}, + {'mass': 6.742063, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}, + {'time': 0.0, 'state': 'detached', 'event': 'ZAMS', + 'orbital_period': 17.957531550841225, 'eccentricity': 0.0}, + "Normal binary"), + + # 9: High BH spin options + ({'mass': 31.616785, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [10, 4.190728383757787, 1.1521129697118118, 5.015343794234789]}, + {'mass': 26.874267, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}, + {'time': 0.0, 'state': 'detached', 'event': 'ZAMS', + 'orbital_period': 501.99252706449792, 'eccentricity': 0.0}, + "High BH spin options"), + + # 10: Original a>1 spin error + ({'mass': 18.107506844123645, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [528.2970725443025, 4.190728383757787, 1.1521129697118118, 5.015343794234789]}, + {'mass': 15.641392951875442, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}, + {'time': 0.0, 'state': 'detached', 'event': 'ZAMS', + 'orbital_period': 151.99252706449792, 'eccentricity': 0.0}, + "Original a>1 spin error"), + + # 11: FIXED disrupted crash + ({'mass': 52.967313, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}, + {'mass': 36.306444, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}, + {'time': 0.0, 'state': 'detached', 'event': 'ZAMS', + 'orbital_period': 12.877004, 'eccentricity': 0.0}, + "FIXED disrupted crash"), + + # 12: FIXED error with SN type + ({'mass': 17.782576, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}, + {'mass': 3.273864, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}, + {'time': 0.0, 'state': 'detached', 'event': 'ZAMS', + 'orbital_period': 4513.150157, 'eccentricity': 0.0}, + "FIXED error with SN type"), + + # 13: FIXED oRLO2 looping + ({'mass': 170.638207, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [4.921294, 4.31745, 1.777768, 3.509656]}, + {'mass': 37.917852, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}, + {'time': 0.0, 'state': 'detached', 'event': 'ZAMS', + 'orbital_period': 113.352736, 'eccentricity': 0.0}, + "FIXED oRLO2 looping"), + + # 14: Redirect to step_CO_HeMS + ({'mass': 8.333579, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [17.125568, 4.101834, 0.917541, 3.961291]}, + {'mass': 8.208376, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}, + {'time': 0.0, 'state': 'detached', 'event': 'ZAMS', + 'orbital_period': 66.870417, 'eccentricity': 0.0}, + "Redirect to step_CO_HeMS"), + + # 15: FIXED oRLO2 looping + ({'mass': 16.921378, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [268.837139, 5.773527, 2.568105, 2.519068]}, + {'mass': 16.286318, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}, + {'time': 0.0, 'state': 'detached', 'event': 'ZAMS', + 'orbital_period': 37.958768, 'eccentricity': 0.0}, + "FIXED oRLO2 looping"), + + # 16: FIXED step_detached failure + ({'mass': 19.787769, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [24.464803, 0.666314, 1.954698, 5.598975]}, + {'mass': 7.638741, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}, + {'time': 0.0, 'state': 'detached', 'event': 'ZAMS', + 'orbital_period': 3007.865561, 'eccentricity': 0.0}, + "FIXED step_detached failure"), + + # 17: Disrupted binary + ({'mass': 16.921378, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [268.837139, 5.773527, 2.568105, 2.519068]}, + {'mass': 16.286318, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}, + {'time': 0.0, 'state': 'detached', 'event': 'ZAMS', + 'orbital_period': 3007.865561, 'eccentricity': 0.0}, + "Disrupted binary"), + + # 18: FIXED Detached binary failure (low mass) + ({'mass': 9, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}, + {'mass': 0.8, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}, + {'time': 0.0, 'state': 'detached', 'event': 'ZAMS', + 'orbital_period': 4513.150157, 'eccentricity': 0.0}, + "FIXED Detached binary failure (low mass)"), + + # 19: FIXED SN_TYPE = None crash + ({'mass': 17.782576, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}, + {'mass': 3.273864, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}, + {'time': 0.0, 'state': 'detached', 'event': 'ZAMS', + 'orbital_period': 4513.150157, 'eccentricity': 0.0}, + "FIXED SN_TYPE = None crash"), + + # 20: FIXED SN_TYPE errors (low mass primary) + ({'mass': 6.782576, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}, + {'mass': 3.273864, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}, + {'time': 0.0, 'state': 'detached', 'event': 'ZAMS', + 'orbital_period': 4513.150157, 'eccentricity': 0.0}, + "FIXED SN_TYPE errors (low mass primary)"), + + # 21: FIXED SN_TYPE errors (high mass) + ({'mass': 40.638207, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [30.921294, 4.31745, 1.777768, 3.509656]}, + {'mass': 37.917852, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}, + {'time': 0.0, 'state': 'detached', 'event': 'ZAMS', + 'orbital_period': 2113.352736, 'eccentricity': 0.0}, + "FIXED SN_TYPE errors (high mass)"), + + # 22: FIXED ECSN errors + ({'mass': 12.376778, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [80, 4.31745, 1.777768, 3.509656]}, + {'mass': 9.711216, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}, + {'time': 0.0, 'state': 'detached', 'event': 'ZAMS', + 'orbital_period': 79.83702, 'eccentricity': 0.0}, + "FIXED ECSN errors"), + + # 23: Interpolator masses (close) + ({'mass': 7.592921, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}, + {'mass': 5.038679, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}, + {'time': 0.0, 'state': 'detached', 'event': 'ZAMS', + 'orbital_period': 5.537807, 'eccentricity': 0.0}, + "Interpolator masses (close)"), + + # 24: Interpolator masses (both kicked) + ({'mass': 38.741115, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [21.113771, 2.060135, 2.224789, 4.089729]}, + {'mass': 27.776178, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [282.712103, 0.296252, 1.628433, 5.623812]}, + {'time': 0.0, 'state': 'detached', 'event': 'ZAMS', + 'orbital_period': 93.387072, 'eccentricity': 0.0}, + "Interpolator masses (both kicked)"), + + # 25: FIXED NaN spin (very high mass, wide) + ({'mass': 70.066924, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}, + {'mass': 34.183110, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}, + {'time': 0.0, 'state': 'detached', 'event': 'ZAMS', + 'orbital_period': 5.931492e+03, 'eccentricity': 0.0}, + "FIXED NaN spin (very high mass, wide)"), + + # 26: FIXED NaN spin + ({'mass': 28.837286, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}, + {'mass': 6.874867, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}, + {'time': 0.0, 'state': 'detached', 'event': 'ZAMS', + 'orbital_period': 35.609894, 'eccentricity': 0.0}, + "FIXED NaN spin"), + + # 27: oRLO2 issue (near-equal mass) + ({'mass': 29.580210, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}, + {'mass': 28.814626, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}, + {'time': 0.0, 'state': 'detached', 'event': 'ZAMS', + 'orbital_period': 40.437993, 'eccentricity': 0.0}, + "oRLO2 issue (near-equal mass)"), + + # 28: oRLO2 issue (high mass ratio) + ({'mass': 67.126795, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}, + {'mass': 19.622908, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}, + {'time': 0.0, 'state': 'detached', 'event': 'ZAMS', + 'orbital_period': 1484.768582, 'eccentricity': 0.0}, + "oRLO2 issue (high mass ratio)"), + + # 29: oRLO2 issue (very high mass, near-equal) + ({'mass': 58.947503, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}, + {'mass': 56.660506, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}, + {'time': 0.0, 'state': 'detached', 'event': 'ZAMS', + 'orbital_period': 2011.300659, 'eccentricity': 0.0}, + "oRLO2 issue (very high mass, near-equal)"), + + # 30: oRLO2 issue (extreme mass, kicked) + ({'mass': 170.638207, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [47.979957374424956, 5.317304576107798, 2.7259013166068145, 4.700929589520818]}, + {'mass': 37.917852, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}, + {'time': 0.0, 'state': 'detached', 'event': 'ZAMS', + 'orbital_period': 113.352736, 'eccentricity': 0.0}, + "oRLO2 issue (extreme mass, kicked)"), + + # 31: oRLO2 issue (very high mass, close) + ({'mass': 109.540207, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}, + {'mass': 84.344530, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}, + {'time': 0.0, 'state': 'detached', 'event': 'ZAMS', + 'orbital_period': 5.651896, 'eccentricity': 0.0}, + "oRLO2 issue (very high mass, close)"), + + # 32: Redirect (extreme mass ratio) + ({'mass': 13.889634, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}, + {'mass': 0.490231, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}, + {'time': 0.0, 'state': 'detached', 'event': 'ZAMS', + 'orbital_period': 14513.150157, 'eccentricity': 0.0}, + "Redirect (extreme mass ratio)"), + + # 33: Redirect (low mass secondary) + ({'mass': 9, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}, + {'mass': 0.8, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}, + {'time': 0.0, 'state': 'detached', 'event': 'ZAMS', + 'orbital_period': 4513.150157, 'eccentricity': 0.0}, + "Redirect (low mass secondary)"), + + # 34: Max time (very high mass, wide) + ({'mass': 103.07996766780799, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [0.0, 0.2965418610971261, 2.0789170290719117, 3.207488023705968]}, + {'mass': 83.66522615073987, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}, + {'time': 0.0, 'state': 'detached', 'event': 'ZAMS', + 'orbital_period': 1449.1101985875678, 'eccentricity': 0.0}, + "Max time (very high mass, wide)"), + + # 35: Max time + ({'mass': 8.860934140643465, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [11.818027275431337, 2.812412688633058, 0.4998731824233789, 2.9272630485628643]}, + {'mass': 8.584716012668551, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}, + {'time': 0.0, 'state': 'detached', 'event': 'ZAMS', + 'orbital_period': 20.82030114750744, 'eccentricity': 0.0}, + "Max time"), + + # 36: PR421 + ({'mass': 24.035366, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}, + {'mass': 23.187355, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}, + {'time': 0.0, 'state': 'detached', 'event': 'ZAMS', + 'orbital_period': 18.865029, 'eccentricity': 0.0}, + "PR421"), + + # 37: CE class + ({'mass': 33.964274, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}, + {'mass': 28.98149, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}, + {'time': 0.0, 'state': 'detached', 'event': 'ZAMS', + 'orbital_period': 82.370989, 'eccentricity': 0.0}, + "CE class"), + + # 38: PR574 - stepCE fix + ({'mass': 29.580210, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}, + {'mass': 28.814626 * 0.4, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}, + {'time': 0.0, 'state': 'detached', 'event': 'ZAMS', + 'orbital_period': 300.437993, 'eccentricity': 0.0}, + "PR574 - stepCE fix"), + + # 39: e_ZAMS error + ({'mass': 8.161885721822461, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}, + {'mass': 3.5907829421526154, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}, + {'time': 0.0, 'state': 'detached', 'event': 'ZAMS', + 'orbital_period': 36.873457164644144, 'eccentricity': 0.0}, + "e_ZAMS error"), + + # 40: e_ZAMS error (eccentric) + ({'mass': 35.24755025317775, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [19.755993125895806, 0.37149222852233904, 1.6588846085306563, 1.434617029858906]}, + {'mass': 30.000450298072902, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}, + {'time': 0.0, 'state': 'detached', 'event': 'ZAMS', + 'orbital_period': 24060.02101364665, 'eccentricity': 0.8085077857996965}, + "e_ZAMS error (eccentric)"), + + # 41: e_ZAMS error (high mass ratio) + ({'mass': 11.862930493162692, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}, + {'mass': 1.4739109294156703, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}, + {'time': 0.0, 'state': 'detached', 'event': 'ZAMS', + 'orbital_period': 4111.083887312003, 'eccentricity': 0.0}, + "e_ZAMS error (high mass ratio)"), + + # 42: e_ZAMS error (extreme mass ratio) + ({'mass': 8.527361341212108, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}, + {'mass': 0.7061748406821822, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}, + {'time': 0.0, 'state': 'detached', 'event': 'ZAMS', + 'orbital_period': 2521.1927287891444, 'eccentricity': 0.0}, + "e_ZAMS error (extreme mass ratio)"), + + # 43: e_ZAMS error + ({'mass': 13.661942533447398, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}, + {'mass': 4.466151109802313, 'state': 'H-rich_Core_H_burning', 'metallicity': Z, + 'natal_kick_array': [0.0, 0.0, 0.0, 0.0]}, + {'time': 0.0, 'state': 'detached', 'event': 'ZAMS', + 'orbital_period': 3110.1346707516914, 'eccentricity': 0.0}, + "e_ZAMS error"), + ] + + return binaries + + +def evolve_binaries(metallicity, verbose, output_path, ini_path=None): + """Evolves the test binary suite at the given metallicity and saves results. + + Args: + metallicity: float, metallicity in solar units + verbose: bool + output_path: str, path to save HDF5 output + ini_path: str, path to ini file (auto-detected if None) + """ + print(f"{'=' * LINE_LENGTH}") + print(f" Evolving test binaries at Z = {metallicity} Zsun") + print(f" Output: {output_path}") + print(f"{'=' * LINE_LENGTH}\n") + + sim_prop = load_inlist(metallicity, verbose, ini_path) + test_binaries = get_test_binaries(metallicity, sim_prop) + + with pd.HDFStore(output_path, mode="w") as h5file: + # Save metadata + meta_df = pd.DataFrame([{ + 'metallicity': metallicity, + 'n_binaries': len(test_binaries), + }]) + h5file.put("metadata", meta_df, format="table") + + for binary_id, (s1_kw, s2_kw, bin_kw, description) in enumerate(test_binaries): + print(f"\n[{binary_id}/{len(test_binaries)-1}] {description}") + + star_1 = SingleStar(**s1_kw) + star_2 = SingleStar(**s2_kw) + + # Add separation from period if not explicitly provided + if 'separation' not in bin_kw and 'orbital_period' in bin_kw: + bin_kw['separation'] = orbital_separation_from_period( + bin_kw['orbital_period'], star_1.mass, star_2.mass + ) + + binary = BinaryStar(star_1, star_2, **bin_kw, properties=sim_prop) + evolve_binary(binary, h5file, binary_id) + + print(f"\n{'=' * LINE_LENGTH}") + print(f" All {len(test_binaries)} binaries complete. Results saved to {output_path}") + print(f"{'=' * LINE_LENGTH}") + +if __name__ == "__main__": + parser = argparse.ArgumentParser( + description='Evolve test binaries for POSYDON branch validation.', + formatter_class=argparse.ArgumentDefaultsHelpFormatter + ) + parser.add_argument('--verbose', '-v', action='store_true', default=False, + help='Enable verbose output') + parser.add_argument('--output', type=str, required=True, + help='Path to save HDF5 output') + parser.add_argument('--metallicity', '-Z', type=float, default=1.0, + help=f'Metallicity in solar units. Available: {AVAILABLE_METALLICITIES}') + parser.add_argument('--ini', type=str, default=None, + help='Path to params ini file (auto-detected if not given)') + args = parser.parse_args() + + if args.metallicity not in AVAILABLE_METALLICITIES: + print(f"WARNING: Metallicity {args.metallicity} not in standard set {AVAILABLE_METALLICITIES}.") + print(f"Proceeding anyway, but POSYDON grids may not exist for this value.") + + evolve_binaries( + metallicity=args.metallicity, + verbose=args.verbose, + output_path=args.output, + ini_path=args.ini, + ) \ No newline at end of file diff --git a/dev-tools/validate_binaries.sh b/dev-tools/validate_binaries.sh index 04a041af06..2ae354b4fa 100644 --- a/dev-tools/validate_binaries.sh +++ b/dev-tools/validate_binaries.sh @@ -1,26 +1,144 @@ -#!/bin/bash - -# A script for validating the outputs of 100 binaries, -# which can be compared to a baseline to monitor changes to the code. - -# script usage: ./validate_binaries.sh --branch candidate_branch - -BRANCH=$1 -SUFFIX=$2 - -# run candidate binaries and save to file -./evolve_binaries.sh "$BRANCH" - -# compare quantitative, qualitative, warnings/errors, structured output -# create outputs/comparison_branchname.txt -SAFE_BRANCH="${BRANCH//\//_}" -CANDIDATE_FILE="outputs/candidate_${SAFE_BRANCH}.h5" -COMPARISON_FILE="outputs/comparison_${SAFE_BRANCH}${SUFFIX:+_$SUFFIX}.txt" -python compare_runs.py baseline.h5 "$CANDIDATE_FILE" > "$COMPARISON_FILE" - -if [ $? -ne 0 ]; then - echo "Error: compare_runs.py failed. Check $COMPARISON_FILE" - exit 1 -fi - -echo "Binary evolution comparison saved to $COMPARISON_FILE" +#!/bin/bash +# ============================================================================= +# validate_binaries.sh — Run the full validation pipeline: +# 1. Evolve test binaries on a candidate branch +# 2. Compare against baseline files +# +# Usage: +# ./validate_binaries.sh [baseline_branch] [metallicities] +# +# Examples: +# ./validate_binaries.sh feature/new-SN # compare vs main baseline +# ./validate_binaries.sh feature/new-SN v2.1.0 # compare vs v2.1.0 baseline +# ./validate_binaries.sh feature/new-SN main "1 0.45" # subset of metallicities +# +# Prerequisites: +# Run generate_baseline.sh first to create baseline files. +# +# Output: +# outputs//comparison_Zsun.txt — per-metallicity comparison reports +# outputs//comparison_summary.txt — overall summary +# ============================================================================= + +set -euo pipefail + +CANDIDATE_BRANCH=${1:?Usage: ./validate_binaries.sh [baseline_branch] [metallicities]} +BASELINE_BRANCH=${2:-main} +METALLICITIES=${3:-"2 1 0.45 0.2 0.1 0.01 0.001 0.0001"} + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +SAFE_CANDIDATE="${CANDIDATE_BRANCH//\//_}" +SAFE_BASELINE="${BASELINE_BRANCH//\//_}" + +BASELINE_DIR="$SCRIPT_DIR/baselines/${SAFE_BASELINE}" +OUTPUT_DIR="$SCRIPT_DIR/outputs/${SAFE_CANDIDATE}" +SUMMARY_FILE="$OUTPUT_DIR/comparison_summary.txt" + +echo "============================================================" +echo " POSYDON Binary Validation" +echo " Candidate: $CANDIDATE_BRANCH" +echo " Baseline: $BASELINE_BRANCH" +echo " Metallicities: $METALLICITIES" +echo "============================================================" + +# ── Verify baseline exists ──────────────────────────────────────────────── +if [ ! -d "$BASELINE_DIR" ]; then + echo "ERROR: Baseline directory not found: $BASELINE_DIR" >&2 + echo "Run generate_baseline.sh first:" >&2 + echo " ./generate_baseline.sh $BASELINE_BRANCH" >&2 + exit 1 +fi + +# Check that at least one baseline file exists +BASELINE_COUNT=0 +for Z in $METALLICITIES; do + if [ -f "$BASELINE_DIR/baseline_${Z}Zsun.h5" ]; then + BASELINE_COUNT=$((BASELINE_COUNT + 1)) + fi +done +if [ $BASELINE_COUNT -eq 0 ]; then + echo "ERROR: No baseline files found in $BASELINE_DIR for requested metallicities." >&2 + exit 1 +fi +echo " Found $BASELINE_COUNT baseline file(s)." + +# ── Step 1: Evolve binaries on candidate branch ────────────────────────── +echo "" +echo "Step 1: Evolving binaries on candidate branch '$CANDIDATE_BRANCH'..." +"$SCRIPT_DIR/evolve_binaries.sh" "$CANDIDATE_BRANCH" "" "$METALLICITIES" + +# ── Step 2: Compare each metallicity ───────────────────────────────────── +echo "" +echo "Step 2: Comparing results..." + +TOTAL=0 +PASS=0 +FAIL=0 +SKIP=0 + +# Initialize summary +mkdir -p "$OUTPUT_DIR" +cat > "$SUMMARY_FILE" << EOF +POSYDON Binary Validation — Comparison Summary +================================================ +Candidate branch: $CANDIDATE_BRANCH +Baseline branch: $BASELINE_BRANCH +Date: $(date -u '+%Y-%m-%d %H:%M:%S UTC') +================================================ + +EOF + +for Z in $METALLICITIES; do + TOTAL=$((TOTAL + 1)) + + BASELINE_FILE="$BASELINE_DIR/baseline_${Z}Zsun.h5" + CANDIDATE_FILE="$OUTPUT_DIR/candidate_${Z}Zsun.h5" + COMPARISON_FILE="$OUTPUT_DIR/comparison_${Z}Zsun.txt" + + echo "" + echo "--- Z = ${Z} Zsun ---" + + if [ ! -f "$BASELINE_FILE" ]; then + echo " SKIP: No baseline file for Z=${Z}" + echo "Z = ${Z} Zsun: SKIPPED (no baseline)" >> "$SUMMARY_FILE" + SKIP=$((SKIP + 1)) + continue + fi + + if [ ! -f "$CANDIDATE_FILE" ]; then + echo " FAIL: No candidate file for Z=${Z}" + echo "Z = ${Z} Zsun: FAIL (no candidate output)" >> "$SUMMARY_FILE" + FAIL=$((FAIL + 1)) + continue + fi + + if python "$SCRIPT_DIR/compare_runs.py" "$BASELINE_FILE" "$CANDIDATE_FILE" \ + 2>&1 | tee "$COMPARISON_FILE"; then + echo " PASS: No differences" + echo "Z = ${Z} Zsun: PASS" >> "$SUMMARY_FILE" + PASS=$((PASS + 1)) + else + echo " DIFFERENCES DETECTED — see $COMPARISON_FILE" + echo "Z = ${Z} Zsun: DIFFERENCES DETECTED (see comparison_${Z}Zsun.txt)" >> "$SUMMARY_FILE" + FAIL=$((FAIL + 1)) + fi +done + +# ── Final Summary ───────────────────────────────────────────────────────── +cat >> "$SUMMARY_FILE" << EOF + +================================================ +TOTAL: $TOTAL | PASS: $PASS | FAIL: $FAIL | SKIP: $SKIP +EOF + +echo "" +echo "============================================================" +echo " Validation Summary" +echo " TOTAL: $TOTAL | PASS: $PASS | FAIL: $FAIL | SKIP: $SKIP" +echo " Full summary: $SUMMARY_FILE" +echo "============================================================" + +if [ $FAIL -gt 0 ]; then + exit 1 +fi +exit 0 \ No newline at end of file From 06abf4b4e7bd67b8f83743fbd452e61261ef190a Mon Sep 17 00:00:00 2001 From: Elizabeth Teng Date: Thu, 26 Feb 2026 04:15:34 -0600 Subject: [PATCH 62/91] gitignore --- dev-tools/.gitignore | 9 - dev-tools/check_outputs.ipynb | 512 ---------------------------------- 2 files changed, 521 deletions(-) delete mode 100644 dev-tools/check_outputs.ipynb diff --git a/dev-tools/.gitignore b/dev-tools/.gitignore index 1cea72efc6..bec9d97e5a 100644 --- a/dev-tools/.gitignore +++ b/dev-tools/.gitignore @@ -1,14 +1,5 @@ -# Remove the accidentally staged clone -git rm --cached -r workdirs/ - -# Create .gitignore -cat > .gitignore << 'EOF' workdirs/ outputs/ logs/ baselines/ test_*.h5 -EOF - -git add .gitignore - diff --git a/dev-tools/check_outputs.ipynb b/dev-tools/check_outputs.ipynb deleted file mode 100644 index c0073df835..0000000000 --- a/dev-tools/check_outputs.ipynb +++ /dev/null @@ -1,512 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": 1, - "id": "7e9791d3", - "metadata": {}, - "outputs": [], - "source": [ - "import argparse\n", - "import os\n", - "import signal\n", - "import sys\n", - "import warnings\n", - "import h5py\n", - "import pandas as pd\n", - "\n", - "from posydon.binary_evol.binarystar import BinaryStar, SingleStar\n", - "from posydon.binary_evol.simulationproperties import SimulationProperties\n", - "from posydon.popsyn.io import simprop_kwargs_from_ini\n", - "from posydon.utils.common_functions import orbital_separation_from_period" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "id": "327be9fe", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "env: PATH_TO_POSYDON=/projects/b1119/eteng/software/valid/POSYDON/\n", - "env: PATH_TO_POSYDON_DATA=/projects/b1119/POSYDON_popsynth_data/v2/250520_newSNe/\n" - ] - } - ], - "source": [ - "%env PATH_TO_POSYDON=/projects/b1119/eteng/software/valid/POSYDON/\n", - "%env PATH_TO_POSYDON_DATA=/projects/b1119/POSYDON_popsynth_data/v2/250520_newSNe/" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "id": "994f6ebf", - "metadata": {}, - "outputs": [ - { - "ename": "HDF5ExtError", - "evalue": "HDF5 error back trace\n\n File \"H5F.c\", line 836, in H5Fopen\n unable to synchronously open file\n File \"H5F.c\", line 796, in H5F__open_api_common\n unable to open file\n File \"H5VLcallback.c\", line 3863, in H5VL_file_open\n open failed\n File \"H5VLcallback.c\", line 3675, in H5VL__file_open\n open failed\n File \"H5VLnative_file.c\", line 128, in H5VL__native_file_open\n unable to open file\n File \"H5Fint.c\", line 2018, in H5F_open\n unable to read superblock\n File \"H5Fsuper.c\", line 600, in H5F__super_read\n truncated file: eof = 96, sblock->base_addr = 0, stored_eof = 2048\n\nEnd of HDF5 error back trace\n\nUnable to open/create file './POSYDON_main/outputs/candidate_main.h5'", - "output_type": "error", - "traceback": [ - "\u001b[31m---------------------------------------------------------------------------\u001b[39m", - "\u001b[31mHDF5ExtError\u001b[39m Traceback (most recent call last)", - "\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[4]\u001b[39m\u001b[32m, line 1\u001b[39m\n\u001b[32m----> \u001b[39m\u001b[32m1\u001b[39m df = \u001b[43mpd\u001b[49m\u001b[43m.\u001b[49m\u001b[43mread_hdf\u001b[49m\u001b[43m(\u001b[49m\u001b[33;43m'\u001b[39;49m\u001b[33;43m./POSYDON_main/outputs/candidate_main.h5\u001b[39;49m\u001b[33;43m'\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[33;43m\"\u001b[39;49m\u001b[33;43mevolution\u001b[39;49m\u001b[33;43m\"\u001b[39;49m\u001b[43m)\u001b[49m\n\u001b[32m 2\u001b[39m warnings = pd.read_hdf(\u001b[33m'\u001b[39m\u001b[33m./POSYDON_main/outputs/candidate_main.h5\u001b[39m\u001b[33m'\u001b[39m, \u001b[33m\"\u001b[39m\u001b[33mwarnings\u001b[39m\u001b[33m\"\u001b[39m)\n", - "\u001b[36mFile \u001b[39m\u001b[32m~/.conda/envs/valid/lib/python3.11/site-packages/pandas/io/pytables.py:426\u001b[39m, in \u001b[36mread_hdf\u001b[39m\u001b[34m(path_or_buf, key, mode, errors, where, start, stop, columns, iterator, chunksize, **kwargs)\u001b[39m\n\u001b[32m 423\u001b[39m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m exists:\n\u001b[32m 424\u001b[39m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mFileNotFoundError\u001b[39;00m(\u001b[33mf\u001b[39m\u001b[33m\"\u001b[39m\u001b[33mFile \u001b[39m\u001b[38;5;132;01m{\u001b[39;00mpath_or_buf\u001b[38;5;132;01m}\u001b[39;00m\u001b[33m does not exist\u001b[39m\u001b[33m\"\u001b[39m)\n\u001b[32m--> \u001b[39m\u001b[32m426\u001b[39m store = \u001b[43mHDFStore\u001b[49m\u001b[43m(\u001b[49m\u001b[43mpath_or_buf\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mmode\u001b[49m\u001b[43m=\u001b[49m\u001b[43mmode\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43merrors\u001b[49m\u001b[43m=\u001b[49m\u001b[43merrors\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43m*\u001b[49m\u001b[43m*\u001b[49m\u001b[43mkwargs\u001b[49m\u001b[43m)\u001b[49m\n\u001b[32m 427\u001b[39m \u001b[38;5;66;03m# can't auto open/close if we are using an iterator\u001b[39;00m\n\u001b[32m 428\u001b[39m \u001b[38;5;66;03m# so delegate to the iterator\u001b[39;00m\n\u001b[32m 429\u001b[39m auto_close = \u001b[38;5;28;01mTrue\u001b[39;00m\n", - "\u001b[36mFile \u001b[39m\u001b[32m~/.conda/envs/valid/lib/python3.11/site-packages/pandas/io/pytables.py:585\u001b[39m, in \u001b[36mHDFStore.__init__\u001b[39m\u001b[34m(self, path, mode, complevel, complib, fletcher32, **kwargs)\u001b[39m\n\u001b[32m 583\u001b[39m \u001b[38;5;28mself\u001b[39m._fletcher32 = fletcher32\n\u001b[32m 584\u001b[39m \u001b[38;5;28mself\u001b[39m._filters = \u001b[38;5;28;01mNone\u001b[39;00m\n\u001b[32m--> \u001b[39m\u001b[32m585\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[43m.\u001b[49m\u001b[43mopen\u001b[49m\u001b[43m(\u001b[49m\u001b[43mmode\u001b[49m\u001b[43m=\u001b[49m\u001b[43mmode\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43m*\u001b[49m\u001b[43m*\u001b[49m\u001b[43mkwargs\u001b[49m\u001b[43m)\u001b[49m\n", - "\u001b[36mFile \u001b[39m\u001b[32m~/.conda/envs/valid/lib/python3.11/site-packages/pandas/io/pytables.py:745\u001b[39m, in \u001b[36mHDFStore.open\u001b[39m\u001b[34m(self, mode, **kwargs)\u001b[39m\n\u001b[32m 739\u001b[39m msg = (\n\u001b[32m 740\u001b[39m \u001b[33m\"\u001b[39m\u001b[33mCannot open HDF5 file, which is already opened, \u001b[39m\u001b[33m\"\u001b[39m\n\u001b[32m 741\u001b[39m \u001b[33m\"\u001b[39m\u001b[33meven in read-only mode.\u001b[39m\u001b[33m\"\u001b[39m\n\u001b[32m 742\u001b[39m )\n\u001b[32m 743\u001b[39m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mValueError\u001b[39;00m(msg)\n\u001b[32m--> \u001b[39m\u001b[32m745\u001b[39m \u001b[38;5;28mself\u001b[39m._handle = \u001b[43mtables\u001b[49m\u001b[43m.\u001b[49m\u001b[43mopen_file\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[43m.\u001b[49m\u001b[43m_path\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[43m.\u001b[49m\u001b[43m_mode\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43m*\u001b[49m\u001b[43m*\u001b[49m\u001b[43mkwargs\u001b[49m\u001b[43m)\u001b[49m\n", - "\u001b[36mFile \u001b[39m\u001b[32m~/.conda/envs/valid/lib/python3.11/site-packages/tables/file.py:296\u001b[39m, in \u001b[36mopen_file\u001b[39m\u001b[34m(filename, mode, title, root_uep, filters, **kwargs)\u001b[39m\n\u001b[32m 291\u001b[39m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mValueError\u001b[39;00m(\n\u001b[32m 292\u001b[39m \u001b[33m\"\u001b[39m\u001b[33mThe file \u001b[39m\u001b[33m'\u001b[39m\u001b[38;5;132;01m%s\u001b[39;00m\u001b[33m'\u001b[39m\u001b[33m is already opened. Please \u001b[39m\u001b[33m\"\u001b[39m\n\u001b[32m 293\u001b[39m \u001b[33m\"\u001b[39m\u001b[33mclose it before reopening in write mode.\u001b[39m\u001b[33m\"\u001b[39m % filename)\n\u001b[32m 295\u001b[39m \u001b[38;5;66;03m# Finally, create the File instance, and return it\u001b[39;00m\n\u001b[32m--> \u001b[39m\u001b[32m296\u001b[39m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43mFile\u001b[49m\u001b[43m(\u001b[49m\u001b[43mfilename\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mmode\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mtitle\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mroot_uep\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mfilters\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43m*\u001b[49m\u001b[43m*\u001b[49m\u001b[43mkwargs\u001b[49m\u001b[43m)\u001b[49m\n", - "\u001b[36mFile \u001b[39m\u001b[32m~/.conda/envs/valid/lib/python3.11/site-packages/tables/file.py:746\u001b[39m, in \u001b[36mFile.__init__\u001b[39m\u001b[34m(self, filename, mode, title, root_uep, filters, **kwargs)\u001b[39m\n\u001b[32m 743\u001b[39m \u001b[38;5;28mself\u001b[39m.params = params\n\u001b[32m 745\u001b[39m \u001b[38;5;66;03m# Now, it is time to initialize the File extension\u001b[39;00m\n\u001b[32m--> \u001b[39m\u001b[32m746\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[43m.\u001b[49m\u001b[43m_g_new\u001b[49m\u001b[43m(\u001b[49m\u001b[43mfilename\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mmode\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43m*\u001b[49m\u001b[43m*\u001b[49m\u001b[43mparams\u001b[49m\u001b[43m)\u001b[49m\n\u001b[32m 748\u001b[39m \u001b[38;5;66;03m# Check filters and set PyTables format version for new files.\u001b[39;00m\n\u001b[32m 749\u001b[39m new = \u001b[38;5;28mself\u001b[39m._v_new\n", - "\u001b[36mFile \u001b[39m\u001b[32m~/.conda/envs/valid/lib/python3.11/site-packages/tables/hdf5extension.pyx:514\u001b[39m, in \u001b[36mtables.hdf5extension.File._g_new\u001b[39m\u001b[34m()\u001b[39m\n", - "\u001b[31mHDF5ExtError\u001b[39m: HDF5 error back trace\n\n File \"H5F.c\", line 836, in H5Fopen\n unable to synchronously open file\n File \"H5F.c\", line 796, in H5F__open_api_common\n unable to open file\n File \"H5VLcallback.c\", line 3863, in H5VL_file_open\n open failed\n File \"H5VLcallback.c\", line 3675, in H5VL__file_open\n open failed\n File \"H5VLnative_file.c\", line 128, in H5VL__native_file_open\n unable to open file\n File \"H5Fint.c\", line 2018, in H5F_open\n unable to read superblock\n File \"H5Fsuper.c\", line 600, in H5F__super_read\n truncated file: eof = 96, sblock->base_addr = 0, stored_eof = 2048\n\nEnd of HDF5 error back trace\n\nUnable to open/create file './POSYDON_main/outputs/candidate_main.h5'" - ] - } - ], - "source": [ - "df = pd.read_hdf('./POSYDON_main/outputs/candidate_main.h5', \"evolution\")\n", - "warnings = pd.read_hdf('./POSYDON_main/outputs/candidate_main.h5', \"warnings\")" - ] - }, - { - "cell_type": "code", - "execution_count": 56, - "id": "7028a060", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Index(['state', 'event', 'time', 'separation', 'orbital_period',\n", - " 'eccentricity', 'rl_relative_overflow_1', 'rl_relative_overflow_2',\n", - " 'lg_mtransfer_rate', 'mass_transfer_case',\n", - " ...\n", - " 'S2_mass_conv_reg_fortides', 'S2_thickness_conv_reg_fortides',\n", - " 'S2_radius_conv_reg_fortides', 'S2_lambda_CE_1cent',\n", - " 'S2_lambda_CE_10cent', 'S2_lambda_CE_30cent',\n", - " 'S2_lambda_CE_pure_He_star_10cent', 'S2_total_mass_h1',\n", - " 'S2_total_mass_he4', 'binary_id'],\n", - " dtype='object', length=134)\n" - ] - } - ], - "source": [ - "print(df.keys())" - ] - }, - { - "cell_type": "code", - "execution_count": 20, - "id": "76233b25", - "metadata": { - "collapsed": true - }, - "outputs": [ - { - "data": { - "text/html": [ - "
\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
binary_idexception_typeexception_message
01ValueErrorTrying to store a string with len [27] in [S1_...
02ValueErrorTrying to store a string with len [12] in [sta...
03ValueErrorTrying to store a string with len [9] in [even...
04ValueErrorTrying to store a string with len [9] in [even...
05ValueErrorTrying to store a string with len [9] in [even...
07ValueErrorTrying to store a string with len [27] in [S1_...
08ValueErrorTrying to store a string with len [10] in [eve...
09ValueErrorTrying to store a string with len [7] in [even...
010ValueErrorTrying to store a string with len [27] in [S1_...
011ValueErrorTrying to store a string with len [7] in [even...
012ValueErrorTrying to store a string with len [7] in [even...
013ValueErrorTrying to store a string with len [7] in [even...
014ValueErrorTrying to store a string with len [23] in [S1_...
015ValueErrorTrying to store a string with len [9] in [even...
016ValueErrorTrying to store a string with len [9] in [even...
018ValueErrorTrying to store a string with len [7] in [even...
019ValueErrorTrying to store a string with len [7] in [even...
020ValueErrorTrying to store a string with len [7] in [even...
021ValueErrorTrying to store a string with len [7] in [even...
022ValueErrorTrying to store a string with len [9] in [even...
023ValueErrorTrying to store a string with len [9] in [even...
024ValueErrorTrying to store a string with len [9] in [even...
025ValueErrorTrying to store a string with len [7] in [even...
026ValueErrorTrying to store a string with len [9] in [even...
027ValueErrorTrying to store a string with len [7] in [even...
028ValueErrorTrying to store a string with len [7] in [even...
029ValueErrorTrying to store a string with len [7] in [even...
030ValueErrorTrying to store a string with len [7] in [even...
031ValueErrorTrying to store a string with len [7] in [even...
032ValueErrorTrying to store a string with len [7] in [even...
033ValueErrorTrying to store a string with len [7] in [even...
034ValueErrorTrying to store a string with len [7] in [even...
035ValueErrorTrying to store a string with len [9] in [even...
036ValueErrorTrying to store a string with len [7] in [even...
037ValueErrorTrying to store a string with len [10] in [eve...
038ValueErrorTrying to store a string with len [9] in [even...
039MatchingErrorGrid matching failed for merged binary. \\nseco...
040ClassificationErrorBinary is in the detached step but has stable ...
041ValueErrorTrying to store a string with len [7] in [even...
042FlowErrorEvolution of H-rich/He-rich stars in RLO onto ...
043ValueErrorTrying to store a string with len [7] in [even...
\n", - "
" - ], - "text/plain": [ - " binary_id exception_type \\\n", - "0 1 ValueError \n", - "0 2 ValueError \n", - "0 3 ValueError \n", - "0 4 ValueError \n", - "0 5 ValueError \n", - "0 7 ValueError \n", - "0 8 ValueError \n", - "0 9 ValueError \n", - "0 10 ValueError \n", - "0 11 ValueError \n", - "0 12 ValueError \n", - "0 13 ValueError \n", - "0 14 ValueError \n", - "0 15 ValueError \n", - "0 16 ValueError \n", - "0 18 ValueError \n", - "0 19 ValueError \n", - "0 20 ValueError \n", - "0 21 ValueError \n", - "0 22 ValueError \n", - "0 23 ValueError \n", - "0 24 ValueError \n", - "0 25 ValueError \n", - "0 26 ValueError \n", - "0 27 ValueError \n", - "0 28 ValueError \n", - "0 29 ValueError \n", - "0 30 ValueError \n", - "0 31 ValueError \n", - "0 32 ValueError \n", - "0 33 ValueError \n", - "0 34 ValueError \n", - "0 35 ValueError \n", - "0 36 ValueError \n", - "0 37 ValueError \n", - "0 38 ValueError \n", - "0 39 MatchingError \n", - "0 40 ClassificationError \n", - "0 41 ValueError \n", - "0 42 FlowError \n", - "0 43 ValueError \n", - "\n", - " exception_message \n", - "0 Trying to store a string with len [27] in [S1_... \n", - "0 Trying to store a string with len [12] in [sta... \n", - "0 Trying to store a string with len [9] in [even... \n", - "0 Trying to store a string with len [9] in [even... \n", - "0 Trying to store a string with len [9] in [even... \n", - "0 Trying to store a string with len [27] in [S1_... \n", - "0 Trying to store a string with len [10] in [eve... \n", - "0 Trying to store a string with len [7] in [even... \n", - "0 Trying to store a string with len [27] in [S1_... \n", - "0 Trying to store a string with len [7] in [even... \n", - "0 Trying to store a string with len [7] in [even... \n", - "0 Trying to store a string with len [7] in [even... \n", - "0 Trying to store a string with len [23] in [S1_... \n", - "0 Trying to store a string with len [9] in [even... \n", - "0 Trying to store a string with len [9] in [even... \n", - "0 Trying to store a string with len [7] in [even... \n", - "0 Trying to store a string with len [7] in [even... \n", - "0 Trying to store a string with len [7] in [even... \n", - "0 Trying to store a string with len [7] in [even... \n", - "0 Trying to store a string with len [9] in [even... \n", - "0 Trying to store a string with len [9] in [even... \n", - "0 Trying to store a string with len [9] in [even... \n", - "0 Trying to store a string with len [7] in [even... \n", - "0 Trying to store a string with len [9] in [even... \n", - "0 Trying to store a string with len [7] in [even... \n", - "0 Trying to store a string with len [7] in [even... \n", - "0 Trying to store a string with len [7] in [even... \n", - "0 Trying to store a string with len [7] in [even... \n", - "0 Trying to store a string with len [7] in [even... \n", - "0 Trying to store a string with len [7] in [even... \n", - "0 Trying to store a string with len [7] in [even... \n", - "0 Trying to store a string with len [7] in [even... \n", - "0 Trying to store a string with len [9] in [even... \n", - "0 Trying to store a string with len [7] in [even... \n", - "0 Trying to store a string with len [10] in [eve... \n", - "0 Trying to store a string with len [9] in [even... \n", - "0 Grid matching failed for merged binary. \\nseco... \n", - "0 Binary is in the detached step but has stable ... \n", - "0 Trying to store a string with len [7] in [even... \n", - "0 Evolution of H-rich/He-rich stars in RLO onto ... \n", - "0 Trying to store a string with len [7] in [even... " - ] - }, - "execution_count": 20, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "errors" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "68d4d8a8", - "metadata": {}, - "outputs": [], - "source": [] - } - ], - "metadata": { - "kernelspec": { - "display_name": "valid", - "language": "python", - "name": "valid" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.11.14" - } - }, - "nbformat": 4, - "nbformat_minor": 5 -} From d80800b6e822c2f0f587ee41b8686ba429e94c5d Mon Sep 17 00:00:00 2001 From: Elizabeth Teng Date: Mon, 9 Mar 2026 16:25:24 -0500 Subject: [PATCH 63/91] adding baseline h5 file for binary evolution --- dev-tools/generate_baseline.sh | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 dev-tools/generate_baseline.sh diff --git a/dev-tools/generate_baseline.sh b/dev-tools/generate_baseline.sh old mode 100644 new mode 100755 From 4fadb6f3530ee7dde3e817e48cf541e90da4d5fa Mon Sep 17 00:00:00 2001 From: Elizabeth Teng Date: Mon, 9 Mar 2026 16:26:45 -0500 Subject: [PATCH 64/91] add tolerances as CLI --- dev-tools/validate_binaries.sh | 85 ++++++++++++++++++++++++++++++++-- 1 file changed, 80 insertions(+), 5 deletions(-) mode change 100644 => 100755 dev-tools/validate_binaries.sh diff --git a/dev-tools/validate_binaries.sh b/dev-tools/validate_binaries.sh old mode 100644 new mode 100755 index 2ae354b4fa..8a312f8873 --- a/dev-tools/validate_binaries.sh +++ b/dev-tools/validate_binaries.sh @@ -1,16 +1,35 @@ #!/bin/bash # ============================================================================= -# validate_binaries.sh — Run the full validation pipeline: +# validate_binaries.sh: Run the full validation pipeline: # 1. Evolve test binaries on a candidate branch # 2. Compare against baseline files # # Usage: # ./validate_binaries.sh [baseline_branch] [metallicities] +# [--loose] [--rtol VALUE] [--atol VALUE] +# +# Positional arguments: +# candidate_branch Branch or tag to validate (required) +# baseline_branch Branch or tag to compare against (default: main) +# metallicities Space-separated list of Z values, quoted +# (default: "2 1 0.45 0.2 0.1 0.01 0.001 0.0001") +# +# Tolerance flags (passed through to compare_runs.py): +# --loose Use relaxed floating-point tolerances +# (rtol=1e-12, atol=1e-15 unless overridden) +# --rtol VALUE Set explicit relative tolerance +# --atol VALUE Set explicit absolute tolerance +# +# --rtol and --atol can be combined with --loose (explicit values take +# precedence over the --loose defaults) or used on their own without --loose. # # Examples: -# ./validate_binaries.sh feature/new-SN # compare vs main baseline -# ./validate_binaries.sh feature/new-SN v2.1.0 # compare vs v2.1.0 baseline -# ./validate_binaries.sh feature/new-SN main "1 0.45" # subset of metallicities +# ./validate_binaries.sh feature/new-SN # compare vs main, exact +# ./validate_binaries.sh feature/new-SN v2.1.0 # compare vs v2.1.0, exact +# ./validate_binaries.sh feature/new-SN main "1 0.45" # subset of metallicities +# ./validate_binaries.sh feature/new-SN --loose # relaxed tolerances +# ./validate_binaries.sh feature/new-SN main --rtol 1e-8 # custom rtol, default atol +# ./validate_binaries.sh feature/new-SN main "1 0.45" --loose --atol 1e-10 # # Prerequisites: # Run generate_baseline.sh first to create baseline files. @@ -22,9 +41,37 @@ set -euo pipefail -CANDIDATE_BRANCH=${1:?Usage: ./validate_binaries.sh [baseline_branch] [metallicities]} +# ── Parse arguments ─────────────────────────────────────────────────────── + +CANDIDATE_BRANCH=${1:?Usage: ./validate_binaries.sh [baseline_branch] [metallicities] [--loose] [--rtol VALUE] [--atol VALUE]} BASELINE_BRANCH=${2:-main} METALLICITIES=${3:-"2 1 0.45 0.2 0.1 0.01 0.001 0.0001"} +shift $(( $# < 3 ? $# : 3 )) + +LOOSE=false +RTOL="" +ATOL="" + +while [[ $# -gt 0 ]]; do + case "$1" in + --loose) + LOOSE=true + shift + ;; + --rtol) + RTOL="${2:?--rtol requires a value}" + shift 2 + ;; + --atol) + ATOL="${2:?--atol requires a value}" + shift 2 + ;; + *) + echo "ERROR: Unknown option: $1" >&2 + exit 1 + ;; + esac +done SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" SAFE_CANDIDATE="${CANDIDATE_BRANCH//\//_}" @@ -34,6 +81,30 @@ BASELINE_DIR="$SCRIPT_DIR/baselines/${SAFE_BASELINE}" OUTPUT_DIR="$SCRIPT_DIR/outputs/${SAFE_CANDIDATE}" SUMMARY_FILE="$OUTPUT_DIR/comparison_summary.txt" +# ── Build compare_runs.py flags ─────────────────────────────────────────── +COMPARE_FLAGS="" +if [ "$LOOSE" = "true" ]; then + COMPARE_FLAGS="$COMPARE_FLAGS --loose" +fi +if [ -n "$RTOL" ]; then + COMPARE_FLAGS="$COMPARE_FLAGS --rtol $RTOL" +fi +if [ -n "$ATOL" ]; then + COMPARE_FLAGS="$COMPARE_FLAGS --atol $ATOL" +fi + +# Build a human-readable tolerance label for the summary +if [ -n "$RTOL" ] || [ -n "$ATOL" ]; then + TOL_LABEL="rtol=${RTOL:-default}, atol=${ATOL:-default}" + if [ "$LOOSE" = "true" ]; then + TOL_LABEL="$TOL_LABEL (--loose)" + fi +elif [ "$LOOSE" = "true" ]; then + TOL_LABEL="--loose (rtol=1e-12, atol=1e-15)" +else + TOL_LABEL="EXACT (rtol=0, atol=0)" +fi + echo "============================================================" echo " POSYDON Binary Validation" echo " Candidate: $CANDIDATE_BRANCH" @@ -83,6 +154,7 @@ POSYDON Binary Validation — Comparison Summary ================================================ Candidate branch: $CANDIDATE_BRANCH Baseline branch: $BASELINE_BRANCH +Tolerances: $TOL_LABEL Date: $(date -u '+%Y-%m-%d %H:%M:%S UTC') ================================================ @@ -112,7 +184,10 @@ for Z in $METALLICITIES; do continue fi + # $COMPARE_FLAGS is intentionally unquoted so it word-splits into + # separate arguments for compare_runs.py. if python "$SCRIPT_DIR/compare_runs.py" "$BASELINE_FILE" "$CANDIDATE_FILE" \ + $COMPARE_FLAGS \ 2>&1 | tee "$COMPARISON_FILE"; then echo " PASS: No differences" echo "Z = ${Z} Zsun: PASS" >> "$SUMMARY_FILE" From d3d29c5f717a850fd1eb1392d71fba5d3c5d305c Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Thu, 26 Feb 2026 10:17:22 +0000 Subject: [PATCH 65/91] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- dev-tools/compare_runs.py | 6 +++--- dev-tools/evolve_binaries.sh | 2 +- dev-tools/generate_baseline.sh | 2 +- dev-tools/script_data/binaries_suite.py | 17 +++++++++-------- dev-tools/validate_binaries.sh | 2 +- 5 files changed, 15 insertions(+), 14 deletions(-) diff --git a/dev-tools/compare_runs.py b/dev-tools/compare_runs.py index 0d2fe2df7e..a19c0f9ddc 100644 --- a/dev-tools/compare_runs.py +++ b/dev-tools/compare_runs.py @@ -19,12 +19,12 @@ """ import argparse -import sys import os +import sys + import numpy as np import pandas as pd - # Columns that represent qualitative (categorical) evolution properties. # Any column matching these names will be compared as exact string matches # and reported under "QUALITATIVE" differences. @@ -409,4 +409,4 @@ def main(): if __name__ == "__main__": - main() \ No newline at end of file + main() diff --git a/dev-tools/evolve_binaries.sh b/dev-tools/evolve_binaries.sh index 8bfcceef2a..30f7d7b745 100755 --- a/dev-tools/evolve_binaries.sh +++ b/dev-tools/evolve_binaries.sh @@ -150,4 +150,4 @@ fi echo " Outputs in: $OUTPUT_DIR/" echo "============================================================" -exit $FAILED \ No newline at end of file +exit $FAILED diff --git a/dev-tools/generate_baseline.sh b/dev-tools/generate_baseline.sh index a4e31534a7..845b52cf3c 100755 --- a/dev-tools/generate_baseline.sh +++ b/dev-tools/generate_baseline.sh @@ -93,4 +93,4 @@ echo "============================================================" if [ $COPIED -eq 0 ]; then echo "ERROR: No baseline files were created!" >&2 exit 1 -fi \ No newline at end of file +fi diff --git a/dev-tools/script_data/binaries_suite.py b/dev-tools/script_data/binaries_suite.py index 08e0365dd9..157dc0dbab 100644 --- a/dev-tools/script_data/binaries_suite.py +++ b/dev-tools/script_data/binaries_suite.py @@ -14,6 +14,7 @@ import os import sys import warnings + import pandas as pd from posydon.binary_evol.binarystar import BinaryStar, SingleStar @@ -26,7 +27,7 @@ # Display settings TARGET_ROWS = 12 LINE_LENGTH = 80 -COLUMNS_TO_SHOW = ['step_names', 'state', 'event', +COLUMNS_TO_SHOW = ['step_names', 'state', 'event', 'S1_state', 'S1_mass', 'S2_state', 'S2_mass', 'orbital_period'] @@ -150,9 +151,9 @@ def warning_handler(message, category, filename, lineno, file=None, line=None): # Set up warning capture old_showwarning = warnings.showwarning warnings.showwarning = warning_handler - + print(f"Binary {binary_id}") - evolution_df = None + evolution_df = None try: binary.evolve() @@ -171,7 +172,7 @@ def warning_handler(message, category, filename, lineno, file=None, line=None): finally: warnings.showwarning = old_showwarning - + # Ensure we always have a dataframe if evolution_df is not None: # Decode bytes columns if needed @@ -212,9 +213,9 @@ def warning_handler(message, category, filename, lineno, file=None, line=None): print(f"āœ… Finished binary {binary_id}") print("=" * LINE_LENGTH) - - - + + + def get_test_binaries(metallicity, sim_prop): """Return the list of test binaries as (star1_kwargs, star2_kwargs, binary_kwargs, description) tuples. @@ -691,4 +692,4 @@ def evolve_binaries(metallicity, verbose, output_path, ini_path=None): verbose=args.verbose, output_path=args.output, ini_path=args.ini, - ) \ No newline at end of file + ) diff --git a/dev-tools/validate_binaries.sh b/dev-tools/validate_binaries.sh index 8a312f8873..ef60c3e59c 100755 --- a/dev-tools/validate_binaries.sh +++ b/dev-tools/validate_binaries.sh @@ -216,4 +216,4 @@ echo "============================================================" if [ $FAIL -gt 0 ]; then exit 1 fi -exit 0 \ No newline at end of file +exit 0 From 57e13ed198cc107f5fcc53ac4989916d2a652e23 Mon Sep 17 00:00:00 2001 From: Elizabeth Teng Date: Mon, 9 Mar 2026 16:36:42 -0500 Subject: [PATCH 66/91] separate handling of errored binaries from successful binaries into an error table --- dev-tools/compare_runs.py | 87 ++++++++++++++++--------- dev-tools/script_data/binaries_suite.py | 23 ++++--- 2 files changed, 73 insertions(+), 37 deletions(-) diff --git a/dev-tools/compare_runs.py b/dev-tools/compare_runs.py index a19c0f9ddc..d2fbab7545 100644 --- a/dev-tools/compare_runs.py +++ b/dev-tools/compare_runs.py @@ -19,12 +19,12 @@ """ import argparse -import os import sys - +import os import numpy as np import pandas as pd + # Columns that represent qualitative (categorical) evolution properties. # Any column matching these names will be compared as exact string matches # and reported under "QUALITATIVE" differences. @@ -80,30 +80,6 @@ def compare_evolution_tables(base_df, cand_df, rtol, atol): b = base_df[base_df['binary_id'] == bid].reset_index(drop=True) c = cand_df[cand_df['binary_id'] == bid].reset_index(drop=True) - # ── Error status changes ────────────────────────────────────── - base_failed = 'exception_type' in b.columns and b['exception_type'].notna().any() - cand_failed = 'exception_type' in c.columns and c['exception_type'].notna().any() - - if base_failed != cand_failed: - if cand_failed: - exc = c['exception_type'].dropna().iloc[0] if 'exception_type' in c.columns else "unknown" - msg = c['exception_message'].dropna().iloc[0] if 'exception_message' in c.columns else "" - struct_diffs.append(f"Binary {bid}: NEWLY FAILING ({exc}: {msg})") - else: - struct_diffs.append(f"Binary {bid}: NEWLY PASSING (was failing in baseline)") - continue - - if base_failed and cand_failed: - b_exc = str(b['exception_type'].dropna().iloc[0]) if 'exception_type' in b.columns else "" - c_exc = str(c['exception_type'].dropna().iloc[0]) if 'exception_type' in c.columns else "" - b_msg = str(b['exception_message'].dropna().iloc[0]) if 'exception_message' in b.columns else "" - c_msg = str(c['exception_message'].dropna().iloc[0]) if 'exception_message' in c.columns else "" - if b_exc != c_exc: - struct_diffs.append(f"Binary {bid}: error type changed ('{b_exc}' -> '{c_exc}')") - if b_msg != c_msg: - struct_diffs.append(f"Binary {bid}: error message changed ('{b_msg}' -> '{c_msg}')") - continue - # ── Step count ──────────────────────────────────────────────── if len(b) != len(c): struct_diffs.append( @@ -260,6 +236,52 @@ def compare_warnings_tables(base_df, cand_df): return diffs +def compare_errors_tables(base_df, cand_df): + """Compare error tables between baseline and candidate. + + Returns list of diff strings. + """ + diffs = [] + + if base_df is None and cand_df is None: + return diffs + if base_df is None and cand_df is not None: + cand_ids = sorted(cand_df['binary_id'].unique()) if 'binary_id' in cand_df.columns else [] + diffs.append(f"Candidate has {len(cand_df)} error(s) (binaries {cand_ids}), baseline has none") + return diffs + if base_df is not None and cand_df is None: + base_ids = sorted(base_df['binary_id'].unique()) if 'binary_id' in base_df.columns else [] + diffs.append(f"Baseline has {len(base_df)} error(s) (binaries {base_ids}), candidate has none") + return diffs + + # Compare per-binary errors + if 'binary_id' in base_df.columns and 'binary_id' in cand_df.columns: + base_ids = set(base_df['binary_id'].unique()) + cand_ids = set(cand_df['binary_id'].unique()) + + for bid in sorted(cand_ids - base_ids): + row = cand_df[cand_df['binary_id'] == bid].iloc[0] + exc = row.get('exception_type', 'unknown') + diffs.append(f"Binary {bid}: NEWLY FAILING in candidate ({exc})") + + for bid in sorted(base_ids - cand_ids): + diffs.append(f"Binary {bid}: NEWLY PASSING in candidate (was failing in baseline)") + + for bid in sorted(base_ids & cand_ids): + b_row = base_df[base_df['binary_id'] == bid].iloc[0] + c_row = cand_df[cand_df['binary_id'] == bid].iloc[0] + b_exc = str(b_row.get('exception_type', '')) + c_exc = str(c_row.get('exception_type', '')) + b_msg = str(b_row.get('exception_message', '')) + c_msg = str(c_row.get('exception_message', '')) + if b_exc != c_exc: + diffs.append(f"Binary {bid}: error type changed ('{b_exc}' -> '{c_exc}')") + if b_msg != c_msg: + diffs.append(f"Binary {bid}: error message changed") + + return diffs + + def read_table_safe(store, key): """Read a table from HDFStore, returning None if it doesn't exist.""" try: @@ -347,12 +369,19 @@ def main(): cand_warn = read_table_safe(cand_store, '/warnings') warn_diffs.extend(compare_warnings_tables(base_warn, cand_warn)) + # ── Errors table ────────────────────────────────────────── + base_err = read_table_safe(base_store, '/errors') + cand_err = read_table_safe(cand_store, '/errors') + error_diffs = compare_errors_tables(base_err, cand_err) + struct_diffs.extend(error_diffs) + # ── Extra/missing top-level keys ────────────────────────── + ignored_keys = {'/evolution', '/warnings', '/errors', '/metadata'} for k in sorted(base_keys - cand_keys): - if k not in ['/evolution', '/warnings', '/metadata']: + if k not in ignored_keys: struct_diffs.append(f"Table '{k}' missing in candidate") for k in sorted(cand_keys - base_keys): - if k not in ['/evolution', '/warnings', '/metadata']: + if k not in ignored_keys: struct_diffs.append(f"Table '{k}' extra in candidate") except Exception as e: @@ -409,4 +438,4 @@ def main(): if __name__ == "__main__": - main() + main() \ No newline at end of file diff --git a/dev-tools/script_data/binaries_suite.py b/dev-tools/script_data/binaries_suite.py index 157dc0dbab..dda3824c75 100644 --- a/dev-tools/script_data/binaries_suite.py +++ b/dev-tools/script_data/binaries_suite.py @@ -43,6 +43,7 @@ def load_inlist(metallicity, verbose, ini_path=None): SimulationProperties object with loaded steps """ if ini_path is None: + # Look for ini file relative to this script's location script_dir = os.path.dirname(os.path.abspath(__file__)) ini_path = os.path.join(script_dir, 'binaries_params.ini') @@ -53,9 +54,12 @@ def load_inlist(metallicity, verbose, ini_path=None): metallicity_kwargs = {'metallicity': metallicity, 'verbose': verbose} - metallicity_steps = ['step_HMS_HMS', 'step_CO_HeMS', 'step_CO_HMS_RLO', - 'step_CO_HeMS_RLO', 'step_detached', 'step_disrupted', - 'step_merged', 'step_initially_single'] + # Apply metallicity to all steps that need it + metallicity_steps = [ + 'step_HMS_HMS', 'step_CO_HeMS', 'step_CO_HMS_RLO', + 'step_CO_HeMS_RLO', 'step_detached', 'step_disrupted', + 'step_merged', 'step_initially_single' + ] for step_name in metallicity_steps: if step_name in sim_kwargs: sim_kwargs[step_name][1].update(metallicity_kwargs) @@ -101,7 +105,6 @@ def print_failed_binary(binary,e, max_error_lines=3): df = binary.to_df(**{'extra_columns':{'step_names':'str'}}) if len(df) > 0: # Select only the desired columns - available_columns = [col for col in COLUMNS_TO_SHOW if col in df.columns] df_filtered = df[available_columns].reset_index(drop=True) @@ -163,12 +166,16 @@ def warning_handler(message, category, filename, lineno, file=None, line=None): except Exception as e: print_failed_binary(binary, e) - # If evolution fails, create a minimal df with error info - evolution_df = pd.DataFrame([{ + # Save error to separate table (different schema from evolution) + error_df = pd.DataFrame([{ "binary_id": int(binary_id), "exception_type": type(e).__name__, "exception_message": str(e) }]) + error_string_cols = error_df.select_dtypes([object]).columns + error_min_itemsize = {col: 1000 for col in error_string_cols} + h5file.append("errors", error_df, format="table", + min_itemsize=error_min_itemsize) finally: warnings.showwarning = old_showwarning @@ -191,7 +198,7 @@ def warning_handler(message, category, filename, lineno, file=None, line=None): # Determine min_itemsize from the dataframe we're actually saving string_cols = evolution_df.select_dtypes([object]).columns - min_itemsize = {col: 100 for col in string_cols} + min_itemsize = {col: 500 for col in string_cols} h5file.append("evolution", evolution_df, format="table", data_columns=True, min_itemsize=min_itemsize) @@ -200,7 +207,7 @@ def warning_handler(message, category, filename, lineno, file=None, line=None): warn_df = pd.DataFrame(captured_warnings) # Ensure consistent string column sizes for warnings table warn_string_cols = warn_df.select_dtypes([object]).columns - warn_min_itemsize = {col: 200 for col in warn_string_cols} + warn_min_itemsize = {col: 1000 for col in warn_string_cols} h5file.append("warnings", warn_df, format="table", min_itemsize=warn_min_itemsize) print(f"āš ļø {len(captured_warnings)} warning(s) raised during evolution:") From ea435933340ab7916fe237dc41ad90204c167215 Mon Sep 17 00:00:00 2001 From: Elizabeth Teng Date: Mon, 9 Mar 2026 16:52:58 -0500 Subject: [PATCH 67/91] consolidate h5 writes for efficiency --- dev-tools/script_data/binaries_suite.py | 94 ++++++++++++++++--------- 1 file changed, 59 insertions(+), 35 deletions(-) diff --git a/dev-tools/script_data/binaries_suite.py b/dev-tools/script_data/binaries_suite.py index dda3824c75..8339adbbb4 100644 --- a/dev-tools/script_data/binaries_suite.py +++ b/dev-tools/script_data/binaries_suite.py @@ -31,6 +31,11 @@ 'S1_state', 'S1_mass', 'S2_state', 'S2_mass', 'orbital_period'] +# Suppress fragmentation warnings from POSYDON internals. +# The .copy() calls below already handle the actual performance impact; +# these warnings are just noise from to_df() building DataFrames column-by-column. +# warnings.filterwarnings("ignore", message=".*DataFrame is highly fragmented.*") + def load_inlist(metallicity, verbose, ini_path=None): """Load simulation properties from ini file and configure for given metallicity. @@ -157,6 +162,7 @@ def warning_handler(message, category, filename, lineno, file=None, line=None): print(f"Binary {binary_id}") evolution_df = None + error_df = None try: binary.evolve() @@ -166,16 +172,11 @@ def warning_handler(message, category, filename, lineno, file=None, line=None): except Exception as e: print_failed_binary(binary, e) - # Save error to separate table (different schema from evolution) error_df = pd.DataFrame([{ "binary_id": int(binary_id), "exception_type": type(e).__name__, "exception_message": str(e) }]) - error_string_cols = error_df.select_dtypes([object]).columns - error_min_itemsize = {col: 1000 for col in error_string_cols} - h5file.append("errors", error_df, format="table", - min_itemsize=error_min_itemsize) finally: warnings.showwarning = old_showwarning @@ -193,23 +194,11 @@ def warning_handler(message, category, filename, lineno, file=None, line=None): if "binary_id" not in evolution_df.columns: evolution_df["binary_id"] = int(binary_id) - # Defragment + # Defragment the DataFrame from POSYDON's column-by-column construction evolution_df = evolution_df.copy() - # Determine min_itemsize from the dataframe we're actually saving - string_cols = evolution_df.select_dtypes([object]).columns - min_itemsize = {col: 500 for col in string_cols} - h5file.append("evolution", evolution_df, format="table", - data_columns=True, min_itemsize=min_itemsize) - # Save warnings if captured_warnings: - warn_df = pd.DataFrame(captured_warnings) - # Ensure consistent string column sizes for warnings table - warn_string_cols = warn_df.select_dtypes([object]).columns - warn_min_itemsize = {col: 1000 for col in warn_string_cols} - h5file.append("warnings", warn_df, format="table", - min_itemsize=warn_min_itemsize) print(f"āš ļø {len(captured_warnings)} warning(s) raised during evolution:") for i, w in enumerate(captured_warnings[:3], 1): print(f" {i}. {w['category']}: {w['message'][:80]}") @@ -221,8 +210,6 @@ def warning_handler(message, category, filename, lineno, file=None, line=None): print(f"āœ… Finished binary {binary_id}") print("=" * LINE_LENGTH) - - def get_test_binaries(metallicity, sim_prop): """Return the list of test binaries as (star1_kwargs, star2_kwargs, binary_kwargs, description) tuples. @@ -647,7 +634,38 @@ def evolve_binaries(metallicity, verbose, output_path, ini_path=None): sim_prop = load_inlist(metallicity, verbose, ini_path) test_binaries = get_test_binaries(metallicity, sim_prop) - + + # Collect all results in memory, then write once at the end. + # This avoids repeated HDFStore.append() calls, each of which + # reconciles schemas, checks string sizing, and flushes to disk. + all_evolution_dfs = [] + all_error_dfs = [] + all_warning_dfs = [] + + for binary_id, (s1_kw, s2_kw, bin_kw, description) in enumerate(test_binaries): + print(f"\n[{binary_id}/{len(test_binaries)-1}] {description}") + + star_1 = SingleStar(**s1_kw) + star_2 = SingleStar(**s2_kw) + + # Add separation from period if not explicitly provided + if 'separation' not in bin_kw and 'orbital_period' in bin_kw: + bin_kw['separation'] = orbital_separation_from_period( + bin_kw['orbital_period'], star_1.mass, star_2.mass + ) + + binary = BinaryStar(star_1, star_2, **bin_kw, properties=sim_prop) + evo_df, err_df, warn_list = evolve_binary(binary, binary_id) + + if evo_df is not None: + all_evolution_dfs.append(evo_df) + if err_df is not None: + all_error_dfs.append(err_df) + if warn_list: + all_warning_dfs.append(pd.DataFrame(warn_list)) + + + # ── Single-pass HDF5 write ────────────────────────────────────────── with pd.HDFStore(output_path, mode="w") as h5file: # Save metadata meta_df = pd.DataFrame([{ @@ -656,20 +674,26 @@ def evolve_binaries(metallicity, verbose, output_path, ini_path=None): }]) h5file.put("metadata", meta_df, format="table") - for binary_id, (s1_kw, s2_kw, bin_kw, description) in enumerate(test_binaries): - print(f"\n[{binary_id}/{len(test_binaries)-1}] {description}") - - star_1 = SingleStar(**s1_kw) - star_2 = SingleStar(**s2_kw) - - # Add separation from period if not explicitly provided - if 'separation' not in bin_kw and 'orbital_period' in bin_kw: - bin_kw['separation'] = orbital_separation_from_period( - bin_kw['orbital_period'], star_1.mass, star_2.mass - ) - - binary = BinaryStar(star_1, star_2, **bin_kw, properties=sim_prop) - evolve_binary(binary, h5file, binary_id) + if all_evolution_dfs: + combined_evo = pd.concat(all_evolution_dfs, ignore_index=True) + string_cols = combined_evo.select_dtypes([object]).columns + min_itemsize = {col: 500 for col in string_cols} + h5file.put("evolution", combined_evo, format="table", + data_columns=True, min_itemsize=min_itemsize) + + if all_error_dfs: + combined_err = pd.concat(all_error_dfs, ignore_index=True) + err_string_cols = combined_err.select_dtypes([object]).columns + err_min_itemsize = {col: 1000 for col in err_string_cols} + h5file.put("errors", combined_err, format="table", + min_itemsize=err_min_itemsize) + + if all_warning_dfs: + combined_warn = pd.concat(all_warning_dfs, ignore_index=True) + warn_string_cols = combined_warn.select_dtypes([object]).columns + warn_min_itemsize = {col: 1000 for col in warn_string_cols} + h5file.put("warnings", combined_warn, format="table", + min_itemsize=warn_min_itemsize) print(f"\n{'=' * LINE_LENGTH}") print(f" All {len(test_binaries)} binaries complete. Results saved to {output_path}") From f0807706904e680c5ef0638402aef894d51877d1 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 9 Mar 2026 21:41:30 +0000 Subject: [PATCH 68/91] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- dev-tools/compare_runs.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dev-tools/compare_runs.py b/dev-tools/compare_runs.py index d2fbab7545..b153c5127b 100644 --- a/dev-tools/compare_runs.py +++ b/dev-tools/compare_runs.py @@ -19,12 +19,12 @@ """ import argparse -import sys import os +import sys + import numpy as np import pandas as pd - # Columns that represent qualitative (categorical) evolution properties. # Any column matching these names will be compared as exact string matches # and reported under "QUALITATIVE" differences. @@ -438,4 +438,4 @@ def main(): if __name__ == "__main__": - main() \ No newline at end of file + main() From 435013f45dbee54946b9f55fec621c560e1f5274 Mon Sep 17 00:00:00 2001 From: Elizabeth Teng Date: Mon, 9 Mar 2026 17:01:18 -0500 Subject: [PATCH 69/91] add flag to promote existing evolved branch to baseline status --- dev-tools/generate_baseline.sh | 51 +++++++++++++++++++++++++++------- 1 file changed, 41 insertions(+), 10 deletions(-) diff --git a/dev-tools/generate_baseline.sh b/dev-tools/generate_baseline.sh index 845b52cf3c..3539be5c81 100755 --- a/dev-tools/generate_baseline.sh +++ b/dev-tools/generate_baseline.sh @@ -7,12 +7,15 @@ # # Usage: # ./generate_baseline.sh [sha] [metallicities] +# ./generate_baseline.sh --promote [metallicities] # # Examples: -# ./generate_baseline.sh main # baseline from main, all Z +# ./generate_baseline.sh main # evolve + save baseline, all Z # ./generate_baseline.sh v2.1.0 # baseline from a release tag # ./generate_baseline.sh main abc123f # baseline from a specific commit # ./generate_baseline.sh main "" "1 0.45" # baseline for subset of Z +# ./generate_baseline.sh --promote main # promote existing outputs to baseline +# ./generate_baseline.sh --promote main "1 0.45" # promote subset of existing outputs # # Output: # baselines//baseline_Zsun.h5 — one file per metallicity @@ -21,26 +24,54 @@ set -euo pipefail +# ── Parse arguments ─────────────────────────────────────────────────────── +PROMOTE=false +if [ "${1:-}" = "--promote" ]; then + PROMOTE=true + shift +fi + BRANCH=${1:-main} -SHA=${2:-} -METALLICITIES=${3:-"2 1 0.45 0.2 0.1 0.01 0.001 0.0001"} +if [ "$PROMOTE" = true ]; then + SHA="" + METALLICITIES=${2:-"2 1 0.45 0.2 0.1 0.01 0.001 0.0001"} +else + SHA=${2:-} + METALLICITIES=${3:-"2 1 0.45 0.2 0.1 0.01 0.001 0.0001"} +fi SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" SAFE_BRANCH="${BRANCH//\//_}" BASELINE_DIR="$SCRIPT_DIR/baselines/${SAFE_BRANCH}" +CANDIDATE_DIR="$SCRIPT_DIR/outputs/${SAFE_BRANCH}" echo "============================================================" echo " POSYDON Binary Validation — Generating Baseline" echo " Branch: $BRANCH" -echo " SHA: ${SHA:-HEAD}" +if [ "$PROMOTE" = true ]; then + echo " Mode: --promote (using existing outputs)" +else + echo " SHA: ${SHA:-HEAD}" +fi echo " Metallicities: $METALLICITIES" echo " Output dir: $BASELINE_DIR" echo "============================================================" -# ── Step 1: Evolve binaries for the baseline branch ────────────────────── -echo "" -echo "Step 1: Evolving binaries on branch '$BRANCH'..." -"$SCRIPT_DIR/evolve_binaries.sh" "$BRANCH" "$SHA" "$METALLICITIES" +# ── Step 1: Evolve binaries (skip if --promote) ────────────────────────── +if [ "$PROMOTE" = true ]; then + echo "" + echo "Step 1: SKIPPED (--promote: using existing outputs in $CANDIDATE_DIR)" + + if [ ! -d "$CANDIDATE_DIR" ]; then + echo "ERROR: No outputs found at $CANDIDATE_DIR" >&2 + echo "Run evolve_binaries.sh first, or drop --promote to evolve from scratch." >&2 + exit 1 + fi +else + echo "" + echo "Step 1: Evolving binaries on branch '$BRANCH'..." + "$SCRIPT_DIR/evolve_binaries.sh" "$BRANCH" "$SHA" "$METALLICITIES" +fi # ── Step 2: Copy results into the baselines directory ──────────────────── echo "" @@ -48,7 +79,6 @@ echo "Step 2: Copying results to baseline directory..." mkdir -p "$BASELINE_DIR" -CANDIDATE_DIR="$SCRIPT_DIR/outputs/${SAFE_BRANCH}" COPIED=0 for Z in $METALLICITIES; do @@ -78,6 +108,7 @@ POSYDON Binary Validation Baseline Branch: $BRANCH Commit SHA: ${ACTUAL_SHA:-unknown} Requested SHA: ${SHA:-HEAD} +Mode: $([ "$PROMOTE" = true ] && echo "promoted from existing outputs" || echo "evolved from scratch") Generated: $(date -u '+%Y-%m-%d %H:%M:%S UTC') Metallicities: $METALLICITIES Files: $COPIED @@ -93,4 +124,4 @@ echo "============================================================" if [ $COPIED -eq 0 ]; then echo "ERROR: No baseline files were created!" >&2 exit 1 -fi +fi \ No newline at end of file From 6474dead6eb311e37770fd1129a2642d026c7f31 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 9 Mar 2026 21:58:35 +0000 Subject: [PATCH 70/91] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- dev-tools/script_data/binaries_suite.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dev-tools/script_data/binaries_suite.py b/dev-tools/script_data/binaries_suite.py index 8339adbbb4..5cd8be7147 100644 --- a/dev-tools/script_data/binaries_suite.py +++ b/dev-tools/script_data/binaries_suite.py @@ -634,14 +634,14 @@ def evolve_binaries(metallicity, verbose, output_path, ini_path=None): sim_prop = load_inlist(metallicity, verbose, ini_path) test_binaries = get_test_binaries(metallicity, sim_prop) - + # Collect all results in memory, then write once at the end. # This avoids repeated HDFStore.append() calls, each of which # reconciles schemas, checks string sizing, and flushes to disk. all_evolution_dfs = [] all_error_dfs = [] all_warning_dfs = [] - + for binary_id, (s1_kw, s2_kw, bin_kw, description) in enumerate(test_binaries): print(f"\n[{binary_id}/{len(test_binaries)-1}] {description}") From e157c0119c71aa21a85c1834b2907d0bbaa28703 Mon Sep 17 00:00:00 2001 From: Elizabeth Teng Date: Mon, 9 Mar 2026 17:07:02 -0500 Subject: [PATCH 71/91] Move binaries_suite.py and binaries_params.ini to dev-tools root --- dev-tools/{script_data => }/binaries_params.ini | 0 dev-tools/{script_data => }/binaries_suite.py | 0 dev-tools/evolve_binaries.sh | 2 +- 3 files changed, 1 insertion(+), 1 deletion(-) rename dev-tools/{script_data => }/binaries_params.ini (100%) rename dev-tools/{script_data => }/binaries_suite.py (100%) diff --git a/dev-tools/script_data/binaries_params.ini b/dev-tools/binaries_params.ini similarity index 100% rename from dev-tools/script_data/binaries_params.ini rename to dev-tools/binaries_params.ini diff --git a/dev-tools/script_data/binaries_suite.py b/dev-tools/binaries_suite.py similarity index 100% rename from dev-tools/script_data/binaries_suite.py rename to dev-tools/binaries_suite.py diff --git a/dev-tools/evolve_binaries.sh b/dev-tools/evolve_binaries.sh index 30f7d7b745..e6b6a90c7e 100755 --- a/dev-tools/evolve_binaries.sh +++ b/dev-tools/evolve_binaries.sh @@ -106,7 +106,7 @@ echo "šŸ“¦ Installing POSYDON" pip install -e "$CLONE_DIR" -q 2>&1 | sed 's/^/ /' # ── Run Suite for Each Metallicity ──────────────────────────────────────── -SUITE_SCRIPT="$SCRIPT_DIR/script_data/binaries_suite.py" +SUITE_SCRIPT="$SCRIPT_DIR/binaries_suite.py" FAILED=0 for Z in $METALLICITIES; do From 5357e0b93fd2f3c31e969620a062291947bd3a84 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 9 Mar 2026 22:04:58 +0000 Subject: [PATCH 72/91] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- dev-tools/generate_baseline.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev-tools/generate_baseline.sh b/dev-tools/generate_baseline.sh index 3539be5c81..fa407d0cbc 100755 --- a/dev-tools/generate_baseline.sh +++ b/dev-tools/generate_baseline.sh @@ -124,4 +124,4 @@ echo "============================================================" if [ $COPIED -eq 0 ]; then echo "ERROR: No baseline files were created!" >&2 exit 1 -fi \ No newline at end of file +fi From 545db6c880b2d5469ee143b4147b99d071a920b8 Mon Sep 17 00:00:00 2001 From: Elizabeth Teng <41969755+elizabethteng@users.noreply.github.com> Date: Mon, 9 Mar 2026 17:10:29 -0500 Subject: [PATCH 73/91] Delete dev-tools/outputs/baseline.h5 --- dev-tools/outputs/baseline.h5 | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 dev-tools/outputs/baseline.h5 diff --git a/dev-tools/outputs/baseline.h5 b/dev-tools/outputs/baseline.h5 deleted file mode 100644 index e69de29bb2..0000000000 From 17b9839bb63284651ad223214ddcf9b0fcaa8040 Mon Sep 17 00:00:00 2001 From: Elizabeth Teng <41969755+elizabethteng@users.noreply.github.com> Date: Mon, 9 Mar 2026 17:14:25 -0500 Subject: [PATCH 74/91] add readme --- dev-tools/README.md | 87 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) create mode 100644 dev-tools/README.md diff --git a/dev-tools/README.md b/dev-tools/README.md new file mode 100644 index 0000000000..7732d50af1 --- /dev/null +++ b/dev-tools/README.md @@ -0,0 +1,87 @@ +# dev-tools + +Validation suite for POSYDON binary evolution. Evolves a fixed set of test binaries on a candidate branch and compares results against a stored baseline to catch regressions. + +## Quick Start + +```bash +# 1. Generate a baseline from the main branch (once) +./generate_baseline.sh main + +# 2. Validate a candidate branch against that baseline +./validate_binaries.sh feature/my-branch +``` + +## Scripts + +### `validate_binaries.sh` + +Top-level entry point. Evolves test binaries on a candidate branch, then compares results against a baseline. + +```bash +./validate_binaries.sh [baseline_branch] [metallicities] [--loose] [--rtol VALUE] [--atol VALUE] +``` + +By default, comparison is exact (rtol=0, atol=0). Use `--loose` for relaxed floating-point tolerances (rtol=1e-12, atol=1e-15), or set `--rtol`/`--atol` explicitly. + +### `generate_baseline.sh` + +Generates baseline HDF5 files from a designated branch or tag. Can also promote existing outputs to baseline with `--promote`. + +```bash +./generate_baseline.sh [sha] [metallicities] +./generate_baseline.sh --promote [metallicities] +``` + +### `evolve_binaries.sh` + +Clones a POSYDON branch, creates a conda environment, installs POSYDON, and runs the binary suite at all requested metallicities. Called by `validate_binaries.sh` and `generate_baseline.sh`; can also be run standalone. + +```bash +./evolve_binaries.sh [sha] [metallicities] +``` + +### `binaries_suite.py` + +Defines and evolves the set of 44 test binaries at a given metallicity. Each binary targets a specific edge case or past bug fix (e.g., matching failures, oRLO2 looping, SN type errors, NaN spins). Results are saved to an HDF5 file. + +```bash +python binaries_suite.py --output results.h5 --metallicity 1 +``` + +### `compare_runs.py` + +Compares two HDF5 files produced by `binaries_suite.py`. Reports three categories of differences: structural (missing binaries, step count changes, new errors), qualitative (state/event/step name changes), and quantitative (numeric value changes). + +```bash +python compare_runs.py baseline.h5 candidate.h5 [--loose] [--rtol VALUE] [--atol VALUE] [--verbose] +``` + +### `binaries_params.ini` + +Configuration file for `SimulationProperties`. Defines the POSYDON evolution steps, supernova prescriptions, common envelope parameters, and output column selections. Metallicity is overridden at runtime by `binaries_suite.py`. + +## Directory Structure + +``` +dev-tools/ +ā”œā”€ā”€ README.md +ā”œā”€ā”€ validate_binaries.sh # full validation pipeline +ā”œā”€ā”€ generate_baseline.sh # create or promote baselines +ā”œā”€ā”€ evolve_binaries.sh # clone, install, and run suite +ā”œā”€ā”€ binaries_suite.py # test binary definitions and evolution +ā”œā”€ā”€ binaries_params.ini # SimulationProperties configuration +ā”œā”€ā”€ compare_runs.py # diff two HDF5 result files +ā”œā”€ā”€ baselines/ # stored baseline HDF5 files (per branch) +ā”œā”€ā”€ outputs/ # candidate evolution results (per branch) +ā”œā”€ā”€ logs/ # per-metallicity evolution logs (per branch) +└── workdirs/ # cloned repos and conda environments (per branch) +``` + +## Available Metallicities + +The suite supports metallicities (in solar units): 2, 1, 0.45, 0.2, 0.1, 0.01, 0.001, 0.0001. All are run by default; pass a quoted subset to limit, e.g. `"1 0.45"`. + +## Authors + +Max Briel, Elizabeth Teng From 2ee28f968267ebb8cbfdfb30ac5ad2c53e410225 Mon Sep 17 00:00:00 2001 From: Elizabeth Teng <41969755+elizabethteng@users.noreply.github.com> Date: Mon, 9 Mar 2026 17:17:21 -0500 Subject: [PATCH 75/91] Update README.md --- dev-tools/README.md | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/dev-tools/README.md b/dev-tools/README.md index 7732d50af1..b75aa74fc0 100644 --- a/dev-tools/README.md +++ b/dev-tools/README.md @@ -1,5 +1,3 @@ -# dev-tools - Validation suite for POSYDON binary evolution. Evolves a fixed set of test binaries on a candidate branch and compares results against a stored baseline to catch regressions. ## Quick Start @@ -16,7 +14,7 @@ Validation suite for POSYDON binary evolution. Evolves a fixed set of test binar ### `validate_binaries.sh` -Top-level entry point. Evolves test binaries on a candidate branch, then compares results against a baseline. +Top-level entry point. Evolves test binaries on a candidate branch, then compares results against an existing baseline. ```bash ./validate_binaries.sh [baseline_branch] [metallicities] [--loose] [--rtol VALUE] [--atol VALUE] @@ -77,11 +75,3 @@ dev-tools/ ā”œā”€ā”€ logs/ # per-metallicity evolution logs (per branch) └── workdirs/ # cloned repos and conda environments (per branch) ``` - -## Available Metallicities - -The suite supports metallicities (in solar units): 2, 1, 0.45, 0.2, 0.1, 0.01, 0.001, 0.0001. All are run by default; pass a quoted subset to limit, e.g. `"1 0.45"`. - -## Authors - -Max Briel, Elizabeth Teng From 74ae017b2790a85f7551c2b4448b44b2770d860b Mon Sep 17 00:00:00 2001 From: Elizabeth Teng <41969755+elizabethteng@users.noreply.github.com> Date: Mon, 9 Mar 2026 17:26:14 -0500 Subject: [PATCH 76/91] Update README.md --- dev-tools/README.md | 55 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 54 insertions(+), 1 deletion(-) diff --git a/dev-tools/README.md b/dev-tools/README.md index b75aa74fc0..4b74b1b1e5 100644 --- a/dev-tools/README.md +++ b/dev-tools/README.md @@ -10,6 +10,19 @@ Validation suite for POSYDON binary evolution. Evolves a fixed set of test binar ./validate_binaries.sh feature/my-branch ``` +Results are written to `outputs//`. After validation, check: + +- `outputs//comparison_summary.txt` for a pass/fail overview across all metallicities +- `outputs//comparison_Zsun.txt` for detailed per-metallicity diff reports +- `logs//evolve_Zsun.log` for the full evolution output of each metallicity + +By default, all eight POSYDON metallicities are run. To validate only a subset, pass a quoted space-separated list as the third argument: + +```bash +./generate_baseline.sh main "" "1 0.45" +./validate_binaries.sh feature/my-branch main "1 0.45" +``` + ## Scripts ### `validate_binaries.sh` @@ -49,7 +62,13 @@ python binaries_suite.py --output results.h5 --metallicity 1 ### `compare_runs.py` -Compares two HDF5 files produced by `binaries_suite.py`. Reports three categories of differences: structural (missing binaries, step count changes, new errors), qualitative (state/event/step name changes), and quantitative (numeric value changes). +Compares two HDF5 files produced by `binaries_suite.py` and reports differences in three categories: + +- **Structural**: missing or extra binaries, evolution step count changes, binaries that newly fail or newly pass, missing HDF5 tables. +- **Qualitative**: changes to categorical columns such as state, event, step name, SN type, interpolation class, and mass transfer history. +- **Quantitative**: changes to any numeric column. By default, comparison is exact (bitwise identical floats). Use `--loose` for slightly relaxed tolerances (rtol=1e-12, atol=1e-15), or set `--rtol`/`--atol` explicitly. + +The script also compares warning and error tables, reporting new, removed, or changed warnings per binary. ```bash python compare_runs.py baseline.h5 candidate.h5 [--loose] [--rtol VALUE] [--atol VALUE] [--verbose] @@ -59,6 +78,40 @@ python compare_runs.py baseline.h5 candidate.h5 [--loose] [--rtol VALUE] [--atol Configuration file for `SimulationProperties`. Defines the POSYDON evolution steps, supernova prescriptions, common envelope parameters, and output column selections. Metallicity is overridden at runtime by `binaries_suite.py`. +## Running Scripts Manually + +The shell scripts handle cloning, environment setup, and orchestration. If you already have POSYDON installed in your current environment, you can run the Python scripts directly. + +### Evolving binaries + +```bash +# Evolve all 44 test binaries at solar metallicity +python binaries_suite.py --output my_results.h5 --metallicity 1 + +# Evolve at a specific metallicity with verbose output +python binaries_suite.py --output my_results.h5 --metallicity 0.01 --verbose + +# Use a custom ini file +python binaries_suite.py --output my_results.h5 --metallicity 1 --ini /path/to/custom.ini +``` + +The output HDF5 contains three tables: `evolution` (per-step binary data), `errors` (binaries that failed), and `warnings` (warnings raised during evolution). + +### Comparing two result files + +```bash +# Exact comparison +python compare_runs.py file_a.h5 file_b.h5 + +# Relaxed tolerances +python compare_runs.py file_a.h5 file_b.h5 --loose + +# Custom tolerances with verbose diagnostics +python compare_runs.py file_a.h5 file_b.h5 --rtol 1e-8 --atol 1e-12 --verbose +``` + +The two files do not need to come from the shell pipeline; any pair of HDF5 files produced by `binaries_suite.py` can be compared. + ## Directory Structure ``` From a254306eda45353d554895afeef92d80776808e7 Mon Sep 17 00:00:00 2001 From: Elizabeth Teng Date: Mon, 9 Mar 2026 17:42:31 -0500 Subject: [PATCH 77/91] minor change --- dev-tools/compare_runs.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dev-tools/compare_runs.py b/dev-tools/compare_runs.py index b153c5127b..d2fbab7545 100644 --- a/dev-tools/compare_runs.py +++ b/dev-tools/compare_runs.py @@ -19,12 +19,12 @@ """ import argparse -import os import sys - +import os import numpy as np import pandas as pd + # Columns that represent qualitative (categorical) evolution properties. # Any column matching these names will be compared as exact string matches # and reported under "QUALITATIVE" differences. @@ -438,4 +438,4 @@ def main(): if __name__ == "__main__": - main() + main() \ No newline at end of file From c9b265ceb7835344a39c59ef616aa4c2a0ec6912 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 9 Mar 2026 22:46:48 +0000 Subject: [PATCH 78/91] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- dev-tools/compare_runs.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/dev-tools/compare_runs.py b/dev-tools/compare_runs.py index 7da74f0859..da206e3d55 100644 --- a/dev-tools/compare_runs.py +++ b/dev-tools/compare_runs.py @@ -19,13 +19,14 @@ """ import argparse + <<<<<<< HEAD -import sys import os +import sys + import numpy as np import pandas as pd - ======= import os import sys From d95c17a655390404dfdca5887ff66333f54e2762 Mon Sep 17 00:00:00 2001 From: Elizabeth Teng Date: Mon, 9 Mar 2026 17:48:49 -0500 Subject: [PATCH 79/91] remove rebase artifacts --- dev-tools/compare_runs.py | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/dev-tools/compare_runs.py b/dev-tools/compare_runs.py index 7da74f0859..48708d3110 100644 --- a/dev-tools/compare_runs.py +++ b/dev-tools/compare_runs.py @@ -19,21 +19,11 @@ """ import argparse -<<<<<<< HEAD import sys import os import numpy as np import pandas as pd - -======= -import os -import sys - -import numpy as np -import pandas as pd - ->>>>>>> d0eaf915cf9f6c5ab67263acb5537facb676c1b8 # Columns that represent qualitative (categorical) evolution properties. # Any column matching these names will be compared as exact string matches # and reported under "QUALITATIVE" differences. @@ -447,8 +437,4 @@ def main(): if __name__ == "__main__": -<<<<<<< HEAD - main() -======= main() ->>>>>>> d0eaf915cf9f6c5ab67263acb5537facb676c1b8 From 108e34ca789604c1d15a628b0c1b3a04b2af394e Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 9 Mar 2026 22:51:32 +0000 Subject: [PATCH 80/91] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- dev-tools/compare_runs.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/dev-tools/compare_runs.py b/dev-tools/compare_runs.py index 48708d3110..b153c5127b 100644 --- a/dev-tools/compare_runs.py +++ b/dev-tools/compare_runs.py @@ -19,8 +19,9 @@ """ import argparse -import sys import os +import sys + import numpy as np import pandas as pd From 033123298b5fcf2306fe4770b6d9f70e0e7b1a7b Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 9 Mar 2026 23:04:46 +0000 Subject: [PATCH 81/91] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- dev-tools/binaries_suite.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev-tools/binaries_suite.py b/dev-tools/binaries_suite.py index 594ecac570..f58d82a2f6 100644 --- a/dev-tools/binaries_suite.py +++ b/dev-tools/binaries_suite.py @@ -209,7 +209,7 @@ def warning_handler(message, category, filename, lineno, file=None, line=None): print(f"āœ… Finished binary {binary_id}") print("=" * LINE_LENGTH) - + return evolution_df, error_df, captured_warnings def get_test_binaries(metallicity, sim_prop): From fe10943c1ce75a5bff30ec5b1335eb21ecc3987d Mon Sep 17 00:00:00 2001 From: Elizabeth Teng <41969755+elizabethteng@users.noreply.github.com> Date: Wed, 11 Mar 2026 15:39:31 -0500 Subject: [PATCH 82/91] Update validate_binaries.sh to add guidance about tolerances --- dev-tools/validate_binaries.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dev-tools/validate_binaries.sh b/dev-tools/validate_binaries.sh index ef60c3e59c..9f454a3344 100755 --- a/dev-tools/validate_binaries.sh +++ b/dev-tools/validate_binaries.sh @@ -17,8 +17,8 @@ # Tolerance flags (passed through to compare_runs.py): # --loose Use relaxed floating-point tolerances # (rtol=1e-12, atol=1e-15 unless overridden) -# --rtol VALUE Set explicit relative tolerance -# --atol VALUE Set explicit absolute tolerance +# --rtol VALUE Set explicit relative tolerance as per np.allclose +# --atol VALUE Set explicit absolute tolerance as per np.allclose # # --rtol and --atol can be combined with --loose (explicit values take # precedence over the --loose defaults) or used on their own without --loose. From a4fa52c6fb5c60b50025cb0ba9c2ad9ad87d9419 Mon Sep 17 00:00:00 2001 From: Elizabeth Teng <41969755+elizabethteng@users.noreply.github.com> Date: Wed, 11 Mar 2026 15:40:46 -0500 Subject: [PATCH 83/91] Update README.md to add guidance about tolerances --- dev-tools/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev-tools/README.md b/dev-tools/README.md index 4b74b1b1e5..fe1d2f2c8e 100644 --- a/dev-tools/README.md +++ b/dev-tools/README.md @@ -33,7 +33,7 @@ Top-level entry point. Evolves test binaries on a candidate branch, then compare ./validate_binaries.sh [baseline_branch] [metallicities] [--loose] [--rtol VALUE] [--atol VALUE] ``` -By default, comparison is exact (rtol=0, atol=0). Use `--loose` for relaxed floating-point tolerances (rtol=1e-12, atol=1e-15), or set `--rtol`/`--atol` explicitly. +By default, comparison is exact (rtol=0, atol=0). Use `--loose` for relaxed floating-point tolerances (rtol=1e-12, atol=1e-15), or set `--rtol`/`--atol` explicitly as per [np.allclose](https://numpy.org/devdocs/reference/generated/numpy.allclose.html). ### `generate_baseline.sh` From e6ae3c2bd40c4ac598a76af0aa7d5a49b476bf54 Mon Sep 17 00:00:00 2001 From: Elizabeth Teng <41969755+elizabethteng@users.noreply.github.com> Date: Wed, 11 Mar 2026 15:41:12 -0500 Subject: [PATCH 84/91] Update README.md --- dev-tools/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev-tools/README.md b/dev-tools/README.md index fe1d2f2c8e..b1e9339b97 100644 --- a/dev-tools/README.md +++ b/dev-tools/README.md @@ -66,7 +66,7 @@ Compares two HDF5 files produced by `binaries_suite.py` and reports differences - **Structural**: missing or extra binaries, evolution step count changes, binaries that newly fail or newly pass, missing HDF5 tables. - **Qualitative**: changes to categorical columns such as state, event, step name, SN type, interpolation class, and mass transfer history. -- **Quantitative**: changes to any numeric column. By default, comparison is exact (bitwise identical floats). Use `--loose` for slightly relaxed tolerances (rtol=1e-12, atol=1e-15), or set `--rtol`/`--atol` explicitly. +- **Quantitative**: changes to any numeric column. By default, comparison is exact (bitwise identical floats). Use `--loose` for slightly relaxed tolerances (rtol=1e-12, atol=1e-15), or set `--rtol`/`--atol` explicitly as per [np.allclose](https://numpy.org/devdocs/reference/generated/numpy.allclose.html). The script also compares warning and error tables, reporting new, removed, or changed warnings per binary. From 28e6af96e3296fdf24adc8e9020b0407c459acde Mon Sep 17 00:00:00 2001 From: Elizabeth Teng <41969755+elizabethteng@users.noreply.github.com> Date: Thu, 19 Mar 2026 08:25:45 -0500 Subject: [PATCH 85/91] Update binaries_suite.py to save path_to_posydon_data in the H5 metadata --- dev-tools/binaries_suite.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/dev-tools/binaries_suite.py b/dev-tools/binaries_suite.py index f58d82a2f6..1c93360d24 100644 --- a/dev-tools/binaries_suite.py +++ b/dev-tools/binaries_suite.py @@ -21,6 +21,7 @@ from posydon.binary_evol.simulationproperties import SimulationProperties from posydon.popsyn.io import simprop_kwargs_from_ini from posydon.utils.common_functions import orbital_separation_from_period +from posydon.config import PATH_TO_POSYDON_DATA AVAILABLE_METALLICITIES = [2., 1., 0.45, 0.2, 0.1, 0.01, 0.001, 0.0001] @@ -673,6 +674,7 @@ def evolve_binaries(metallicity, verbose, output_path, ini_path=None): meta_df = pd.DataFrame([{ 'metallicity': metallicity, 'n_binaries': len(test_binaries), + 'path_to_posydon_data': PATH_TO_POSYDON_DATA, }]) h5file.put("metadata", meta_df, format="table") From 0bab574bff5b7b8e23b1811136c4b8dfda54673c Mon Sep 17 00:00:00 2001 From: Elizabeth Teng <41969755+elizabethteng@users.noreply.github.com> Date: Thu, 19 Mar 2026 08:33:08 -0500 Subject: [PATCH 86/91] Update generate_baseline.sh to save PATH_TO_POSYDON_DATA to baseline_info.txt --- dev-tools/generate_baseline.sh | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/dev-tools/generate_baseline.sh b/dev-tools/generate_baseline.sh index fa407d0cbc..91a0a173f1 100755 --- a/dev-tools/generate_baseline.sh +++ b/dev-tools/generate_baseline.sh @@ -101,6 +101,24 @@ if [ -d "$CLONE_DIR" ]; then ACTUAL_SHA=$(cd "$CLONE_DIR" && git rev-parse HEAD 2>/dev/null || echo "unknown") fi +# Extract PATH_TO_POSYDON_DATA from the first available baseline HDF5 file +POSYDON_DATA_PATH="unknown" +for Z in $METALLICITIES; do + H5="$BASELINE_DIR/baseline_${Z}Zsun.h5" + if [ -f "$H5" ]; then + POSYDON_DATA_PATH=$(python -c " +import pandas as pd +with pd.HDFStore('$H5', mode='r') as s: + print(s['/metadata']['path_to_posydon_data'].iloc[0]) +" 2>&1) || { + echo " WARNING: Could not read POSYDON data path from $H5" + echo " ($POSYDON_DATA_PATH)" + POSYDON_DATA_PATH="unknown" + } + break + fi +done + INFO_FILE="$BASELINE_DIR/baseline_info.txt" cat > "$INFO_FILE" << EOF POSYDON Binary Validation Baseline @@ -112,6 +130,7 @@ Mode: $([ "$PROMOTE" = true ] && echo "promoted from existing outputs" Generated: $(date -u '+%Y-%m-%d %H:%M:%S UTC') Metallicities: $METALLICITIES Files: $COPIED +POSYDON data: $POSYDON_DATA_PATH EOF echo "" From b1f516654aa41138015e1b204abafae3b8fbb6de Mon Sep 17 00:00:00 2001 From: Elizabeth Teng <41969755+elizabethteng@users.noreply.github.com> Date: Thu, 19 Mar 2026 08:43:24 -0500 Subject: [PATCH 87/91] Update binaries_suite.py to check how many binaries ran and save to metadata in h5 --- dev-tools/binaries_suite.py | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/dev-tools/binaries_suite.py b/dev-tools/binaries_suite.py index 1c93360d24..a4a2c5bf44 100644 --- a/dev-tools/binaries_suite.py +++ b/dev-tools/binaries_suite.py @@ -667,6 +667,24 @@ def evolve_binaries(metallicity, verbose, output_path, ini_path=None): if warn_list: all_warning_dfs.append(pd.DataFrame(warn_list)) + # ── Completeness check ────────────────────────────────────────── + expected_ids = set(range(len(test_binaries))) + evolved_ids = set() + errored_ids = set() + + for df in all_evolution_dfs: + if 'binary_id' in df.columns: + evolved_ids.update(df['binary_id'].unique()) + for df in all_error_dfs: + if 'binary_id' in df.columns: + errored_ids.update(df['binary_id'].unique()) + + accounted_ids = evolved_ids | errored_ids + missing_ids = sorted(expected_ids - accounted_ids) + + if missing_ids: + print(f"\nāš ļø WARNING: {len(missing_ids)} binary(ies) unaccounted for: {missing_ids}") + print(f" These produced neither evolution output nor a caught error.") # ── Single-pass HDF5 write ────────────────────────────────────────── with pd.HDFStore(output_path, mode="w") as h5file: @@ -674,6 +692,10 @@ def evolve_binaries(metallicity, verbose, output_path, ini_path=None): meta_df = pd.DataFrame([{ 'metallicity': metallicity, 'n_binaries': len(test_binaries), + 'n_evolved': len(evolved_ids), + 'n_errored': len(errored_ids), + 'n_missing': len(missing_ids), + 'missing_ids': str(missing_ids) if missing_ids else '', 'path_to_posydon_data': PATH_TO_POSYDON_DATA, }]) h5file.put("metadata", meta_df, format="table") From f2e9361d2f2077e04f92b5e27cd518fd621e37a7 Mon Sep 17 00:00:00 2001 From: Elizabeth Teng <41969755+elizabethteng@users.noreply.github.com> Date: Thu, 19 Mar 2026 08:46:29 -0500 Subject: [PATCH 88/91] Update generate_baseline.sh to check if any binaries didn't run --- dev-tools/generate_baseline.sh | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/dev-tools/generate_baseline.sh b/dev-tools/generate_baseline.sh index 91a0a173f1..a23fc18882 100755 --- a/dev-tools/generate_baseline.sh +++ b/dev-tools/generate_baseline.sh @@ -119,6 +119,29 @@ with pd.HDFStore('$H5', mode='r') as s: fi done +# Check completeness from HDF5 metadata +INCOMPLETE="" +for Z in $METALLICITIES; do + DST="$BASELINE_DIR/baseline_${Z}Zsun.h5" + if [ -f "$DST" ]; then + MISSING=$(python3 -c " +import pandas as pd, sys +try: + with pd.HDFStore('$DST', mode='r') as s: + m = s['/metadata'] + n = int(m['n_missing'].iloc[0]) + if n > 0: + print(f'Z={Z}: {n} missing — {m[\"missing_ids\"].iloc[0]}') +except Exception as e: + print(f'Z={Z}: could not read metadata ({e})', file=sys.stderr) +" 2>/dev/null) + if [ -n "$MISSING" ]; then + echo " āš ļø $MISSING" + INCOMPLETE="${INCOMPLETE} ${MISSING}\n" + fi + fi +done + INFO_FILE="$BASELINE_DIR/baseline_info.txt" cat > "$INFO_FILE" << EOF POSYDON Binary Validation Baseline @@ -133,6 +156,12 @@ Files: $COPIED POSYDON data: $POSYDON_DATA_PATH EOF +if [ -n "$INCOMPLETE" ]; then + printf "\nINCOMPLETE BASELINES:\n%b\n" "$INCOMPLETE" >> "$INFO_FILE" + echo "" + echo "āš ļø WARNING: Some baselines have missing binaries. See $INFO_FILE" +fi + echo "" echo "============================================================" echo " Baseline generated: $COPIED file(s)" From 5c505c8052d5ce37248b15a8230e9c08ff9ff9a6 Mon Sep 17 00:00:00 2001 From: Elizabeth Teng <41969755+elizabethteng@users.noreply.github.com> Date: Thu, 19 Mar 2026 08:52:51 -0500 Subject: [PATCH 89/91] Update compare_runs.py to eliminate redundancies in report (missing binary vs failed binary) --- dev-tools/compare_runs.py | 33 ++++++++++++++++++++++++++------- 1 file changed, 26 insertions(+), 7 deletions(-) diff --git a/dev-tools/compare_runs.py b/dev-tools/compare_runs.py index b153c5127b..d5f4643062 100644 --- a/dev-tools/compare_runs.py +++ b/dev-tools/compare_runs.py @@ -49,9 +49,16 @@ def classify_column(col, dtype): return 'qualitative' -def compare_evolution_tables(base_df, cand_df, rtol, atol): +def compare_evolution_tables(base_df, cand_df, rtol, atol, + base_error_ids=None, cand_error_ids=None): """Compare two evolution DataFrames, reporting per-binary diffs. - + + Args: + base_error_ids: set of binary IDs that errored in the baseline run. + cand_error_ids: set of binary IDs that errored in the candidate run. + Binaries present in these sets are excluded from MISSING/EXTRA + reporting here, since they are already covered by compare_errors_tables. + Returns: dict with keys 'quantitative', 'qualitative', 'structural' each mapping to a list of diff strings. @@ -68,10 +75,14 @@ def compare_evolution_tables(base_df, cand_df, rtol, atol): base_ids = set(base_df['binary_id'].unique()) cand_ids = set(cand_df['binary_id'].unique()) - # Missing/extra binaries + # Missing/extra binaries (excluding those already reported under errors) for bid in sorted(base_ids - cand_ids): + if bid in cand_error_ids: + continue # candidate errored; reported by compare_errors_tables struct_diffs.append(f"Binary {bid}: MISSING in candidate") for bid in sorted(cand_ids - base_ids): + if bid in base_error_ids: + continue # baseline errored; reported by compare_errors_tables struct_diffs.append(f"Binary {bid}: EXTRA in candidate") common_ids = sorted(base_ids & cand_ids) @@ -342,6 +353,15 @@ def main(): print(f"Baseline keys: {sorted(base_keys)}") print(f"Candidate keys: {sorted(cand_keys)}") + # ── Errors table (read early so IDs are available for evolution comparison) + base_err = read_table_safe(base_store, '/errors') + cand_err = read_table_safe(cand_store, '/errors') + + base_error_ids = set(base_err['binary_id'].unique()) \ + if base_err is not None and 'binary_id' in base_err.columns else set() + cand_error_ids = set(cand_err['binary_id'].unique()) \ + if cand_err is not None and 'binary_id' in cand_err.columns else set() + # ── Evolution table ─────────────────────────────────────── base_evol = read_table_safe(base_store, '/evolution') cand_evol = read_table_safe(cand_store, '/evolution') @@ -359,7 +379,8 @@ def main(): print(f"Baseline: {n_base} binaries, {len(base_evol)} total rows") print(f"Candidate: {n_cand} binaries, {len(cand_evol)} total rows") - evol_results = compare_evolution_tables(base_evol, cand_evol, rtol, atol) + evol_results = compare_evolution_tables(base_evol, cand_evol, rtol, atol, + base_error_ids, cand_error_ids) quant_diffs.extend(evol_results['quantitative']) qual_diffs.extend(evol_results['qualitative']) struct_diffs.extend(evol_results['structural']) @@ -369,9 +390,7 @@ def main(): cand_warn = read_table_safe(cand_store, '/warnings') warn_diffs.extend(compare_warnings_tables(base_warn, cand_warn)) - # ── Errors table ────────────────────────────────────────── - base_err = read_table_safe(base_store, '/errors') - cand_err = read_table_safe(cand_store, '/errors') + # ── Errors table (comparison) ────────────────────────────────────────── error_diffs = compare_errors_tables(base_err, cand_err) struct_diffs.extend(error_diffs) From 64be558bb799234e53dd021d9fcccd8a85e697ec Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Thu, 19 Mar 2026 14:49:45 +0000 Subject: [PATCH 90/91] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- dev-tools/binaries_suite.py | 2 +- dev-tools/compare_runs.py | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/dev-tools/binaries_suite.py b/dev-tools/binaries_suite.py index a4a2c5bf44..bb6add8f5e 100644 --- a/dev-tools/binaries_suite.py +++ b/dev-tools/binaries_suite.py @@ -19,9 +19,9 @@ from posydon.binary_evol.binarystar import BinaryStar, SingleStar from posydon.binary_evol.simulationproperties import SimulationProperties +from posydon.config import PATH_TO_POSYDON_DATA from posydon.popsyn.io import simprop_kwargs_from_ini from posydon.utils.common_functions import orbital_separation_from_period -from posydon.config import PATH_TO_POSYDON_DATA AVAILABLE_METALLICITIES = [2., 1., 0.45, 0.2, 0.1, 0.01, 0.001, 0.0001] diff --git a/dev-tools/compare_runs.py b/dev-tools/compare_runs.py index d5f4643062..6470288198 100644 --- a/dev-tools/compare_runs.py +++ b/dev-tools/compare_runs.py @@ -52,13 +52,13 @@ def classify_column(col, dtype): def compare_evolution_tables(base_df, cand_df, rtol, atol, base_error_ids=None, cand_error_ids=None): """Compare two evolution DataFrames, reporting per-binary diffs. - + Args: base_error_ids: set of binary IDs that errored in the baseline run. cand_error_ids: set of binary IDs that errored in the candidate run. Binaries present in these sets are excluded from MISSING/EXTRA reporting here, since they are already covered by compare_errors_tables. - + Returns: dict with keys 'quantitative', 'qualitative', 'structural' each mapping to a list of diff strings. @@ -356,7 +356,7 @@ def main(): # ── Errors table (read early so IDs are available for evolution comparison) base_err = read_table_safe(base_store, '/errors') cand_err = read_table_safe(cand_store, '/errors') - + base_error_ids = set(base_err['binary_id'].unique()) \ if base_err is not None and 'binary_id' in base_err.columns else set() cand_error_ids = set(cand_err['binary_id'].unique()) \ From d0555a404b6e3c14e447ea5357c0d02ce041f0d4 Mon Sep 17 00:00:00 2001 From: Elizabeth Teng Date: Thu, 19 Mar 2026 10:10:30 -0500 Subject: [PATCH 91/91] added more descriptive errors to evolve_binaries --- dev-tools/evolve_binaries.sh | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/dev-tools/evolve_binaries.sh b/dev-tools/evolve_binaries.sh index e6b6a90c7e..f46efd096a 100755 --- a/dev-tools/evolve_binaries.sh +++ b/dev-tools/evolve_binaries.sh @@ -120,21 +120,26 @@ for Z in $METALLICITIES; do echo " Log: $LOG_FILE" echo "============================================================" - if python "$SUITE_SCRIPT" \ + python "$SUITE_SCRIPT" \ --metallicity "$Z" \ --output "$OUTPUT_FILE" \ - 2>&1 | tee "$LOG_FILE"; then - - if [ ! -f "$OUTPUT_FILE" ]; then - echo "WARNING: Output file not created for Z=${Z}" >&2 - FAILED=$((FAILED + 1)) - else - echo " Z=${Z} Zsun complete." - fi - else - echo "WARNING: Suite failed for Z=${Z}. Check $LOG_FILE" >&2 + 2>&1 | tee "$LOG_FILE" + EXIT_CODE=${PIPESTATUS[0]} + + if [ $EXIT_CODE -eq 137 ]; then + echo "ERROR: Process killed (likely OOM) for Z=${Z}. Exit code 137 (SIGKILL)." >&2 + echo " Consider increasing job memory." >&2 + FAILED=$((FAILED + 1)) + elif [ $EXIT_CODE -ne 0 ]; then + echo "WARNING: Suite failed for Z=${Z} (exit code $EXIT_CODE). Check $LOG_FILE" >&2 FAILED=$((FAILED + 1)) + elif [ ! -f "$OUTPUT_FILE" ]; then + echo "WARNING: Output file not created for Z=${Z}" >&2 + FAILED=$((FAILED + 1)) + else + echo " Z=${Z} Zsun complete." fi + done # ── Deactivate Environment ────────────────────────────────────────────────