From 305e624962e72d9f533539af4c9df9aea1edeb4a Mon Sep 17 00:00:00 2001 From: Steven Rieder Date: Fri, 1 Nov 2024 14:00:37 +0100 Subject: [PATCH 01/30] Move files --- TPS.py => src/tres/TPS.py | 0 TRES.py => src/tres/TRES.py | 0 TRES_options.py => src/tres/TRES_options.py | 0 TRES_plotting.py => src/tres/TRES_plotting.py | 0 TRES_setup.py => src/tres/TRES_setup.py | 0 __init__.py => src/tres/__init__.py | 0 interactions.py => src/tres/interactions.py | 0 rdc_TRES.py => src/tres/rdc_TRES.py | 0 rdc_TRES_csv.py => src/tres/rdc_TRES_csv.py | 0 {seculartriple_TPS => src/tres/seculartriple_TPS}/Makefile | 0 {seculartriple_TPS => src/tres/seculartriple_TPS}/Makefile_old | 0 {seculartriple_TPS => src/tres/seculartriple_TPS}/__init__.py | 0 {seculartriple_TPS => src/tres/seculartriple_TPS}/interface.py | 0 .../tres/seculartriple_TPS}/src/ODE_system.c | 0 .../tres/seculartriple_TPS}/src/ODE_system.h | 0 .../tres/seculartriple_TPS}/src/cvode/cvode.c | 0 .../tres/seculartriple_TPS}/src/cvode/cvode.h | 0 .../tres/seculartriple_TPS}/src/cvode/cvode_band.c | 0 .../tres/seculartriple_TPS}/src/cvode/cvode_band.h | 0 .../tres/seculartriple_TPS}/src/cvode/cvode_bandpre.h | 0 .../tres/seculartriple_TPS}/src/cvode/cvode_dense.c | 0 .../tres/seculartriple_TPS}/src/cvode/cvode_dense.h | 0 .../tres/seculartriple_TPS}/src/cvode/cvode_diag.c | 0 .../tres/seculartriple_TPS}/src/cvode/cvode_diag.h | 0 .../tres/seculartriple_TPS}/src/cvode/cvode_diag_impl.h | 0 .../tres/seculartriple_TPS}/src/cvode/cvode_direct.c | 0 .../tres/seculartriple_TPS}/src/cvode/cvode_direct.h | 0 .../tres/seculartriple_TPS}/src/cvode/cvode_direct_impl.h | 0 .../tres/seculartriple_TPS}/src/cvode/cvode_impl.h | 0 .../tres/seculartriple_TPS}/src/cvode/cvode_io.c | 0 .../tres/seculartriple_TPS}/src/cvode/cvode_spbcgs.c | 0 .../tres/seculartriple_TPS}/src/cvode/cvode_spbcgs.h | 0 .../tres/seculartriple_TPS}/src/cvode/cvode_spgmr.c | 0 .../tres/seculartriple_TPS}/src/cvode/cvode_spgmr.h | 0 .../tres/seculartriple_TPS}/src/cvode/cvode_spils.c | 0 .../tres/seculartriple_TPS}/src/cvode/cvode_spils.h | 0 .../tres/seculartriple_TPS}/src/cvode/cvode_spils_impl.h | 0 .../tres/seculartriple_TPS}/src/cvode/cvode_sptfqmr.c | 0 .../tres/seculartriple_TPS}/src/cvode/cvode_sptfqmr.h | 0 .../tres/seculartriple_TPS}/src/cvode/nvector_serial.c | 0 .../tres/seculartriple_TPS}/src/cvode/nvector_serial.h | 0 .../tres/seculartriple_TPS}/src/cvode/sundials_band.c | 0 .../tres/seculartriple_TPS}/src/cvode/sundials_band.h | 0 .../tres/seculartriple_TPS}/src/cvode/sundials_config.h | 0 .../tres/seculartriple_TPS}/src/cvode/sundials_dense.c | 0 .../tres/seculartriple_TPS}/src/cvode/sundials_dense.h | 0 .../tres/seculartriple_TPS}/src/cvode/sundials_direct.c | 0 .../tres/seculartriple_TPS}/src/cvode/sundials_direct.h | 0 .../tres/seculartriple_TPS}/src/cvode/sundials_iterative.c | 0 .../tres/seculartriple_TPS}/src/cvode/sundials_iterative.h | 0 .../tres/seculartriple_TPS}/src/cvode/sundials_math.c | 0 .../tres/seculartriple_TPS}/src/cvode/sundials_math.h | 0 .../tres/seculartriple_TPS}/src/cvode/sundials_nvector.c | 0 .../tres/seculartriple_TPS}/src/cvode/sundials_nvector.h | 0 .../tres/seculartriple_TPS}/src/cvode/sundials_spbcgs.c | 0 .../tres/seculartriple_TPS}/src/cvode/sundials_spbcgs.h | 0 .../tres/seculartriple_TPS}/src/cvode/sundials_spgmr.c | 0 .../tres/seculartriple_TPS}/src/cvode/sundials_spgmr.h | 0 .../tres/seculartriple_TPS}/src/cvode/sundials_sptfqmr.c | 0 .../tres/seculartriple_TPS}/src/cvode/sundials_sptfqmr.h | 0 .../tres/seculartriple_TPS}/src/cvode/sundials_types.h | 0 .../tres/seculartriple_TPS}/src/helper_routines.c | 0 .../tres/seculartriple_TPS}/src/helper_routines.h | 0 {seculartriple_TPS => src/tres/seculartriple_TPS}/src/main_code.c | 0 {seculartriple_TPS => src/tres/seculartriple_TPS}/src/main_code.h | 0 .../tres/seculartriple_TPS}/src/tidal_friction_parameters.c | 0 .../tres/seculartriple_TPS}/src/tidal_friction_parameters.h | 0 .../tres/seculartriple_TPS}/tidal_friction_constant.py | 0 tidal_friction_constant.py => src/tres/tidal_friction_constant.py | 0 triple_class.py => src/tres/triple_class.py | 0 70 files changed, 0 insertions(+), 0 deletions(-) rename TPS.py => src/tres/TPS.py (100%) rename TRES.py => src/tres/TRES.py (100%) rename TRES_options.py => src/tres/TRES_options.py (100%) rename TRES_plotting.py => src/tres/TRES_plotting.py (100%) rename TRES_setup.py => src/tres/TRES_setup.py (100%) rename __init__.py => src/tres/__init__.py (100%) rename interactions.py => src/tres/interactions.py (100%) rename rdc_TRES.py => src/tres/rdc_TRES.py (100%) rename rdc_TRES_csv.py => src/tres/rdc_TRES_csv.py (100%) rename {seculartriple_TPS => src/tres/seculartriple_TPS}/Makefile (100%) rename {seculartriple_TPS => src/tres/seculartriple_TPS}/Makefile_old (100%) rename {seculartriple_TPS => src/tres/seculartriple_TPS}/__init__.py (100%) rename {seculartriple_TPS => src/tres/seculartriple_TPS}/interface.py (100%) rename {seculartriple_TPS => src/tres/seculartriple_TPS}/src/ODE_system.c (100%) rename {seculartriple_TPS => src/tres/seculartriple_TPS}/src/ODE_system.h (100%) rename {seculartriple_TPS => src/tres/seculartriple_TPS}/src/cvode/cvode.c (100%) rename {seculartriple_TPS => src/tres/seculartriple_TPS}/src/cvode/cvode.h (100%) rename {seculartriple_TPS => src/tres/seculartriple_TPS}/src/cvode/cvode_band.c (100%) rename {seculartriple_TPS => src/tres/seculartriple_TPS}/src/cvode/cvode_band.h (100%) rename {seculartriple_TPS => src/tres/seculartriple_TPS}/src/cvode/cvode_bandpre.h (100%) rename {seculartriple_TPS => src/tres/seculartriple_TPS}/src/cvode/cvode_dense.c (100%) rename {seculartriple_TPS => src/tres/seculartriple_TPS}/src/cvode/cvode_dense.h (100%) rename {seculartriple_TPS => src/tres/seculartriple_TPS}/src/cvode/cvode_diag.c (100%) rename {seculartriple_TPS => src/tres/seculartriple_TPS}/src/cvode/cvode_diag.h (100%) rename {seculartriple_TPS => src/tres/seculartriple_TPS}/src/cvode/cvode_diag_impl.h (100%) rename {seculartriple_TPS => src/tres/seculartriple_TPS}/src/cvode/cvode_direct.c (100%) rename {seculartriple_TPS => src/tres/seculartriple_TPS}/src/cvode/cvode_direct.h (100%) rename {seculartriple_TPS => src/tres/seculartriple_TPS}/src/cvode/cvode_direct_impl.h (100%) rename {seculartriple_TPS => src/tres/seculartriple_TPS}/src/cvode/cvode_impl.h (100%) rename {seculartriple_TPS => src/tres/seculartriple_TPS}/src/cvode/cvode_io.c (100%) rename {seculartriple_TPS => src/tres/seculartriple_TPS}/src/cvode/cvode_spbcgs.c (100%) rename {seculartriple_TPS => src/tres/seculartriple_TPS}/src/cvode/cvode_spbcgs.h (100%) rename {seculartriple_TPS => src/tres/seculartriple_TPS}/src/cvode/cvode_spgmr.c (100%) rename {seculartriple_TPS => src/tres/seculartriple_TPS}/src/cvode/cvode_spgmr.h (100%) rename {seculartriple_TPS => src/tres/seculartriple_TPS}/src/cvode/cvode_spils.c (100%) rename {seculartriple_TPS => src/tres/seculartriple_TPS}/src/cvode/cvode_spils.h (100%) rename {seculartriple_TPS => src/tres/seculartriple_TPS}/src/cvode/cvode_spils_impl.h (100%) rename {seculartriple_TPS => src/tres/seculartriple_TPS}/src/cvode/cvode_sptfqmr.c (100%) rename {seculartriple_TPS => src/tres/seculartriple_TPS}/src/cvode/cvode_sptfqmr.h (100%) rename {seculartriple_TPS => src/tres/seculartriple_TPS}/src/cvode/nvector_serial.c (100%) rename {seculartriple_TPS => src/tres/seculartriple_TPS}/src/cvode/nvector_serial.h (100%) rename {seculartriple_TPS => src/tres/seculartriple_TPS}/src/cvode/sundials_band.c (100%) rename {seculartriple_TPS => src/tres/seculartriple_TPS}/src/cvode/sundials_band.h (100%) rename {seculartriple_TPS => src/tres/seculartriple_TPS}/src/cvode/sundials_config.h (100%) rename {seculartriple_TPS => src/tres/seculartriple_TPS}/src/cvode/sundials_dense.c (100%) rename {seculartriple_TPS => src/tres/seculartriple_TPS}/src/cvode/sundials_dense.h (100%) rename {seculartriple_TPS => src/tres/seculartriple_TPS}/src/cvode/sundials_direct.c (100%) rename {seculartriple_TPS => src/tres/seculartriple_TPS}/src/cvode/sundials_direct.h (100%) rename {seculartriple_TPS => src/tres/seculartriple_TPS}/src/cvode/sundials_iterative.c (100%) rename {seculartriple_TPS => src/tres/seculartriple_TPS}/src/cvode/sundials_iterative.h (100%) rename {seculartriple_TPS => src/tres/seculartriple_TPS}/src/cvode/sundials_math.c (100%) rename {seculartriple_TPS => src/tres/seculartriple_TPS}/src/cvode/sundials_math.h (100%) rename {seculartriple_TPS => src/tres/seculartriple_TPS}/src/cvode/sundials_nvector.c (100%) rename {seculartriple_TPS => src/tres/seculartriple_TPS}/src/cvode/sundials_nvector.h (100%) rename {seculartriple_TPS => src/tres/seculartriple_TPS}/src/cvode/sundials_spbcgs.c (100%) rename {seculartriple_TPS => src/tres/seculartriple_TPS}/src/cvode/sundials_spbcgs.h (100%) rename {seculartriple_TPS => src/tres/seculartriple_TPS}/src/cvode/sundials_spgmr.c (100%) rename {seculartriple_TPS => src/tres/seculartriple_TPS}/src/cvode/sundials_spgmr.h (100%) rename {seculartriple_TPS => src/tres/seculartriple_TPS}/src/cvode/sundials_sptfqmr.c (100%) rename {seculartriple_TPS => src/tres/seculartriple_TPS}/src/cvode/sundials_sptfqmr.h (100%) rename {seculartriple_TPS => src/tres/seculartriple_TPS}/src/cvode/sundials_types.h (100%) rename {seculartriple_TPS => src/tres/seculartriple_TPS}/src/helper_routines.c (100%) rename {seculartriple_TPS => src/tres/seculartriple_TPS}/src/helper_routines.h (100%) rename {seculartriple_TPS => src/tres/seculartriple_TPS}/src/main_code.c (100%) rename {seculartriple_TPS => src/tres/seculartriple_TPS}/src/main_code.h (100%) rename {seculartriple_TPS => src/tres/seculartriple_TPS}/src/tidal_friction_parameters.c (100%) rename {seculartriple_TPS => src/tres/seculartriple_TPS}/src/tidal_friction_parameters.h (100%) rename {seculartriple_TPS => src/tres/seculartriple_TPS}/tidal_friction_constant.py (100%) rename tidal_friction_constant.py => src/tres/tidal_friction_constant.py (100%) rename triple_class.py => src/tres/triple_class.py (100%) diff --git a/TPS.py b/src/tres/TPS.py similarity index 100% rename from TPS.py rename to src/tres/TPS.py diff --git a/TRES.py b/src/tres/TRES.py similarity index 100% rename from TRES.py rename to src/tres/TRES.py diff --git a/TRES_options.py b/src/tres/TRES_options.py similarity index 100% rename from TRES_options.py rename to src/tres/TRES_options.py diff --git a/TRES_plotting.py b/src/tres/TRES_plotting.py similarity index 100% rename from TRES_plotting.py rename to src/tres/TRES_plotting.py diff --git a/TRES_setup.py b/src/tres/TRES_setup.py similarity index 100% rename from TRES_setup.py rename to src/tres/TRES_setup.py diff --git a/__init__.py b/src/tres/__init__.py similarity index 100% rename from __init__.py rename to src/tres/__init__.py diff --git a/interactions.py b/src/tres/interactions.py similarity index 100% rename from interactions.py rename to src/tres/interactions.py diff --git a/rdc_TRES.py b/src/tres/rdc_TRES.py similarity index 100% rename from rdc_TRES.py rename to src/tres/rdc_TRES.py diff --git a/rdc_TRES_csv.py b/src/tres/rdc_TRES_csv.py similarity index 100% rename from rdc_TRES_csv.py rename to src/tres/rdc_TRES_csv.py diff --git a/seculartriple_TPS/Makefile b/src/tres/seculartriple_TPS/Makefile similarity index 100% rename from seculartriple_TPS/Makefile rename to src/tres/seculartriple_TPS/Makefile diff --git a/seculartriple_TPS/Makefile_old b/src/tres/seculartriple_TPS/Makefile_old similarity index 100% rename from seculartriple_TPS/Makefile_old rename to src/tres/seculartriple_TPS/Makefile_old diff --git a/seculartriple_TPS/__init__.py b/src/tres/seculartriple_TPS/__init__.py similarity index 100% rename from seculartriple_TPS/__init__.py rename to src/tres/seculartriple_TPS/__init__.py diff --git a/seculartriple_TPS/interface.py b/src/tres/seculartriple_TPS/interface.py similarity index 100% rename from seculartriple_TPS/interface.py rename to src/tres/seculartriple_TPS/interface.py diff --git a/seculartriple_TPS/src/ODE_system.c b/src/tres/seculartriple_TPS/src/ODE_system.c similarity index 100% rename from seculartriple_TPS/src/ODE_system.c rename to src/tres/seculartriple_TPS/src/ODE_system.c diff --git a/seculartriple_TPS/src/ODE_system.h b/src/tres/seculartriple_TPS/src/ODE_system.h similarity index 100% rename from seculartriple_TPS/src/ODE_system.h rename to src/tres/seculartriple_TPS/src/ODE_system.h diff --git a/seculartriple_TPS/src/cvode/cvode.c b/src/tres/seculartriple_TPS/src/cvode/cvode.c similarity index 100% rename from seculartriple_TPS/src/cvode/cvode.c rename to src/tres/seculartriple_TPS/src/cvode/cvode.c diff --git a/seculartriple_TPS/src/cvode/cvode.h b/src/tres/seculartriple_TPS/src/cvode/cvode.h similarity index 100% rename from seculartriple_TPS/src/cvode/cvode.h rename to src/tres/seculartriple_TPS/src/cvode/cvode.h diff --git a/seculartriple_TPS/src/cvode/cvode_band.c b/src/tres/seculartriple_TPS/src/cvode/cvode_band.c similarity index 100% rename from seculartriple_TPS/src/cvode/cvode_band.c rename to src/tres/seculartriple_TPS/src/cvode/cvode_band.c diff --git a/seculartriple_TPS/src/cvode/cvode_band.h b/src/tres/seculartriple_TPS/src/cvode/cvode_band.h similarity index 100% rename from seculartriple_TPS/src/cvode/cvode_band.h rename to src/tres/seculartriple_TPS/src/cvode/cvode_band.h diff --git a/seculartriple_TPS/src/cvode/cvode_bandpre.h b/src/tres/seculartriple_TPS/src/cvode/cvode_bandpre.h similarity index 100% rename from seculartriple_TPS/src/cvode/cvode_bandpre.h rename to src/tres/seculartriple_TPS/src/cvode/cvode_bandpre.h diff --git a/seculartriple_TPS/src/cvode/cvode_dense.c b/src/tres/seculartriple_TPS/src/cvode/cvode_dense.c similarity index 100% rename from seculartriple_TPS/src/cvode/cvode_dense.c rename to src/tres/seculartriple_TPS/src/cvode/cvode_dense.c diff --git a/seculartriple_TPS/src/cvode/cvode_dense.h b/src/tres/seculartriple_TPS/src/cvode/cvode_dense.h similarity index 100% rename from seculartriple_TPS/src/cvode/cvode_dense.h rename to src/tres/seculartriple_TPS/src/cvode/cvode_dense.h diff --git a/seculartriple_TPS/src/cvode/cvode_diag.c b/src/tres/seculartriple_TPS/src/cvode/cvode_diag.c similarity index 100% rename from seculartriple_TPS/src/cvode/cvode_diag.c rename to src/tres/seculartriple_TPS/src/cvode/cvode_diag.c diff --git a/seculartriple_TPS/src/cvode/cvode_diag.h b/src/tres/seculartriple_TPS/src/cvode/cvode_diag.h similarity index 100% rename from seculartriple_TPS/src/cvode/cvode_diag.h rename to src/tres/seculartriple_TPS/src/cvode/cvode_diag.h diff --git a/seculartriple_TPS/src/cvode/cvode_diag_impl.h b/src/tres/seculartriple_TPS/src/cvode/cvode_diag_impl.h similarity index 100% rename from seculartriple_TPS/src/cvode/cvode_diag_impl.h rename to src/tres/seculartriple_TPS/src/cvode/cvode_diag_impl.h diff --git a/seculartriple_TPS/src/cvode/cvode_direct.c b/src/tres/seculartriple_TPS/src/cvode/cvode_direct.c similarity index 100% rename from seculartriple_TPS/src/cvode/cvode_direct.c rename to src/tres/seculartriple_TPS/src/cvode/cvode_direct.c diff --git a/seculartriple_TPS/src/cvode/cvode_direct.h b/src/tres/seculartriple_TPS/src/cvode/cvode_direct.h similarity index 100% rename from seculartriple_TPS/src/cvode/cvode_direct.h rename to src/tres/seculartriple_TPS/src/cvode/cvode_direct.h diff --git a/seculartriple_TPS/src/cvode/cvode_direct_impl.h b/src/tres/seculartriple_TPS/src/cvode/cvode_direct_impl.h similarity index 100% rename from seculartriple_TPS/src/cvode/cvode_direct_impl.h rename to src/tres/seculartriple_TPS/src/cvode/cvode_direct_impl.h diff --git a/seculartriple_TPS/src/cvode/cvode_impl.h b/src/tres/seculartriple_TPS/src/cvode/cvode_impl.h similarity index 100% rename from seculartriple_TPS/src/cvode/cvode_impl.h rename to src/tres/seculartriple_TPS/src/cvode/cvode_impl.h diff --git a/seculartriple_TPS/src/cvode/cvode_io.c b/src/tres/seculartriple_TPS/src/cvode/cvode_io.c similarity index 100% rename from seculartriple_TPS/src/cvode/cvode_io.c rename to src/tres/seculartriple_TPS/src/cvode/cvode_io.c diff --git a/seculartriple_TPS/src/cvode/cvode_spbcgs.c b/src/tres/seculartriple_TPS/src/cvode/cvode_spbcgs.c similarity index 100% rename from seculartriple_TPS/src/cvode/cvode_spbcgs.c rename to src/tres/seculartriple_TPS/src/cvode/cvode_spbcgs.c diff --git a/seculartriple_TPS/src/cvode/cvode_spbcgs.h b/src/tres/seculartriple_TPS/src/cvode/cvode_spbcgs.h similarity index 100% rename from seculartriple_TPS/src/cvode/cvode_spbcgs.h rename to src/tres/seculartriple_TPS/src/cvode/cvode_spbcgs.h diff --git a/seculartriple_TPS/src/cvode/cvode_spgmr.c b/src/tres/seculartriple_TPS/src/cvode/cvode_spgmr.c similarity index 100% rename from seculartriple_TPS/src/cvode/cvode_spgmr.c rename to src/tres/seculartriple_TPS/src/cvode/cvode_spgmr.c diff --git a/seculartriple_TPS/src/cvode/cvode_spgmr.h b/src/tres/seculartriple_TPS/src/cvode/cvode_spgmr.h similarity index 100% rename from seculartriple_TPS/src/cvode/cvode_spgmr.h rename to src/tres/seculartriple_TPS/src/cvode/cvode_spgmr.h diff --git a/seculartriple_TPS/src/cvode/cvode_spils.c b/src/tres/seculartriple_TPS/src/cvode/cvode_spils.c similarity index 100% rename from seculartriple_TPS/src/cvode/cvode_spils.c rename to src/tres/seculartriple_TPS/src/cvode/cvode_spils.c diff --git a/seculartriple_TPS/src/cvode/cvode_spils.h b/src/tres/seculartriple_TPS/src/cvode/cvode_spils.h similarity index 100% rename from seculartriple_TPS/src/cvode/cvode_spils.h rename to src/tres/seculartriple_TPS/src/cvode/cvode_spils.h diff --git a/seculartriple_TPS/src/cvode/cvode_spils_impl.h b/src/tres/seculartriple_TPS/src/cvode/cvode_spils_impl.h similarity index 100% rename from seculartriple_TPS/src/cvode/cvode_spils_impl.h rename to src/tres/seculartriple_TPS/src/cvode/cvode_spils_impl.h diff --git a/seculartriple_TPS/src/cvode/cvode_sptfqmr.c b/src/tres/seculartriple_TPS/src/cvode/cvode_sptfqmr.c similarity index 100% rename from seculartriple_TPS/src/cvode/cvode_sptfqmr.c rename to src/tres/seculartriple_TPS/src/cvode/cvode_sptfqmr.c diff --git a/seculartriple_TPS/src/cvode/cvode_sptfqmr.h b/src/tres/seculartriple_TPS/src/cvode/cvode_sptfqmr.h similarity index 100% rename from seculartriple_TPS/src/cvode/cvode_sptfqmr.h rename to src/tres/seculartriple_TPS/src/cvode/cvode_sptfqmr.h diff --git a/seculartriple_TPS/src/cvode/nvector_serial.c b/src/tres/seculartriple_TPS/src/cvode/nvector_serial.c similarity index 100% rename from seculartriple_TPS/src/cvode/nvector_serial.c rename to src/tres/seculartriple_TPS/src/cvode/nvector_serial.c diff --git a/seculartriple_TPS/src/cvode/nvector_serial.h b/src/tres/seculartriple_TPS/src/cvode/nvector_serial.h similarity index 100% rename from seculartriple_TPS/src/cvode/nvector_serial.h rename to src/tres/seculartriple_TPS/src/cvode/nvector_serial.h diff --git a/seculartriple_TPS/src/cvode/sundials_band.c b/src/tres/seculartriple_TPS/src/cvode/sundials_band.c similarity index 100% rename from seculartriple_TPS/src/cvode/sundials_band.c rename to src/tres/seculartriple_TPS/src/cvode/sundials_band.c diff --git a/seculartriple_TPS/src/cvode/sundials_band.h b/src/tres/seculartriple_TPS/src/cvode/sundials_band.h similarity index 100% rename from seculartriple_TPS/src/cvode/sundials_band.h rename to src/tres/seculartriple_TPS/src/cvode/sundials_band.h diff --git a/seculartriple_TPS/src/cvode/sundials_config.h b/src/tres/seculartriple_TPS/src/cvode/sundials_config.h similarity index 100% rename from seculartriple_TPS/src/cvode/sundials_config.h rename to src/tres/seculartriple_TPS/src/cvode/sundials_config.h diff --git a/seculartriple_TPS/src/cvode/sundials_dense.c b/src/tres/seculartriple_TPS/src/cvode/sundials_dense.c similarity index 100% rename from seculartriple_TPS/src/cvode/sundials_dense.c rename to src/tres/seculartriple_TPS/src/cvode/sundials_dense.c diff --git a/seculartriple_TPS/src/cvode/sundials_dense.h b/src/tres/seculartriple_TPS/src/cvode/sundials_dense.h similarity index 100% rename from seculartriple_TPS/src/cvode/sundials_dense.h rename to src/tres/seculartriple_TPS/src/cvode/sundials_dense.h diff --git a/seculartriple_TPS/src/cvode/sundials_direct.c b/src/tres/seculartriple_TPS/src/cvode/sundials_direct.c similarity index 100% rename from seculartriple_TPS/src/cvode/sundials_direct.c rename to src/tres/seculartriple_TPS/src/cvode/sundials_direct.c diff --git a/seculartriple_TPS/src/cvode/sundials_direct.h b/src/tres/seculartriple_TPS/src/cvode/sundials_direct.h similarity index 100% rename from seculartriple_TPS/src/cvode/sundials_direct.h rename to src/tres/seculartriple_TPS/src/cvode/sundials_direct.h diff --git a/seculartriple_TPS/src/cvode/sundials_iterative.c b/src/tres/seculartriple_TPS/src/cvode/sundials_iterative.c similarity index 100% rename from seculartriple_TPS/src/cvode/sundials_iterative.c rename to src/tres/seculartriple_TPS/src/cvode/sundials_iterative.c diff --git a/seculartriple_TPS/src/cvode/sundials_iterative.h b/src/tres/seculartriple_TPS/src/cvode/sundials_iterative.h similarity index 100% rename from seculartriple_TPS/src/cvode/sundials_iterative.h rename to src/tres/seculartriple_TPS/src/cvode/sundials_iterative.h diff --git a/seculartriple_TPS/src/cvode/sundials_math.c b/src/tres/seculartriple_TPS/src/cvode/sundials_math.c similarity index 100% rename from seculartriple_TPS/src/cvode/sundials_math.c rename to src/tres/seculartriple_TPS/src/cvode/sundials_math.c diff --git a/seculartriple_TPS/src/cvode/sundials_math.h b/src/tres/seculartriple_TPS/src/cvode/sundials_math.h similarity index 100% rename from seculartriple_TPS/src/cvode/sundials_math.h rename to src/tres/seculartriple_TPS/src/cvode/sundials_math.h diff --git a/seculartriple_TPS/src/cvode/sundials_nvector.c b/src/tres/seculartriple_TPS/src/cvode/sundials_nvector.c similarity index 100% rename from seculartriple_TPS/src/cvode/sundials_nvector.c rename to src/tres/seculartriple_TPS/src/cvode/sundials_nvector.c diff --git a/seculartriple_TPS/src/cvode/sundials_nvector.h b/src/tres/seculartriple_TPS/src/cvode/sundials_nvector.h similarity index 100% rename from seculartriple_TPS/src/cvode/sundials_nvector.h rename to src/tres/seculartriple_TPS/src/cvode/sundials_nvector.h diff --git a/seculartriple_TPS/src/cvode/sundials_spbcgs.c b/src/tres/seculartriple_TPS/src/cvode/sundials_spbcgs.c similarity index 100% rename from seculartriple_TPS/src/cvode/sundials_spbcgs.c rename to src/tres/seculartriple_TPS/src/cvode/sundials_spbcgs.c diff --git a/seculartriple_TPS/src/cvode/sundials_spbcgs.h b/src/tres/seculartriple_TPS/src/cvode/sundials_spbcgs.h similarity index 100% rename from seculartriple_TPS/src/cvode/sundials_spbcgs.h rename to src/tres/seculartriple_TPS/src/cvode/sundials_spbcgs.h diff --git a/seculartriple_TPS/src/cvode/sundials_spgmr.c b/src/tres/seculartriple_TPS/src/cvode/sundials_spgmr.c similarity index 100% rename from seculartriple_TPS/src/cvode/sundials_spgmr.c rename to src/tres/seculartriple_TPS/src/cvode/sundials_spgmr.c diff --git a/seculartriple_TPS/src/cvode/sundials_spgmr.h b/src/tres/seculartriple_TPS/src/cvode/sundials_spgmr.h similarity index 100% rename from seculartriple_TPS/src/cvode/sundials_spgmr.h rename to src/tres/seculartriple_TPS/src/cvode/sundials_spgmr.h diff --git a/seculartriple_TPS/src/cvode/sundials_sptfqmr.c b/src/tres/seculartriple_TPS/src/cvode/sundials_sptfqmr.c similarity index 100% rename from seculartriple_TPS/src/cvode/sundials_sptfqmr.c rename to src/tres/seculartriple_TPS/src/cvode/sundials_sptfqmr.c diff --git a/seculartriple_TPS/src/cvode/sundials_sptfqmr.h b/src/tres/seculartriple_TPS/src/cvode/sundials_sptfqmr.h similarity index 100% rename from seculartriple_TPS/src/cvode/sundials_sptfqmr.h rename to src/tres/seculartriple_TPS/src/cvode/sundials_sptfqmr.h diff --git a/seculartriple_TPS/src/cvode/sundials_types.h b/src/tres/seculartriple_TPS/src/cvode/sundials_types.h similarity index 100% rename from seculartriple_TPS/src/cvode/sundials_types.h rename to src/tres/seculartriple_TPS/src/cvode/sundials_types.h diff --git a/seculartriple_TPS/src/helper_routines.c b/src/tres/seculartriple_TPS/src/helper_routines.c similarity index 100% rename from seculartriple_TPS/src/helper_routines.c rename to src/tres/seculartriple_TPS/src/helper_routines.c diff --git a/seculartriple_TPS/src/helper_routines.h b/src/tres/seculartriple_TPS/src/helper_routines.h similarity index 100% rename from seculartriple_TPS/src/helper_routines.h rename to src/tres/seculartriple_TPS/src/helper_routines.h diff --git a/seculartriple_TPS/src/main_code.c b/src/tres/seculartriple_TPS/src/main_code.c similarity index 100% rename from seculartriple_TPS/src/main_code.c rename to src/tres/seculartriple_TPS/src/main_code.c diff --git a/seculartriple_TPS/src/main_code.h b/src/tres/seculartriple_TPS/src/main_code.h similarity index 100% rename from seculartriple_TPS/src/main_code.h rename to src/tres/seculartriple_TPS/src/main_code.h diff --git a/seculartriple_TPS/src/tidal_friction_parameters.c b/src/tres/seculartriple_TPS/src/tidal_friction_parameters.c similarity index 100% rename from seculartriple_TPS/src/tidal_friction_parameters.c rename to src/tres/seculartriple_TPS/src/tidal_friction_parameters.c diff --git a/seculartriple_TPS/src/tidal_friction_parameters.h b/src/tres/seculartriple_TPS/src/tidal_friction_parameters.h similarity index 100% rename from seculartriple_TPS/src/tidal_friction_parameters.h rename to src/tres/seculartriple_TPS/src/tidal_friction_parameters.h diff --git a/seculartriple_TPS/tidal_friction_constant.py b/src/tres/seculartriple_TPS/tidal_friction_constant.py similarity index 100% rename from seculartriple_TPS/tidal_friction_constant.py rename to src/tres/seculartriple_TPS/tidal_friction_constant.py diff --git a/tidal_friction_constant.py b/src/tres/tidal_friction_constant.py similarity index 100% rename from tidal_friction_constant.py rename to src/tres/tidal_friction_constant.py diff --git a/triple_class.py b/src/tres/triple_class.py similarity index 100% rename from triple_class.py rename to src/tres/triple_class.py From 30c5a4f00f2580b25481175f6841fd8648c396fa Mon Sep 17 00:00:00 2001 From: Steven Rieder Date: Fri, 1 Nov 2024 14:16:29 +0100 Subject: [PATCH 02/30] fix line endings (win->unix) --- src/tres/TRES.py | 844 +++++++++++++++++++++++------------------------ 1 file changed, 422 insertions(+), 422 deletions(-) diff --git a/src/tres/TRES.py b/src/tres/TRES.py index ded776f..d9dd944 100644 --- a/src/tres/TRES.py +++ b/src/tres/TRES.py @@ -1,441 +1,441 @@ -# to do -# min teken in mean anomaly - -## Triple: Triple evolution -## computes the evolution of a given triple -## given any initial conditions (M, m, l, A, a, E, e, i, G, g, O, o, T, z). - -import sys - -import numpy as np -# from interactions import * -# from tidal_friction_constant import * -from amuse.units import units -from amuse.support.console import set_printing_strategy - -from amuse.community.seba.interface import SeBa -from seculartriple_TPS.interface import SecularTriple - - -from triple_class import Triple_Class -from TRES_plotting import plot_data_container, plot_function -from TRES_setup import make_particle_sets, setup_stellar_code -from TRES_options import REPORT_DEBUG, \ - REPORT_TRIPLE_EVOLUTION, \ - MAKE_PLOTS, \ - REPORT_USER_WARNINGS +# to do +# min teken in mean anomaly + +## Triple: Triple evolution +## computes the evolution of a given triple +## given any initial conditions (M, m, l, A, a, E, e, i, G, g, O, o, T, z). + +import sys + +import numpy as np +# from interactions import * +# from tidal_friction_constant import * +from amuse.units import units +from amuse.support.console import set_printing_strategy + +from amuse.community.seba.interface import SeBa +from seculartriple_TPS.interface import SecularTriple + + +from triple_class import Triple_Class +from TRES_plotting import plot_data_container, plot_function +from TRES_setup import make_particle_sets, setup_stellar_code +from TRES_options import REPORT_DEBUG, \ + REPORT_TRIPLE_EVOLUTION, \ + MAKE_PLOTS, \ + REPORT_USER_WARNINGS from interactions import corotating_spin_angular_frequency_binary, \ lang_spin_angular_frequency, \ break_up_angular_frequency, \ - criticial_angular_frequency_CHE - -def initialize_triple_class(stars, bins, correct_params, - stellar_code, secular_code, relative_inclination = 80.0*np.pi/180.0, - metallicity = 0.02, tend = 5.0 |units.Myr, tinit = 0.0|units.Myr, - number = 0, maximum_radius_change_factor = 0.005, - stop_at_mass_transfer = True, stop_at_init_mass_transfer = True, stop_at_outer_mass_transfer = True, - stop_at_stable_mass_transfer = True, stop_at_eccentric_stable_mass_transfer = True, - stop_at_unstable_mass_transfer = False, stop_at_eccentric_unstable_mass_transfer = False, which_common_envelope = 2, - stop_at_no_CHE = False, include_CHE = False, - stop_at_merger = True, stop_at_disintegrated = True, stop_at_inner_collision = True, stop_at_outer_collision = True, - stop_at_dynamical_instability = True, stop_at_semisecular_regime = False, - stop_at_SN = False, SN_kick_distr = 2, impulse_kick_for_black_holes = True, fallback_kick_for_black_holes = True, - stop_at_CPU_time = False, max_CPU_time = 3600.0, file_name = "TRES.hdf", file_type = "hdf5", dir_plots = ""): - - triple = Triple_Class(stars, bins, correct_params, stellar_code, secular_code, - relative_inclination, tend, tinit, - number, maximum_radius_change_factor, - stop_at_mass_transfer, stop_at_init_mass_transfer, stop_at_outer_mass_transfer, - stop_at_stable_mass_transfer, stop_at_eccentric_stable_mass_transfer, - stop_at_unstable_mass_transfer, stop_at_eccentric_unstable_mass_transfer, which_common_envelope, - stop_at_no_CHE, include_CHE, - stop_at_merger, stop_at_disintegrated, stop_at_inner_collision, stop_at_outer_collision, - stop_at_dynamical_instability, stop_at_semisecular_regime, - stop_at_SN, SN_kick_distr, impulse_kick_for_black_holes, fallback_kick_for_black_holes, - stop_at_CPU_time, max_CPU_time, file_name, file_type, dir_plots) - triple.stellar_code.parameters.metallicity = metallicity - - return triple - - -#----- -#for running TRES.py from other routines -def main(inner_primary_mass = 1.3|units.MSun, inner_secondary_mass = 0.5|units.MSun, outer_mass = 0.5|units.MSun, - inner_semimajor_axis = 1.0 |units.AU, outer_semimajor_axis = 100.0 |units.AU, - inner_eccentricity = 0.1, outer_eccentricity= 0.5, - relative_inclination = 80.0*np.pi/180.0, - inner_argument_of_pericenter = 0.1, outer_argument_of_pericenter = 0.5, - inner_longitude_of_ascending_node = 0.0, - metallicity = 0.02, tend = 5.0 |units.Myr, tinit = 0.0|units.Myr, - number = 0, maximum_radius_change_factor = 0.005, - stop_at_mass_transfer = True, stop_at_init_mass_transfer = True, stop_at_outer_mass_transfer = True, - stop_at_stable_mass_transfer = True, stop_at_eccentric_stable_mass_transfer = True, - stop_at_unstable_mass_transfer = False, stop_at_eccentric_unstable_mass_transfer = False, which_common_envelope = 2, - stop_at_no_CHE = False, include_CHE = False, - stop_at_merger = True, stop_at_disintegrated = True, stop_at_inner_collision = True, stop_at_outer_collision = True, - stop_at_dynamical_instability = True, stop_at_semisecular_regime = False, - stop_at_SN = False, SN_kick_distr = 2, impulse_kick_for_black_holes = True, fallback_kick_for_black_holes = True, + criticial_angular_frequency_CHE + +def initialize_triple_class(stars, bins, correct_params, + stellar_code, secular_code, relative_inclination = 80.0*np.pi/180.0, + metallicity = 0.02, tend = 5.0 |units.Myr, tinit = 0.0|units.Myr, + number = 0, maximum_radius_change_factor = 0.005, + stop_at_mass_transfer = True, stop_at_init_mass_transfer = True, stop_at_outer_mass_transfer = True, + stop_at_stable_mass_transfer = True, stop_at_eccentric_stable_mass_transfer = True, + stop_at_unstable_mass_transfer = False, stop_at_eccentric_unstable_mass_transfer = False, which_common_envelope = 2, + stop_at_no_CHE = False, include_CHE = False, + stop_at_merger = True, stop_at_disintegrated = True, stop_at_inner_collision = True, stop_at_outer_collision = True, + stop_at_dynamical_instability = True, stop_at_semisecular_regime = False, + stop_at_SN = False, SN_kick_distr = 2, impulse_kick_for_black_holes = True, fallback_kick_for_black_holes = True, + stop_at_CPU_time = False, max_CPU_time = 3600.0, file_name = "TRES.hdf", file_type = "hdf5", dir_plots = ""): + + triple = Triple_Class(stars, bins, correct_params, stellar_code, secular_code, + relative_inclination, tend, tinit, + number, maximum_radius_change_factor, + stop_at_mass_transfer, stop_at_init_mass_transfer, stop_at_outer_mass_transfer, + stop_at_stable_mass_transfer, stop_at_eccentric_stable_mass_transfer, + stop_at_unstable_mass_transfer, stop_at_eccentric_unstable_mass_transfer, which_common_envelope, + stop_at_no_CHE, include_CHE, + stop_at_merger, stop_at_disintegrated, stop_at_inner_collision, stop_at_outer_collision, + stop_at_dynamical_instability, stop_at_semisecular_regime, + stop_at_SN, SN_kick_distr, impulse_kick_for_black_holes, fallback_kick_for_black_holes, + stop_at_CPU_time, max_CPU_time, file_name, file_type, dir_plots) + triple.stellar_code.parameters.metallicity = metallicity + + return triple + + +#----- +#for running TRES.py from other routines +def main(inner_primary_mass = 1.3|units.MSun, inner_secondary_mass = 0.5|units.MSun, outer_mass = 0.5|units.MSun, + inner_semimajor_axis = 1.0 |units.AU, outer_semimajor_axis = 100.0 |units.AU, + inner_eccentricity = 0.1, outer_eccentricity= 0.5, + relative_inclination = 80.0*np.pi/180.0, + inner_argument_of_pericenter = 0.1, outer_argument_of_pericenter = 0.5, + inner_longitude_of_ascending_node = 0.0, + metallicity = 0.02, tend = 5.0 |units.Myr, tinit = 0.0|units.Myr, + number = 0, maximum_radius_change_factor = 0.005, + stop_at_mass_transfer = True, stop_at_init_mass_transfer = True, stop_at_outer_mass_transfer = True, + stop_at_stable_mass_transfer = True, stop_at_eccentric_stable_mass_transfer = True, + stop_at_unstable_mass_transfer = False, stop_at_eccentric_unstable_mass_transfer = False, which_common_envelope = 2, + stop_at_no_CHE = False, include_CHE = False, + stop_at_merger = True, stop_at_disintegrated = True, stop_at_inner_collision = True, stop_at_outer_collision = True, + stop_at_dynamical_instability = True, stop_at_semisecular_regime = False, + stop_at_SN = False, SN_kick_distr = 2, impulse_kick_for_black_holes = True, fallback_kick_for_black_holes = True, stop_at_CPU_time = False, max_CPU_time = 3600.0, file_name = "TRES.hdf", file_type = "hdf5", dir_plots = "", - stellar_code=None, secular_code=None): - - set_printing_strategy("custom", - preferred_units = [units.MSun, units.RSun, units.Myr], - precision = 11, prefix = "", - separator = " [", suffix = "]") - - inner_eccentricity = float(inner_eccentricity) - outer_eccentricity = float(outer_eccentricity) - relative_inclination = float(relative_inclination) - inner_argument_of_pericenter = float(inner_argument_of_pericenter) - outer_argument_of_pericenter = float(outer_argument_of_pericenter) - inner_longitude_of_ascending_node = float(inner_longitude_of_ascending_node) - - stars, bins, correct_params = make_particle_sets(inner_primary_mass, inner_secondary_mass, outer_mass, - inner_semimajor_axis, outer_semimajor_axis, - inner_eccentricity, outer_eccentricity, - relative_inclination, - inner_argument_of_pericenter, outer_argument_of_pericenter, - inner_longitude_of_ascending_node) - + stellar_code=None, secular_code=None): + + set_printing_strategy("custom", + preferred_units = [units.MSun, units.RSun, units.Myr], + precision = 11, prefix = "", + separator = " [", suffix = "]") + + inner_eccentricity = float(inner_eccentricity) + outer_eccentricity = float(outer_eccentricity) + relative_inclination = float(relative_inclination) + inner_argument_of_pericenter = float(inner_argument_of_pericenter) + outer_argument_of_pericenter = float(outer_argument_of_pericenter) + inner_longitude_of_ascending_node = float(inner_longitude_of_ascending_node) + + stars, bins, correct_params = make_particle_sets(inner_primary_mass, inner_secondary_mass, outer_mass, + inner_semimajor_axis, outer_semimajor_axis, + inner_eccentricity, outer_eccentricity, + relative_inclination, + inner_argument_of_pericenter, outer_argument_of_pericenter, + inner_longitude_of_ascending_node) + clean_up_stellar_code = False clean_up_secular_code = False if stellar_code is None: - stellar_code = SeBa() - # stellar_code = SeBa(redirection='none') + stellar_code = SeBa() + # stellar_code = SeBa(redirection='none') # stellar_code = SeBa(redirection='file', redirect_file='output_SeBa_TRES.txt') clean_up_stellar_code = True - - stellar_code.parameters.metallicity = metallicity + + stellar_code.parameters.metallicity = metallicity if secular_code is None: - secular_code = SecularTriple() - # secular_code = SecularTriple(redirection='none') - # secular_code = SecularTriple(redirection='file', redirect_file='output_SecularTriple_TRES.txt') + secular_code = SecularTriple() + # secular_code = SecularTriple(redirection='none') + # secular_code = SecularTriple(redirection='file', redirect_file='output_SecularTriple_TRES.txt') clean_up_secular_code = True - - triple_class_object = Triple_Class(stars, bins, correct_params, stellar_code, secular_code, - relative_inclination, tend, tinit, - number, maximum_radius_change_factor, - stop_at_mass_transfer, stop_at_init_mass_transfer, stop_at_outer_mass_transfer, - stop_at_stable_mass_transfer, stop_at_eccentric_stable_mass_transfer, - stop_at_unstable_mass_transfer, stop_at_eccentric_unstable_mass_transfer, which_common_envelope, - stop_at_no_CHE, include_CHE, - stop_at_merger, stop_at_disintegrated, stop_at_inner_collision, stop_at_outer_collision, - stop_at_dynamical_instability, stop_at_semisecular_regime, - stop_at_SN, SN_kick_distr, impulse_kick_for_black_holes, fallback_kick_for_black_holes, - stop_at_CPU_time, max_CPU_time, file_name, file_type, dir_plots) - - - if triple_class_object.correct_params == False: - if REPORT_USER_WARNINGS: - print('Choose a different system. The parameters of the given triple are incorrect.') - return triple_class_object # no codes initialized yet - elif stop_at_semisecular_regime == True and triple_class_object.semisecular_regime_at_initialisation == True: - if REPORT_USER_WARNINGS: - print('Choose a different system. The given triple is in the semisecular regime at initialization.') - elif triple_class_object.dynamical_instability_at_initialisation == True: - if REPORT_USER_WARNINGS: - print('Choose a different system. The given triple is dynamically unstable at initialization.') - elif triple_class_object.mass_transfer_at_initialisation == True: - if REPORT_USER_WARNINGS: - print('Choose a different system. There is mass transfer in the given triple at initialization.') - elif stop_at_no_CHE == True and triple_class_object.CHE_at_initialisation == False: - if REPORT_USER_WARNINGS: - print('Choose a different system. No chemically homogeneous evolution at initialization') - else: - triple_class_object.evolve_model(tend) - if REPORT_DEBUG or MAKE_PLOTS: - plot_function(triple_class_object, dir_plots) - triple_class_object.print_stellar_system() - + + triple_class_object = Triple_Class(stars, bins, correct_params, stellar_code, secular_code, + relative_inclination, tend, tinit, + number, maximum_radius_change_factor, + stop_at_mass_transfer, stop_at_init_mass_transfer, stop_at_outer_mass_transfer, + stop_at_stable_mass_transfer, stop_at_eccentric_stable_mass_transfer, + stop_at_unstable_mass_transfer, stop_at_eccentric_unstable_mass_transfer, which_common_envelope, + stop_at_no_CHE, include_CHE, + stop_at_merger, stop_at_disintegrated, stop_at_inner_collision, stop_at_outer_collision, + stop_at_dynamical_instability, stop_at_semisecular_regime, + stop_at_SN, SN_kick_distr, impulse_kick_for_black_holes, fallback_kick_for_black_holes, + stop_at_CPU_time, max_CPU_time, file_name, file_type, dir_plots) + + + if triple_class_object.correct_params == False: + if REPORT_USER_WARNINGS: + print('Choose a different system. The parameters of the given triple are incorrect.') + return triple_class_object # no codes initialized yet + elif stop_at_semisecular_regime == True and triple_class_object.semisecular_regime_at_initialisation == True: + if REPORT_USER_WARNINGS: + print('Choose a different system. The given triple is in the semisecular regime at initialization.') + elif triple_class_object.dynamical_instability_at_initialisation == True: + if REPORT_USER_WARNINGS: + print('Choose a different system. The given triple is dynamically unstable at initialization.') + elif triple_class_object.mass_transfer_at_initialisation == True: + if REPORT_USER_WARNINGS: + print('Choose a different system. There is mass transfer in the given triple at initialization.') + elif stop_at_no_CHE == True and triple_class_object.CHE_at_initialisation == False: + if REPORT_USER_WARNINGS: + print('Choose a different system. No chemically homogeneous evolution at initialization') + else: + triple_class_object.evolve_model(tend) + if REPORT_DEBUG or MAKE_PLOTS: + plot_function(triple_class_object, dir_plots) + triple_class_object.print_stellar_system() + stellar_code.particles.remove_particles(stars) - triple_set = triple_class_object.triple.as_set() + triple_set = triple_class_object.triple.as_set() secular_code.triples.remove_particles(triple_set) - del stars, bins, triple_set + del stars, bins, triple_set if clean_up_stellar_code: - triple_class_object.stellar_code.stop() - print('cleaning se') + triple_class_object.stellar_code.stop() + print('cleaning se') if clean_up_secular_code: triple_class_object.secular_code.stop() - print('cleaning sec') + print('cleaning sec') - return triple_class_object - - -def main_developer(stars, bins, correct_params, stellar_code, secular_code, - relative_inclination = 80.0*np.pi/180.0, - metallicity = 0.02, tend = 5.0 |units.Myr, tinit = 0.0 |units.Myr, - number = 0, maximum_radius_change_factor = 0.005, - stop_at_mass_transfer = True, stop_at_init_mass_transfer = True, stop_at_outer_mass_transfer = True, - stop_at_stable_mass_transfer = True, stop_at_eccentric_stable_mass_transfer = True, - stop_at_unstable_mass_transfer = False, stop_at_eccentric_unstable_mass_transfer = False, which_common_envelope = 2, - stop_at_no_CHE = False, include_CHE = False, - stop_at_merger = True, stop_at_disintegrated = True, stop_at_inner_collision = True, stop_at_outer_collision = True, - stop_at_dynamical_instability = True, stop_at_semisecular_regime = False, - stop_at_SN = False, SN_kick_distr = 2, impulse_kick_for_black_holes = True, fallback_kick_for_black_holes = True, - stop_at_CPU_time = False, max_CPU_time = 3600.0, file_name = "TRES.hdf", file_type = "hdf5", dir_plots = ""): - - - set_printing_strategy("custom", - preferred_units = [units.MSun, units.RSun, units.Myr], - precision = 11, prefix = "", - separator = " [", suffix = "]") - - bins.eccentricity[0] = float(bins.eccentricity[0]) - bins.eccentricity[1] = float(bins.eccentricity[1]) - bins.argument_of_pericenter[0] = float(bins.argument_of_pericenter[0]) - bins.argument_of_pericenter[1] = float(bins.argument_of_pericenter[1]) - bins.longitude_of_ascending_node[0] = float(bins.longitude_of_ascending_node[0]) - bins.longitude_of_ascending_node[1] = float(bins.longitude_of_ascending_node[1]) - relative_inclination = float(relative_inclination) - - triple_class_object = Triple_Class(stars, bins, correct_params, stellar_code, secular_code, - relative_inclination, tend, tinit, - number, maximum_radius_change_factor, - stop_at_mass_transfer, stop_at_init_mass_transfer, stop_at_outer_mass_transfer, - stop_at_stable_mass_transfer, stop_at_eccentric_stable_mass_transfer, - stop_at_unstable_mass_transfer, stop_at_eccentric_unstable_mass_transfer, which_common_envelope, - stop_at_no_CHE, include_CHE, - stop_at_merger, stop_at_disintegrated, stop_at_inner_collision, stop_at_outer_collision, - stop_at_dynamical_instability, stop_at_semisecular_regime, - stop_at_SN, SN_kick_distr, impulse_kick_for_black_holes, fallback_kick_for_black_holes, - stop_at_CPU_time, max_CPU_time, file_name, file_type, dir_plots) - - - if triple_class_object.correct_params == False: - if REPORT_USER_WARNINGS: - print('Choose a different system. The parameters of the given triple are incorrect.') - return triple_class_object # no codes initialized yet - elif stop_at_semisecular_regime == True and triple_class_object.semisecular_regime_at_initialisation == True: - if REPORT_USER_WARNINGS: - print('Choose a different system. The given triple is in the semisecular regime at initialization.') - elif triple_class_object.dynamical_instability_at_initialisation == True: - if REPORT_USER_WARNINGS: - print('Choose a different system. The given triple is dynamically unstable at initialization.') - elif triple_class_object.mass_transfer_at_initialisation == True: - if REPORT_USER_WARNINGS: - print('Choose a different system. There is mass transfer in the given triple at initialization.') - elif stop_at_no_CHE == True and triple_class_object.CHE_at_initialisation == False: - if REPORT_USER_WARNINGS: - print('Choose a different system. No chemically homogeneous evolution at initialization') - else: - triple_class_object.evolve_model(tend) - if REPORT_DEBUG or MAKE_PLOTS: - plot_function(triple_class_object, dir_plots) - triple_class_object.print_stellar_system() - - return triple_class_object - - - -#----- - -#----- -#for running triple.py from the commandline -def parse_arguments(): - from amuse.units.optparse import OptionParser - parser = OptionParser() - parser.add_option("-M", "--M1", unit=units.MSun, - dest="inner_primary_mass", type="float", default = 1.3|units.MSun, - help="inner primary mass [%default]") - parser.add_option("-m", "--M2", unit=units.MSun, - dest="inner_secondary_mass", type="float", default = 0.5|units.MSun, - help="inner secondary mass [%default]") - parser.add_option("-l", "--M3", unit=units.MSun, - dest="outer_mass", type="float", default = 0.5|units.MSun, - help="outer mass [%default]") - - parser.add_option("-A", "--Ain", unit=units.RSun, - dest="inner_semimajor_axis", type="float", - default = 200.0 |units.RSun, - help="inner semi major axis [%default]") - parser.add_option("-a", "--Aout",unit=units.RSun, - dest="outer_semimajor_axis", type="float", - default = 20000.0 |units.RSun, - help="outer semi major axis [%default]") - parser.add_option("-E", "--Ein", - dest="inner_eccentricity", type="float", default = 0.1, - help="inner eccentricity [%default]") - parser.add_option("-e", "--Eout", - dest="outer_eccentricity", type="float", default = 0.5, - help="outer eccentricity [%default]") - parser.add_option("-i","-I", - dest="relative_inclination", type="float", default = 80.0*np.pi/180.0, - help="relative inclination [rad] [%default]") - parser.add_option("-G", "--Gin", - dest="inner_argument_of_pericenter", type="float", default = 0.1, - help="inner argument of pericenter [rad] [%default]") - parser.add_option("-g","--Gout", - dest="outer_argument_of_pericenter", type="float", default = 0.5, - help="outer argument of pericenter [rad] [%default]") - parser.add_option("-O", "--Oin", - dest="inner_longitude_of_ascending_node", type="float", default = 0.0, - help="inner longitude of ascending node [rad] [%default]") -## outer longitude of ascending nodes = inner - pi -# parser.add_option("-o", -# dest="outer_longitude_of_ascending_node", type="float", default = 0.0, -# help="outer longitude of ascending node [rad] [%default]") - - parser.add_option("-z", "-Z", dest="metallicity", type="float", default = 0.02, - help="metallicity [%default] %unit") - parser.add_option("-t", "-T", unit=units.Myr, - dest="tend", type="float", default = 5.0 |units.Myr, - help="end time [%default] %unit") - parser.add_option("--initial_time", unit=units.Myr, - dest="tinit", type="float", default = 0.0 |units.Myr, - help="initial time [%default] %unit") - parser.add_option("-N", dest="number", type="int", default = 0, - help="number ID of system [%default]") - parser.add_option("-r", dest="maximum_radius_change_factor", type="float", default = 0.01, - help="maximum_radius_change_factor [%default] %unit") - -# parser.add_option("--tidal", dest="tidal_terms", action="store_false", default = True, -# help="tidal terms included [%default] %unit") - - parser.add_option("--no_stop_at_mass_transfer", dest="stop_at_mass_transfer", action="store_false", default = True, - help="stop at mass transfer [%default] %unit") - parser.add_option("--no_stop_at_init_mass_transfer", dest="stop_at_init_mass_transfer", action="store_false", default = True, - help="stop if initially mass transfer[%default] %unit") - parser.add_option("--no_stop_at_outer_mass_transfer", dest="stop_at_outer_mass_transfer", action="store_false", default = True, - help="stop at triple mass transfer [%default] %unit") - -# if stop_at_mass_transfer is False, the following 4 stopping conditions can be used to further specify. -# if stop_at_mass_transfer is True, the following 4 are ignored. - parser.add_option("--stop_at_stable_mass_transfer", dest="stop_at_stable_mass_transfer", action="store_true", default = False, - help="stop at stable mass transfer [%default] %unit") - parser.add_option("--stop_at_eccentric_stable_mass_transfer", dest="stop_at_eccentric_stable_mass_transfer", action="store_true", - default = False, help="stop at eccentric stable mass transfer [%default] %unit") - #unstable mass transfer leads to common-envelope evolution - parser.add_option("--stop_at_unstable_mass_transfer", dest="stop_at_unstable_mass_transfer", action="store_true", - default = False, help="stop at unstable mass transfer [%default] %unit") - parser.add_option("--stop_at_eccentric_unstable_mass_transfer", dest="stop_at_eccentric_unstable_mass_transfer", - action="store_true", default = False, help="stop at eccentric unstable mass transfer [%default] %unit") - #0 alpha-ce + alpha-dce - #1 gamma-ce + alpha-dce - #2 seba style; combination of gamma-ce, alpha-ce & alpha-dce - parser.add_option("--CE", dest="which_common_envelope", type="int", default = 2, - help="which common envelope modeling [%default]") - - parser.add_option("--stop_at_no_CHE", dest="stop_at_no_CHE", - action="store_true", default = False, help="stop if no chemically homogeneous evolution [%default] %unit") - parser.add_option("--include_CHE", dest="include_CHE", - action="store_true", default = False, help="include chemically homogeneous evolution in the stellar evolution [%default] %unit") - - parser.add_option("--no_stop_at_merger", dest="stop_at_merger", action="store_false", default = True, - help="stop at merger [%default] %unit") - parser.add_option("--no_stop_at_disintegrated", dest="stop_at_disintegrated", action="store_false", default = True, - help="stop at disintegrated [%default] %unit") - parser.add_option("--no_stop_at_inner_collision", dest="stop_at_inner_collision", action="store_false",default = True, - help="stop at collision in inner binary[%default] %unit") - parser.add_option("--no_stop_at_outer_collision", dest="stop_at_outer_collision", action="store_false",default = True, - help="stop at collision in outer binary[%default] %unit") - parser.add_option("--no_stop_at_dynamical_instability", dest="stop_at_dynamical_instability", action="store_false", default = True, - help="stop at dynamical instability [%default] %unit") - parser.add_option("--stop_at_semisecular_regime", dest="stop_at_semisecular_regime", action="store_true", default = False, - help="stop at semisecular regime [%default] %unit") - - parser.add_option("--stop_at_SN", dest="stop_at_SN", action="store_true", default = False, - help="stop at supernova [%default] %unit") - #0 No kick - #1 Hobbs, Lorimer, Lyne & Kramer 2005, 360, 974 - #2 Arzoumanian ea 2002, 568, 289 - #3 Hansen & Phinney 1997, 291, 569 - #4 Paczynski 1990, 348, 485 - #5 Verbunt, Igoshev & Cator, 2017, 608, 57 - parser.add_option("--SN_kick_distr", dest="SN_kick_distr", type="int", default = 5, - help="which supernova kick distribution [%default]") - parser.add_option("--no_impulse_kick_for_black_holes", dest="impulse_kick_for_black_holes", action="store_false", default = True, - help="do not rescale the BH SN kick by mass -> impulse kick [%default]") - parser.add_option("--no_fallback_kick_for_black_holes", dest="fallback_kick_for_black_holes", action="store_false", default = True, - help="do not rescale the BH SN kick with fallback [%default]") - - - - parser.add_option("--stop_at_CPU_time", dest="stop_at_CPU_time", action="store_true", default = False, - help="stop at CPU time [%default] %unit") - parser.add_option("--max_CPU_time", dest="max_CPU_time", type="float", default = 3600.0, - help="max CPU time [%default] %unit") - - - parser.add_option("-f", dest="file_name", type ="string", default = "TRES.hdf",#"TRES.txt" - help="file name[%default]") - parser.add_option("-F", dest="file_type", type ="string", default = "hdf5",#"txt" - help="file type[%default]") - parser.add_option("--dir_plots", dest="dir_plots", type ="string", default = "",#"txt" - help="directory for plots for debugging mode [%default]") - - options, args = parser.parse_args() - return options.__dict__ - - -if __name__ == '__main__': - opt = parse_arguments() - - set_printing_strategy("custom", - preferred_units = [units.MSun, units.RSun, units.Myr], - precision = 11, prefix = "", - separator = " [", suffix = "]") - - stars, bins, correct_params = make_particle_sets(opt["inner_primary_mass"], opt["inner_secondary_mass"], opt["outer_mass"], - opt["inner_semimajor_axis"], opt["outer_semimajor_axis"], - opt["inner_eccentricity"], opt["outer_eccentricity"], - opt["relative_inclination"], - opt["inner_argument_of_pericenter"], opt["outer_argument_of_pericenter"], - opt["inner_longitude_of_ascending_node"]) - - stellar_code = SeBa() -# stellar_code = SeBa(redirection='none') -# stellar_code = SeBa(redirection='file', redirect_file='output_SeBa_TRES.txt') - stellar_code.parameters.metallicity = opt["metallicity"] - secular_code = SecularTriple() -# secular_code = SecularTriple(redirection='none') -# secular_code = SecularTriple(redirection='file', redirect_file='output_SecularTriple_TRES.txt') - - triple_class_object = Triple_Class(stars, bins, correct_params, stellar_code, secular_code, - opt["relative_inclination"], opt["tend"], opt["tinit"], - opt["number"], opt["maximum_radius_change_factor"], - opt["stop_at_mass_transfer"], opt["stop_at_init_mass_transfer"], opt["stop_at_outer_mass_transfer"], - opt["stop_at_stable_mass_transfer"], opt["stop_at_eccentric_stable_mass_transfer"], - opt["stop_at_unstable_mass_transfer"], opt["stop_at_eccentric_unstable_mass_transfer"], opt["which_common_envelope"], - opt["stop_at_no_CHE"], opt["include_CHE"], - opt["stop_at_merger"], opt["stop_at_disintegrated"], opt["stop_at_inner_collision"], opt["stop_at_outer_collision"], - opt["stop_at_dynamical_instability"], opt["stop_at_semisecular_regime"], - opt["stop_at_SN"], opt["SN_kick_distr"], opt["impulse_kick_for_black_holes"], opt["fallback_kick_for_black_holes"], - opt["stop_at_CPU_time"], opt["max_CPU_time"], opt["file_name"], opt["file_type"], opt["dir_plots"]) - - if triple_class_object.correct_params == False: - if REPORT_USER_WARNINGS: - print('Choose a different system. The parameters of the given triple are incorrect.' ) - # no codes initialized yet - sys.exit('Choose a different system. The parameters of the given triple are incorrect.') - elif opt['stop_at_semisecular_regime'] == True and triple_class_object.semisecular_regime_at_initialisation == True: - if REPORT_USER_WARNINGS: - print('Choose a different system. The given triple is in the semisecular regime at initialization.') - elif triple_class_object.dynamical_instability_at_initialisation == True: - if REPORT_USER_WARNINGS: - print('Choose a different system. The given triple is dynamically unstable at initialization.') - elif triple_class_object.mass_transfer_at_initialisation == True: - if REPORT_USER_WARNINGS: - print('Choose a different system. There is mass transfer in the given triple at initialization.') - elif opt["stop_at_no_CHE"] == True and triple_class_object.CHE_at_initialisation == False: - if REPORT_USER_WARNINGS: - print('Choose a different system. No chemically homogeneous evolution at initialization') - else: - triple_class_object.evolve_model(opt["tend"]) - if REPORT_DEBUG or MAKE_PLOTS: - plot_function(triple_class_object, opt['dir_plots']) - triple_class_object.print_stellar_system() - - - - if REPORT_TRIPLE_EVOLUTION: - print('Simulation has finished succesfully') - - print('\nYou have used the TRES triple evolution code. Literature reference:') - print('** Toonen, Hamers & Portegies Zwart 2016, ComAC, 3, 6T:') - print('... "The evolution of hierarchical triple star-systems" ') - - triple_class_object.stellar_code.stop() - triple_class_object.secular_code.stop() - + return triple_class_object + + +def main_developer(stars, bins, correct_params, stellar_code, secular_code, + relative_inclination = 80.0*np.pi/180.0, + metallicity = 0.02, tend = 5.0 |units.Myr, tinit = 0.0 |units.Myr, + number = 0, maximum_radius_change_factor = 0.005, + stop_at_mass_transfer = True, stop_at_init_mass_transfer = True, stop_at_outer_mass_transfer = True, + stop_at_stable_mass_transfer = True, stop_at_eccentric_stable_mass_transfer = True, + stop_at_unstable_mass_transfer = False, stop_at_eccentric_unstable_mass_transfer = False, which_common_envelope = 2, + stop_at_no_CHE = False, include_CHE = False, + stop_at_merger = True, stop_at_disintegrated = True, stop_at_inner_collision = True, stop_at_outer_collision = True, + stop_at_dynamical_instability = True, stop_at_semisecular_regime = False, + stop_at_SN = False, SN_kick_distr = 2, impulse_kick_for_black_holes = True, fallback_kick_for_black_holes = True, + stop_at_CPU_time = False, max_CPU_time = 3600.0, file_name = "TRES.hdf", file_type = "hdf5", dir_plots = ""): + + + set_printing_strategy("custom", + preferred_units = [units.MSun, units.RSun, units.Myr], + precision = 11, prefix = "", + separator = " [", suffix = "]") + + bins.eccentricity[0] = float(bins.eccentricity[0]) + bins.eccentricity[1] = float(bins.eccentricity[1]) + bins.argument_of_pericenter[0] = float(bins.argument_of_pericenter[0]) + bins.argument_of_pericenter[1] = float(bins.argument_of_pericenter[1]) + bins.longitude_of_ascending_node[0] = float(bins.longitude_of_ascending_node[0]) + bins.longitude_of_ascending_node[1] = float(bins.longitude_of_ascending_node[1]) + relative_inclination = float(relative_inclination) + + triple_class_object = Triple_Class(stars, bins, correct_params, stellar_code, secular_code, + relative_inclination, tend, tinit, + number, maximum_radius_change_factor, + stop_at_mass_transfer, stop_at_init_mass_transfer, stop_at_outer_mass_transfer, + stop_at_stable_mass_transfer, stop_at_eccentric_stable_mass_transfer, + stop_at_unstable_mass_transfer, stop_at_eccentric_unstable_mass_transfer, which_common_envelope, + stop_at_no_CHE, include_CHE, + stop_at_merger, stop_at_disintegrated, stop_at_inner_collision, stop_at_outer_collision, + stop_at_dynamical_instability, stop_at_semisecular_regime, + stop_at_SN, SN_kick_distr, impulse_kick_for_black_holes, fallback_kick_for_black_holes, + stop_at_CPU_time, max_CPU_time, file_name, file_type, dir_plots) + + + if triple_class_object.correct_params == False: + if REPORT_USER_WARNINGS: + print('Choose a different system. The parameters of the given triple are incorrect.') + return triple_class_object # no codes initialized yet + elif stop_at_semisecular_regime == True and triple_class_object.semisecular_regime_at_initialisation == True: + if REPORT_USER_WARNINGS: + print('Choose a different system. The given triple is in the semisecular regime at initialization.') + elif triple_class_object.dynamical_instability_at_initialisation == True: + if REPORT_USER_WARNINGS: + print('Choose a different system. The given triple is dynamically unstable at initialization.') + elif triple_class_object.mass_transfer_at_initialisation == True: + if REPORT_USER_WARNINGS: + print('Choose a different system. There is mass transfer in the given triple at initialization.') + elif stop_at_no_CHE == True and triple_class_object.CHE_at_initialisation == False: + if REPORT_USER_WARNINGS: + print('Choose a different system. No chemically homogeneous evolution at initialization') + else: + triple_class_object.evolve_model(tend) + if REPORT_DEBUG or MAKE_PLOTS: + plot_function(triple_class_object, dir_plots) + triple_class_object.print_stellar_system() + + return triple_class_object + + + +#----- + +#----- +#for running triple.py from the commandline +def parse_arguments(): + from amuse.units.optparse import OptionParser + parser = OptionParser() + parser.add_option("-M", "--M1", unit=units.MSun, + dest="inner_primary_mass", type="float", default = 1.3|units.MSun, + help="inner primary mass [%default]") + parser.add_option("-m", "--M2", unit=units.MSun, + dest="inner_secondary_mass", type="float", default = 0.5|units.MSun, + help="inner secondary mass [%default]") + parser.add_option("-l", "--M3", unit=units.MSun, + dest="outer_mass", type="float", default = 0.5|units.MSun, + help="outer mass [%default]") + + parser.add_option("-A", "--Ain", unit=units.RSun, + dest="inner_semimajor_axis", type="float", + default = 200.0 |units.RSun, + help="inner semi major axis [%default]") + parser.add_option("-a", "--Aout",unit=units.RSun, + dest="outer_semimajor_axis", type="float", + default = 20000.0 |units.RSun, + help="outer semi major axis [%default]") + parser.add_option("-E", "--Ein", + dest="inner_eccentricity", type="float", default = 0.1, + help="inner eccentricity [%default]") + parser.add_option("-e", "--Eout", + dest="outer_eccentricity", type="float", default = 0.5, + help="outer eccentricity [%default]") + parser.add_option("-i","-I", + dest="relative_inclination", type="float", default = 80.0*np.pi/180.0, + help="relative inclination [rad] [%default]") + parser.add_option("-G", "--Gin", + dest="inner_argument_of_pericenter", type="float", default = 0.1, + help="inner argument of pericenter [rad] [%default]") + parser.add_option("-g","--Gout", + dest="outer_argument_of_pericenter", type="float", default = 0.5, + help="outer argument of pericenter [rad] [%default]") + parser.add_option("-O", "--Oin", + dest="inner_longitude_of_ascending_node", type="float", default = 0.0, + help="inner longitude of ascending node [rad] [%default]") +## outer longitude of ascending nodes = inner - pi +# parser.add_option("-o", +# dest="outer_longitude_of_ascending_node", type="float", default = 0.0, +# help="outer longitude of ascending node [rad] [%default]") + + parser.add_option("-z", "-Z", dest="metallicity", type="float", default = 0.02, + help="metallicity [%default] %unit") + parser.add_option("-t", "-T", unit=units.Myr, + dest="tend", type="float", default = 5.0 |units.Myr, + help="end time [%default] %unit") + parser.add_option("--initial_time", unit=units.Myr, + dest="tinit", type="float", default = 0.0 |units.Myr, + help="initial time [%default] %unit") + parser.add_option("-N", dest="number", type="int", default = 0, + help="number ID of system [%default]") + parser.add_option("-r", dest="maximum_radius_change_factor", type="float", default = 0.01, + help="maximum_radius_change_factor [%default] %unit") + +# parser.add_option("--tidal", dest="tidal_terms", action="store_false", default = True, +# help="tidal terms included [%default] %unit") + + parser.add_option("--no_stop_at_mass_transfer", dest="stop_at_mass_transfer", action="store_false", default = True, + help="stop at mass transfer [%default] %unit") + parser.add_option("--no_stop_at_init_mass_transfer", dest="stop_at_init_mass_transfer", action="store_false", default = True, + help="stop if initially mass transfer[%default] %unit") + parser.add_option("--no_stop_at_outer_mass_transfer", dest="stop_at_outer_mass_transfer", action="store_false", default = True, + help="stop at triple mass transfer [%default] %unit") + +# if stop_at_mass_transfer is False, the following 4 stopping conditions can be used to further specify. +# if stop_at_mass_transfer is True, the following 4 are ignored. + parser.add_option("--stop_at_stable_mass_transfer", dest="stop_at_stable_mass_transfer", action="store_true", default = False, + help="stop at stable mass transfer [%default] %unit") + parser.add_option("--stop_at_eccentric_stable_mass_transfer", dest="stop_at_eccentric_stable_mass_transfer", action="store_true", + default = False, help="stop at eccentric stable mass transfer [%default] %unit") + #unstable mass transfer leads to common-envelope evolution + parser.add_option("--stop_at_unstable_mass_transfer", dest="stop_at_unstable_mass_transfer", action="store_true", + default = False, help="stop at unstable mass transfer [%default] %unit") + parser.add_option("--stop_at_eccentric_unstable_mass_transfer", dest="stop_at_eccentric_unstable_mass_transfer", + action="store_true", default = False, help="stop at eccentric unstable mass transfer [%default] %unit") + #0 alpha-ce + alpha-dce + #1 gamma-ce + alpha-dce + #2 seba style; combination of gamma-ce, alpha-ce & alpha-dce + parser.add_option("--CE", dest="which_common_envelope", type="int", default = 2, + help="which common envelope modeling [%default]") + + parser.add_option("--stop_at_no_CHE", dest="stop_at_no_CHE", + action="store_true", default = False, help="stop if no chemically homogeneous evolution [%default] %unit") + parser.add_option("--include_CHE", dest="include_CHE", + action="store_true", default = False, help="include chemically homogeneous evolution in the stellar evolution [%default] %unit") + + parser.add_option("--no_stop_at_merger", dest="stop_at_merger", action="store_false", default = True, + help="stop at merger [%default] %unit") + parser.add_option("--no_stop_at_disintegrated", dest="stop_at_disintegrated", action="store_false", default = True, + help="stop at disintegrated [%default] %unit") + parser.add_option("--no_stop_at_inner_collision", dest="stop_at_inner_collision", action="store_false",default = True, + help="stop at collision in inner binary[%default] %unit") + parser.add_option("--no_stop_at_outer_collision", dest="stop_at_outer_collision", action="store_false",default = True, + help="stop at collision in outer binary[%default] %unit") + parser.add_option("--no_stop_at_dynamical_instability", dest="stop_at_dynamical_instability", action="store_false", default = True, + help="stop at dynamical instability [%default] %unit") + parser.add_option("--stop_at_semisecular_regime", dest="stop_at_semisecular_regime", action="store_true", default = False, + help="stop at semisecular regime [%default] %unit") + + parser.add_option("--stop_at_SN", dest="stop_at_SN", action="store_true", default = False, + help="stop at supernova [%default] %unit") + #0 No kick + #1 Hobbs, Lorimer, Lyne & Kramer 2005, 360, 974 + #2 Arzoumanian ea 2002, 568, 289 + #3 Hansen & Phinney 1997, 291, 569 + #4 Paczynski 1990, 348, 485 + #5 Verbunt, Igoshev & Cator, 2017, 608, 57 + parser.add_option("--SN_kick_distr", dest="SN_kick_distr", type="int", default = 5, + help="which supernova kick distribution [%default]") + parser.add_option("--no_impulse_kick_for_black_holes", dest="impulse_kick_for_black_holes", action="store_false", default = True, + help="do not rescale the BH SN kick by mass -> impulse kick [%default]") + parser.add_option("--no_fallback_kick_for_black_holes", dest="fallback_kick_for_black_holes", action="store_false", default = True, + help="do not rescale the BH SN kick with fallback [%default]") + + + + parser.add_option("--stop_at_CPU_time", dest="stop_at_CPU_time", action="store_true", default = False, + help="stop at CPU time [%default] %unit") + parser.add_option("--max_CPU_time", dest="max_CPU_time", type="float", default = 3600.0, + help="max CPU time [%default] %unit") + + + parser.add_option("-f", dest="file_name", type ="string", default = "TRES.hdf",#"TRES.txt" + help="file name[%default]") + parser.add_option("-F", dest="file_type", type ="string", default = "hdf5",#"txt" + help="file type[%default]") + parser.add_option("--dir_plots", dest="dir_plots", type ="string", default = "",#"txt" + help="directory for plots for debugging mode [%default]") + + options, args = parser.parse_args() + return options.__dict__ + + +if __name__ == '__main__': + opt = parse_arguments() + + set_printing_strategy("custom", + preferred_units = [units.MSun, units.RSun, units.Myr], + precision = 11, prefix = "", + separator = " [", suffix = "]") + + stars, bins, correct_params = make_particle_sets(opt["inner_primary_mass"], opt["inner_secondary_mass"], opt["outer_mass"], + opt["inner_semimajor_axis"], opt["outer_semimajor_axis"], + opt["inner_eccentricity"], opt["outer_eccentricity"], + opt["relative_inclination"], + opt["inner_argument_of_pericenter"], opt["outer_argument_of_pericenter"], + opt["inner_longitude_of_ascending_node"]) + + stellar_code = SeBa() +# stellar_code = SeBa(redirection='none') +# stellar_code = SeBa(redirection='file', redirect_file='output_SeBa_TRES.txt') + stellar_code.parameters.metallicity = opt["metallicity"] + secular_code = SecularTriple() +# secular_code = SecularTriple(redirection='none') +# secular_code = SecularTriple(redirection='file', redirect_file='output_SecularTriple_TRES.txt') + + triple_class_object = Triple_Class(stars, bins, correct_params, stellar_code, secular_code, + opt["relative_inclination"], opt["tend"], opt["tinit"], + opt["number"], opt["maximum_radius_change_factor"], + opt["stop_at_mass_transfer"], opt["stop_at_init_mass_transfer"], opt["stop_at_outer_mass_transfer"], + opt["stop_at_stable_mass_transfer"], opt["stop_at_eccentric_stable_mass_transfer"], + opt["stop_at_unstable_mass_transfer"], opt["stop_at_eccentric_unstable_mass_transfer"], opt["which_common_envelope"], + opt["stop_at_no_CHE"], opt["include_CHE"], + opt["stop_at_merger"], opt["stop_at_disintegrated"], opt["stop_at_inner_collision"], opt["stop_at_outer_collision"], + opt["stop_at_dynamical_instability"], opt["stop_at_semisecular_regime"], + opt["stop_at_SN"], opt["SN_kick_distr"], opt["impulse_kick_for_black_holes"], opt["fallback_kick_for_black_holes"], + opt["stop_at_CPU_time"], opt["max_CPU_time"], opt["file_name"], opt["file_type"], opt["dir_plots"]) + + if triple_class_object.correct_params == False: + if REPORT_USER_WARNINGS: + print('Choose a different system. The parameters of the given triple are incorrect.' ) + # no codes initialized yet + sys.exit('Choose a different system. The parameters of the given triple are incorrect.') + elif opt['stop_at_semisecular_regime'] == True and triple_class_object.semisecular_regime_at_initialisation == True: + if REPORT_USER_WARNINGS: + print('Choose a different system. The given triple is in the semisecular regime at initialization.') + elif triple_class_object.dynamical_instability_at_initialisation == True: + if REPORT_USER_WARNINGS: + print('Choose a different system. The given triple is dynamically unstable at initialization.') + elif triple_class_object.mass_transfer_at_initialisation == True: + if REPORT_USER_WARNINGS: + print('Choose a different system. There is mass transfer in the given triple at initialization.') + elif opt["stop_at_no_CHE"] == True and triple_class_object.CHE_at_initialisation == False: + if REPORT_USER_WARNINGS: + print('Choose a different system. No chemically homogeneous evolution at initialization') + else: + triple_class_object.evolve_model(opt["tend"]) + if REPORT_DEBUG or MAKE_PLOTS: + plot_function(triple_class_object, opt['dir_plots']) + triple_class_object.print_stellar_system() + + + + if REPORT_TRIPLE_EVOLUTION: + print('Simulation has finished succesfully') + + print('\nYou have used the TRES triple evolution code. Literature reference:') + print('** Toonen, Hamers & Portegies Zwart 2016, ComAC, 3, 6T:') + print('... "The evolution of hierarchical triple star-systems" ') + + triple_class_object.stellar_code.stop() + triple_class_object.secular_code.stop() + From 51191b123a97fe352a3b8b24e48b12a0e3404716 Mon Sep 17 00:00:00 2001 From: Steven Rieder Date: Fri, 1 Nov 2024 14:16:48 +0100 Subject: [PATCH 03/30] initial refactor of tps.py --- src/tres/TPS.py | 3759 ++++++++++++++++++++++++++++++----------------- 1 file changed, 2433 insertions(+), 1326 deletions(-) diff --git a/src/tres/TPS.py b/src/tres/TPS.py index 23de6b2..b0e483a 100644 --- a/src/tres/TPS.py +++ b/src/tres/TPS.py @@ -1,1341 +1,2448 @@ -# TPS: Triple population synthesis. -## computes the evolution of a population of given triples -## given any initial conditions (M, q, m, A, a, E, e, i, G, g, O, o). -## Options: --M_max upper limit for the inner primary mass [100 Msun] -## --M_min lower limit for the inner primary mass [0.1 Msun] -## --M_distr mass function option: -lib_inner_primary_mass_distr = {0: "Kroupa", #default - 1: "Scalo", - 2: "Miller & Scalo", - 3: "Salpeter", - 4: "Logarithmically flat", - 5: "Eggleton", - 6: "Kroupa for massive stars M>0.5 powerlaw with exp=-2.3",} -## --Q_max upper limit for the inner mass ratio [1.] -## --Q_min lower limit for the inner mass ratio [0.] -## --Q_distr inner mass ratio option: -lib_inner_mass_ratio_distr = {0: "Uniform distribution", #default - 1: "Kroupa IMF", #draws from mass distribution instead of mass ratio distribution - 2: "Galicher et al. 2016 powerlaw (M^-1.31)", } #draws from mass distribution instead of mass ratio distribution, appropriate for planets -## --q_max upper limit for the outer mass ratio [1.] -## --q_min lower limit for the mass of the outer star [0.] -## --q_distr outer mass ratio option: -lib_outer_mass_ratio_distr = {0: "Uniform distribution", #default - 1: "Kroupa IMF", #draws from mass distribution instead of mass ratio distribution - 2: "Galicher et al. 2016 powerlaw (M^-1.31)", } #draws from mass distribution instead of mass ratio distribution, appropriate for planets -## --A_max upper limit for the inner semi-major axis [5e6 RSun] -## --A_min lower limit for the inner semi-major axis [5] -## --A_distr inner semi-major axcis option: -lib_inner_semi_distr = {0: "Log Uniform distribution", #default - 1: "Constant semi-major axis", - 2: "Tokovinin lognormal mu = 10^5d, sigma = 2.3", - 3: "Lognormal mu = 10^3.5d, sigma = 2.3", - 4: "Rizzuto Lognormal mu = 10^0.95 AU, sigma = 1.35", - 5: "Sana et al. 2012", - 6: "flat distribution", - 7: "Galicher et al. 2016 powerlaw (a^-0.61)",} #appropriate for planets -## --a_max upper limit for the outer semi-major axis [5e6 RSun] -## --a_min lower limit for the outer semi-major axis [5 RSun] -## --a_distr outer semi-major axis option: -lib_outer_semi_distr = {0: "Log Uniform distribution", #default - 1: "Constant semi-major axis", - 2: "Tokovinin lognormal mu = 10^5d, sigma = 2.3", - 3: "Lognormal mu = 10^3.5d, sigma = 2.3", - 4: "Rizzuto Lognormal mu = 10^0.95 AU, sigma = 1.35", - 5: "Sana et al. 2012", - 6: "flat distribution", - 7: "Galicher et al. 2016 powerlaw (a^-0.61)",} #appropriate for planets -## --E_max upper limit for the inner eccentricity [0.9] -## --E_min lower limit for the inner eccentricity [0.] -## --E_distr inner eccentricity option: -lib_inner_ecc_distr = {0: "Thermal", #default - 1: "Constant eccentricity", - 2: "Sana et al. 2012 e^-0.45", #-> close binaries - 3: "Flat distribution", - 4: "Powerlaw e^0.5", - 5: "Bowler et al. 2020 Beta distribution",} #appropriate for planets -## --e_max upper limit for the outer eccentricity [0.9] -## --e_min lower limit for the outer eccentricity [0.] -## --e_distr outer eccentricity option: -lib_outer_ecc_distr = {0: "Thermal", #default - 1: "Constant eccentricity", - 2: "Sana et al. 2012 e^-0.45", #-> close binaries - 3: "Flat distribution", - 4: "Powerlaw e^0.5", - 5: "Bowler et al. 2020 Beta distribution",} #appropriate for planets -## --i_max upper limit for the relative inclination [pi] -## --i_min lower limit for the relative inclination [0] -## --i_distr relative inclination option: -lib_incl_distr = {0: "Circular uniform distribution", #default - 1: "Constant inclination",} -## --G_max upper limit for the inner argument of pericenter [pi] -## --G_min lower limit for the inner argument of pericenter [-pi] -## --G_distr inner argument of pericenter option: r -lib_inner_aop_distr = {0: "Uniform distribution", #default - 1: "Constant argument of pericenter",} -## --g_max upper limit for the outer argument of pericenter [pi] -## --g_min lower limit for the outer argument of pericenter [-pi] -## --g_distr outer argument of pericenter option: -lib_outer_aop_distr = {0: "Uniform distribution", #default - 1: "Constant argument of pericenter",} -## outer longitude of ascending nodes = inner - pi -## --O_max upper limit for the inner longitude of ascending node [pi] -## --O_min lower limit for the inner longitude of ascending node [-pi] -## --O_distr inner longitude of ascending node option: -lib_inner_loan_distr = {0: "Circular niform distribution", - 1: "Constant longitude of ascending nodes",} #default -## -T or -t binary end time. [13500 Myr] -## -z metallicity of stars [0.02 Solar] -## -n total number of systems to be simulated. [1] -## -N number ID of first system. [0] -## --no_stop_at_mass_transfer stopping condition at mass transfer -## --no_stop_at_init_mass_transfer stopping condition at mass transfer at initialisation -## --no_stop_at_outer_mass_transfer stopping condition at mass transfer in outer binary -## --stop_at_stable_mass_transfer stopping condition at stable mass transfer -## --stop_at_eccentric_stable_mass_transfer stopping condition at eccentric stable mass transfer -## --stop_at_unstable_mass_transfer stopping condition at unstable mass transfer -## --stop_at_eccentric_unstable_mass_transfer stopping condition at eccentric unstable mass transfer -## --stop_at_no_CHE stopping condition if no chemically homogeneous evolution - -## --no_stop_at_merger stopping condition at merger -## --no_stop_at_disintegrated stopping condition at disintegration -## --no_stop_at_inner_collision stopping condition at collision in inner binary -## --no_stop_at_outer_collision stopping condition at collision involving tertiary star -## --no_stop_at_dynamical_instability stopping condition at dynamical instability -## --stop_at_semisecular_regime stopping condition at semisecular regime -## --stop_at_SN stopping condition at supernova -lib_SN_kick_distr = {0: "No kick", - 1: "Hobbs", #Hobbs, Lorimer, Lyne & Kramer 2005, 360, 974 - 2: "Arzoumanian", #Arzoumanian ea 2002, 568, 289 - 3: "Hansen", #Hansen & Phinney 1997, 291, 569 - 4: "Paczynski", #Paczynski 1990, 348, 485 - 5: "Verbunt", #Verbunt, Igoshev & Cator, 2017, 608, 57 - } #default - - -lib_CE = { 0: "alpha-ce + alpha-dce", - 1: "gamma-ce + alpha-dce", - 2: "seba style; combination of gamma-ce, alpha-ce & alpha-dce", -} - - - -#not implemented yet -## -s random seed - - -import TRES as TRES -from amuse.community.seba.interface import SeBa -from seculartriple_TPS.interface import SecularTriple - +""" +TPS: Triple population synthesis. + computes the evolution of a population of given triples + given any initial conditions (M, q, m, A, a, E, e, i, G, g, O, o). + Options: --M_max upper limit for the inner primary mass [100 Msun] + --M_min lower limit for the inner primary mass [0.1 Msun] + --M_distr mass function option: +lib_inner_primary_mass_distr = { + 0: "Kroupa", # default + 1: "Scalo", + 2: "Miller & Scalo", + 3: "Salpeter", + 4: "Logarithmically flat", + 5: "Eggleton", + 6: "Kroupa for massive stars M>0.5 powerlaw with exp=-2.3", +} +## --Q_max upper limit for the inner mass ratio [1.] +## --Q_min lower limit for the inner mass ratio [0.] +## --Q_distr inner mass ratio option: +lib_inner_mass_ratio_distr = { + 0: "Uniform distribution", # default + 1: "Kroupa IMF", # draws from mass distribution instead of mass ratio distribution + 2: "Galicher et al. 2016 powerlaw (M^-1.31)", +} # draws from mass distribution instead of mass ratio distribution, appropriate for planets +## --q_max upper limit for the outer mass ratio [1.] +## --q_min lower limit for the mass of the outer star [0.] +## --q_distr outer mass ratio option: +lib_outer_mass_ratio_distr = { + 0: "Uniform distribution", # default + 1: "Kroupa IMF", # draws from mass distribution instead of mass ratio distribution + 2: "Galicher et al. 2016 powerlaw (M^-1.31)", +} # draws from mass distribution instead of mass ratio distribution, appropriate for planets +## --A_max upper limit for the inner semi-major axis [5e6 RSun] +## --A_min lower limit for the inner semi-major axis [5] +## --A_distr inner semi-major axcis option: +lib_inner_semi_distr = { + 0: "Log Uniform distribution", # default + 1: "Constant semi-major axis", + 2: "Tokovinin lognormal mu = 10^5d, sigma = 2.3", + 3: "Lognormal mu = 10^3.5d, sigma = 2.3", + 4: "Rizzuto Lognormal mu = 10^0.95 AU, sigma = 1.35", + 5: "Sana et al. 2012", + 6: "flat distribution", + 7: "Galicher et al. 2016 powerlaw (a^-0.61)", +} # appropriate for planets +## --a_max upper limit for the outer semi-major axis [5e6 RSun] +## --a_min lower limit for the outer semi-major axis [5 RSun] +## --a_distr outer semi-major axis option: +lib_outer_semi_distr = { + 0: "Log Uniform distribution", # default + 1: "Constant semi-major axis", + 2: "Tokovinin lognormal mu = 10^5d, sigma = 2.3", + 3: "Lognormal mu = 10^3.5d, sigma = 2.3", + 4: "Rizzuto Lognormal mu = 10^0.95 AU, sigma = 1.35", + 5: "Sana et al. 2012", + 6: "flat distribution", + 7: "Galicher et al. 2016 powerlaw (a^-0.61)", +} # appropriate for planets +## --E_max upper limit for the inner eccentricity [0.9] +## --E_min lower limit for the inner eccentricity [0.] +## --E_distr inner eccentricity option: +lib_inner_ecc_distr = { + 0: "Thermal", # default + 1: "Constant eccentricity", + 2: "Sana et al. 2012 e^-0.45", # -> close binaries + 3: "Flat distribution", + 4: "Powerlaw e^0.5", + 5: "Bowler et al. 2020 Beta distribution", +} # appropriate for planets +## --e_max upper limit for the outer eccentricity [0.9] +## --e_min lower limit for the outer eccentricity [0.] +## --e_distr outer eccentricity option: +lib_outer_ecc_distr = { + 0: "Thermal", # default + 1: "Constant eccentricity", + 2: "Sana et al. 2012 e^-0.45", # -> close binaries + 3: "Flat distribution", + 4: "Powerlaw e^0.5", + 5: "Bowler et al. 2020 Beta distribution", +} # appropriate for planets +## --i_max upper limit for the relative inclination [pi] +## --i_min lower limit for the relative inclination [0] +## --i_distr relative inclination option: +lib_incl_distr = { + 0: "Circular uniform distribution", # default + 1: "Constant inclination", +} +## --G_max upper limit for the inner argument of pericenter [pi] +## --G_min lower limit for the inner argument of pericenter [-pi] +## --G_distr inner argument of pericenter option: r +lib_inner_aop_distr = { + 0: "Uniform distribution", # default + 1: "Constant argument of pericenter", +} +## --g_max upper limit for the outer argument of pericenter [pi] +## --g_min lower limit for the outer argument of pericenter [-pi] +## --g_distr outer argument of pericenter option: +lib_outer_aop_distr = { + 0: "Uniform distribution", # default + 1: "Constant argument of pericenter", +} +## outer longitude of ascending nodes = inner - pi +## --O_max upper limit for the inner longitude of ascending node [pi] +## --O_min lower limit for the inner longitude of ascending node [-pi] +## --O_distr inner longitude of ascending node option: +lib_inner_loan_distr = { + 0: "Circular niform distribution", + 1: "Constant longitude of ascending nodes", +} # default +## -T or -t binary end time. [13500 Myr] +## -z metallicity of stars [0.02 Solar] +## -n total number of systems to be simulated. [1] +## -N number ID of first system. [0] +## --no_stop_at_mass_transfer stopping condition at mass transfer +## --no_stop_at_init_mass_transfer stopping condition at mass transfer at initialisation +## --no_stop_at_outer_mass_transfer stopping condition at mass transfer in outer binary +## --stop_at_stable_mass_transfer stopping condition at stable mass transfer +## --stop_at_eccentric_stable_mass_transfer stopping condition at eccentric stable mass transfer +## --stop_at_unstable_mass_transfer stopping condition at unstable mass transfer +## --stop_at_eccentric_unstable_mass_transfer stopping condition at eccentric unstable mass transfer +## --stop_at_no_CHE stopping condition if no chemically homogeneous evolution + +## --no_stop_at_merger stopping condition at merger +## --no_stop_at_disintegrated stopping condition at disintegration +## --no_stop_at_inner_collision stopping condition at collision in inner binary +## --no_stop_at_outer_collision stopping condition at collision involving tertiary star +## --no_stop_at_dynamical_instability stopping condition at dynamical instability +## --stop_at_semisecular_regime stopping condition at semisecular regime +## --stop_at_SN stopping condition at supernova +lib_SN_kick_distr = { + 0: "No kick", + 1: "Hobbs", # Hobbs, Lorimer, Lyne & Kramer 2005, 360, 974 + 2: "Arzoumanian", # Arzoumanian ea 2002, 568, 289 + 3: "Hansen", # Hansen & Phinney 1997, 291, 569 + 4: "Paczynski", # Paczynski 1990, 348, 485 + 5: "Verbunt", # Verbunt, Igoshev & Cator, 2017, 608, 57 +} # default + + +lib_CE = { + 0: "alpha-ce + alpha-dce", + 1: "gamma-ce + alpha-dce", + 2: "seba style; combination of gamma-ce, alpha-ce & alpha-dce", +} + + +# not implemented yet +## -s random seed +""" + + +import sys +import numpy as np +from scipy.interpolate import interp1d +from scipy.stats import beta as beta_distribution + +from amuse.units.optparse import OptionParser +from amuse.units import units, constants +from amuse.support.console import set_printing_strategy + +from amuse.ic.kroupa import new_kroupa_mass_distribution +from amuse.ic.scalo import new_scalo_mass_distribution +from amuse.ic.millerscalo import new_miller_scalo_mass_distribution +from amuse.ic.salpeter import new_salpeter_mass_distribution +from amuse.ic.flatimf import new_flat_mass_distribution +from amuse.community.seba import Seba + +import TRES +from seculartriple_TPS.interface import SecularTriple + +from TRES_options import ( + REPORT_TPS, + REPORT_USER_WARNINGS_TPS, + EXCLUDE_SSO, + precision, + min_mass, + absolute_min_mass, + absolute_max_mass, +) + secular_code = SecularTriple() -import sys -from amuse.units.optparse import OptionParser -from amuse.units import units, constants -from amuse.support.console import set_printing_strategy -import numpy as np -from scipy.interpolate import interp1d -from scipy.stats import beta as beta_distribution - -from amuse.ic.kroupa import new_kroupa_mass_distribution -from amuse.ic.scalo import new_scalo_mass_distribution -from amuse.ic.millerscalo import new_miller_scalo_mass_distribution -from amuse.ic.salpeter import new_salpeter_mass_distribution -from amuse.ic.flatimf import new_flat_mass_distribution - -from TRES_options import REPORT_TPS, \ - REPORT_USER_WARNINGS_TPS, \ - EXCLUDE_SSO, \ - precision, min_mass, absolute_min_mass, absolute_max_mass - -def flat_distr(lower, upper): - return np.random.uniform(lower, upper) - -def log_flat_distr(lower, upper): - x= np.random.uniform(np.log10(lower), np.log10(upper)) - return 10**x - -def eggleton_mass_distr(lower_mass, upper_mass): - turnover_mass = 0.3|units.MSun - power = 0.85 - - y_max = (upper_mass/turnover_mass) **(1/power) - upper = y_max / (1+y_max) - y_min = (lower_mass/turnover_mass) **(1/power) - lower = y_min / (1+y_min) - - x = np.random.uniform(lower, upper) - y=turnover_mass * (x/(1-x))**power - return turnover_mass * (x/(1-x))**power - -def powerlaw_distr(m_min, m_max, slope): - if slope == -1 or slope == 0: - sys.exit('slope of powerlap distribution incorrect') - slope1 = slope + 1 - factor = (pow(m_max / m_min, slope1) - 1.0 ) - x = np.random.uniform(0,1) - return m_min * (1.0 + factor*x) ** (1.0 / slope1) - - -def beta_distr_SSOs(lower, upper, mass): # (Bowler et al. 2020) - min_mass_BD = 16 |units.MJupiter # brown dwarf boundary - if absolute_min_mass < mass <= min_mass_BD : - A, B = 30, 200 # for exoplanets - elif min_mass_BD < mass < min_mass : - A, B = 2.30, 1.65 # for brown dwarfs - else: - sys.exit('You may be using a SSOs distribution for a stellar object, exiting') - - e_sample = beta_distribution.rvs( A, B) - if lower <= e_sample <= upper: - return e_sample - - return beta_distr_SSOs(lower, upper, mass) # pick another sample within given bounds - - -class Generate_initial_triple: - #------- - #setup stellar system - def __init__(self, inner_primary_mass_max, inner_primary_mass_min, - inner_secondary_mass_max, inner_secondary_mass_min, - outer_mass_min, outer_mass_max, - inner_mass_ratio_max, inner_mass_ratio_min, - outer_mass_ratio_max, outer_mass_ratio_min, - inner_semi_max, inner_semi_min, outer_semi_max, outer_semi_min, - inner_semi_latus_rectum_min, outer_semi_latus_rectum_min, - inner_semi_latus_rectum_max, outer_semi_latus_rectum_max, - inner_ecc_max, inner_ecc_min, outer_ecc_max, outer_ecc_min, - incl_max, incl_min, - inner_aop_max, inner_aop_min, outer_aop_max, outer_aop_min, - inner_loan_max, inner_loan_min, - inner_primary_mass_distr, inner_mass_ratio_distr, outer_mass_ratio_distr, - inner_semi_distr, outer_semi_distr, inner_ecc_distr, outer_ecc_distr, incl_distr, - inner_aop_distr, outer_aop_distr, inner_loan_distr): - - if inner_primary_mass_distr == 5: - mass_convergence = False - while mass_convergence == False: - mass_convergence = self.generate_mass_and_semi_eggleton(inner_primary_mass_max, inner_primary_mass_min, - inner_secondary_mass_min,outer_mass_min, outer_mass_max, - inner_semi_max, inner_semi_min, outer_semi_max, outer_semi_min) - - #Does not use boolean inner/outer _semi_latus_rectum_ min/max - self.inner_ecc = self.generate_ecc_1d(inner_ecc_max, inner_ecc_min, inner_ecc_distr, self.inner_secondary_mass) - self.outer_ecc = self.generate_ecc_1d(outer_ecc_max, outer_ecc_min, outer_ecc_distr, self.outer_mass) - - - else: - self.generate_mass(inner_primary_mass_max, inner_primary_mass_min, - inner_secondary_mass_max,inner_secondary_mass_min,outer_mass_min,outer_mass_max, - inner_mass_ratio_max, inner_mass_ratio_min, - outer_mass_ratio_max, outer_mass_ratio_min, - inner_primary_mass_distr, inner_mass_ratio_distr, outer_mass_ratio_distr) - - - orbit_convergence = False - while orbit_convergence == False: - orbit_convergence = self.generate_semi_and_ecc(inner_semi_max, inner_semi_min, - outer_semi_max, outer_semi_min, - inner_semi_distr, outer_semi_distr, - inner_semi_latus_rectum_min, outer_semi_latus_rectum_min, - inner_semi_latus_rectum_max, outer_semi_latus_rectum_max, - inner_ecc_max, inner_ecc_min, - outer_ecc_max, outer_ecc_min, - inner_ecc_distr, outer_ecc_distr, - self.inner_secondary_mass, self.outer_mass) - - - self.generate_incl(incl_max, incl_min, incl_distr) - - self.generate_aop(inner_aop_max, inner_aop_min, - outer_aop_max, outer_aop_min, - inner_aop_distr, outer_aop_distr) - - self.generate_loan(inner_loan_max, inner_loan_min, inner_loan_distr) - - #------- - def generate_mass(self, inner_primary_mass_max, inner_primary_mass_min, - inner_secondary_mass_max,inner_secondary_mass_min,outer_mass_min, outer_mass_max, - inner_mass_ratio_max, inner_mass_ratio_min, - outer_mass_ratio_max, outer_mass_ratio_min, - inner_primary_mass_distr, inner_mass_ratio_distr, outer_mass_ratio_distr): - if REPORT_TPS: - print('generate_mass') - - if inner_primary_mass_max == inner_primary_mass_min: - self.inner_primary_mass = inner_primary_mass_min - else: - if inner_primary_mass_distr == 1: #Scalo 1986 - self.inner_primary_mass= new_scalo_mass_distribution(1, inner_primary_mass_max)[0] - while self.inner_primary_mass < inner_primary_mass_min: - self.inner_primary_mass = new_scalo_mass_distribution(1, inner_primary_mass_max)[0] - elif inner_primary_mass_distr == 2:#Miller & Scale 1979 - self.inner_primary_mass= new_miller_scalo_mass_distribution(1, inner_primary_mass_max)[0] - while self.inner_primary_mass < inner_primary_mass_min: - self.inner_primary_mass = new_miller_scalo_mass_distribution(1, inner_primary_mass_max)[0] - elif inner_primary_mass_distr == 3: #Salpeter with slope 2.35 - self.inner_primary_mass= new_salpeter_mass_distribution(1, inner_primary_mass_min, inner_primary_mass_max)[0] - elif inner_primary_mass_distr == 4: # Flat in log space - self.inner_primary_mass= new_flat_mass_distribution(1, inner_primary_mass_min, inner_primary_mass_max)[0] - elif inner_primary_mass_distr == 5: # Eggleton 2009, 399, 1471, Salpeter-like with turnover at low masses - self.inner_primary_mass= eggleton_mass_distr(inner_primary_mass_min, inner_primary_mass_max) - elif inner_primary_mass_distr == 6: #Salpeter with slope 2.3 -> Kroupa for M>0.5 - self.inner_primary_mass = powerlaw_distr(inner_primary_mass_min, inner_primary_mass_max, -2.3) - else: #Kroupa 2001 - self.inner_primary_mass = new_kroupa_mass_distribution(1, mass_min = inner_primary_mass_min, mass_max = inner_primary_mass_max)[0] - - - if inner_mass_ratio_max == inner_mass_ratio_min: - inner_mass_ratio = inner_mass_ratio_min - self.inner_secondary_mass = inner_mass_ratio * self.inner_primary_mass - else: - if inner_mass_ratio_distr == 1:# Kroupa 2001 - self.inner_secondary_mass = new_kroupa_mass_distribution(1, mass_min=inner_secondary_mass_min, mass_max=inner_secondary_mass_max)[0] -# self.inner_secondary_mass = new_kroupa_mass_distribution(1, mass_min=inner_secondary_mass_min, mass_max=inner_primary_mass_max)[0] -# self.inner_secondary_mass = new_kroupa_mass_distribution(1, mass_min=inner_secondary_mass_min, mass_max=inner_primary_mass)[0] - elif inner_mass_ratio_distr == 2: # Galicher et al 2016 - self.inner_secondary_mass = powerlaw_distr( m_min= inner_secondary_mass_min, m_max= inner_secondary_mass_max, slope= -1.31) - else: # flat distribution - inner_mass_ratio = flat_distr(max(inner_mass_ratio_min, inner_secondary_mass_min/self.inner_primary_mass), min(inner_mass_ratio_max, inner_secondary_mass_max/self.inner_primary_mass)) - self.inner_secondary_mass = inner_mass_ratio * self.inner_primary_mass - - - - if outer_mass_ratio_max == outer_mass_ratio_min: - outer_mass_ratio = outer_mass_ratio_min - self.outer_mass = outer_mass_ratio * (self.inner_primary_mass + self.inner_secondary_mass) - else: - if outer_mass_ratio_distr == 1:# Kroupa 2001 - self.outer_mass = new_kroupa_mass_distribution(1, mass_min=outer_mass_min, mass_max=outer_mass_max)[0] - elif outer_mass_ratio_distr == 2: # Galicher et al 2016 - self.outer_mass = powerlaw_distr( m_min= outer_mass_min, m_max= outer_mass_max, slope= -1.31) - else: # flat distribution - inner_mass_tot = self.inner_primary_mass + self.inner_secondary_mass - outer_mass_ratio = flat_distr(max(outer_mass_ratio_min,outer_mass_min/inner_mass_tot), min(outer_mass_ratio_max, outer_mass_max/inner_mass_tot)) - self.outer_mass = outer_mass_ratio * inner_mass_tot - - - - def generate_semi_and_ecc(self, - inner_semi_max_orig, inner_semi_min_orig, - outer_semi_max_orig, outer_semi_min_orig, - inner_semi_distr, outer_semi_distr, - inner_semi_latus_rectum_min, outer_semi_latus_rectum_min, - inner_semi_latus_rectum_max, outer_semi_latus_rectum_max, - inner_ecc_max, inner_ecc_min, - outer_ecc_max, outer_ecc_min, - inner_ecc_distr, outer_ecc_distr, - inner_secondary_mass, outer_mass): - if REPORT_TPS: - print('generate_semi_and_ecc') - - self.inner_ecc = self.generate_ecc_1d(inner_ecc_max, inner_ecc_min, inner_ecc_distr, inner_secondary_mass) - self.outer_ecc = self.generate_ecc_1d(outer_ecc_max, outer_ecc_min, outer_ecc_distr, outer_mass) - - inner_semi_min = inner_semi_min_orig - if inner_semi_latus_rectum_min: - inner_semi_min = inner_semi_min_orig /(1-self.inner_ecc**2) - outer_semi_min = outer_semi_min_orig - if outer_semi_latus_rectum_min: - outer_semi_min = outer_semi_min_orig /(1-self.outer_ecc**2) - - inner_semi_max = inner_semi_max_orig - if inner_semi_latus_rectum_max: - inner_semi_max = inner_semi_max_orig /(1-self.inner_ecc**2) - outer_semi_max = outer_semi_max_orig - if outer_semi_latus_rectum_max: - outer_semi_max = outer_semi_max_orig /(1-self.outer_ecc**2) - - - - if inner_semi_max == inner_semi_min: - self.inner_semi = inner_semi_min - else: - if inner_semi_distr == 1: #Constant - if REPORT_USER_WARNINGS_TPS: - print('TPS::generate_semi: unambiguous choice of constant semi-major axis') - print('--A_min option to set the value of the semi-major axis in the inner binary') - self.inner_semi = inner_semi_min - elif inner_semi_distr == 2: #Tokovinin Lognormal mu=10^5d, sigma=2.3 - self.inner_semi = 0.|units.RSun - while (self.inner_semi < inner_semi_min or self.inner_semi > inner_semi_max): - self.inner_ecc = self.generate_ecc_1d(inner_ecc_max, inner_ecc_min, inner_ecc_distr, inner_secondary_mass) - inner_semi_min = inner_semi_min_orig - if inner_semi_latus_rectum_min: - inner_semi_min = inner_semi_min_orig /(1-self.inner_ecc**2) - - logP = np.random.normal(5, 2.3, 1) - P = (10**logP[0])|units.day - self.inner_semi = ((P/2./np.pi)**2 * constants.G* (self.inner_primary_mass + self.inner_secondary_mass))**(1./3.) - if logP < -0.3 or logP > 10:#truncation of Gaussian wings - self.inner_semi = 0.|units.RSun - elif inner_semi_distr == 3: #Lognormal mu=10^3.5d, sigma=2.3 - self.inner_semi = 0.|units.RSun - while (self.inner_semi < inner_semi_min or self.inner_semi > inner_semi_max): - self.inner_ecc = self.generate_ecc_1d(inner_ecc_max, inner_ecc_min, inner_ecc_distr, inner_secondary_mass) - inner_semi_min = inner_semi_min_orig - if inner_semi_latus_rectum_min: - inner_semi_min = inner_semi_min_orig /(1-self.inner_ecc**2) - inner_semi_max = inner_semi_max_orig - if inner_semi_latus_rectum_max: - inner_semi_max = inner_semi_max_orig /(1-self.inner_ecc**2) - - logP = np.random.normal(3.5, 2.3, 1) - P = (10**logP[0])|units.day - self.inner_semi = ((P/2./np.pi)**2 * constants.G* (self.inner_primary_mass + self.inner_secondary_mass))**(1./3.) - if logP < -0.3 or logP > 10:#truncation of Gaussian wings - self.inner_semi = 0.|units.RSun - elif inner_semi_distr == 4: #Rizzuto et al 2013, 436, 1694, Lognormal mu=10^0.95AU, sigma=1.35 - self.inner_semi = 0.|units.RSun - while (self.inner_semi < inner_semi_min or self.inner_semi > inner_semi_max): - self.inner_ecc = self.generate_ecc_1d(inner_ecc_max, inner_ecc_min, inner_ecc_distr, inner_secondary_mass) - inner_semi_min = inner_semi_min_orig - if inner_semi_latus_rectum_min: - inner_semi_min = inner_semi_min_orig /(1-self.inner_ecc**2) - inner_semi_max = inner_semi_max_orig - if inner_semi_latus_rectum_max: - inner_semi_max = inner_semi_max_orig /(1-self.inner_ecc**2) - - logAU = np.random.normal(0.95, 1.35, 1) - self.inner_semi = (10**logAU[0])|units.AU - if self.inner_semi < 0.5|units.RSun or self.inner_semi > 5e8|units.RSun:#truncation of Gaussian wings - self.inner_semi = 0.|units.RSun - - elif inner_semi_distr == 5: #Sana - self.inner_semi = 0.|units.RSun - # (logP)^-0.55 - while (self.inner_semi < inner_semi_min or self.inner_semi > inner_semi_max): - self.inner_ecc = self.generate_ecc_1d(inner_ecc_max, inner_ecc_min, inner_ecc_distr, inner_secondary_mass) - inner_semi_min = inner_semi_min_orig - if inner_semi_latus_rectum_min: - inner_semi_min = inner_semi_min_orig /(1-self.inner_ecc**2) - inner_semi_max = inner_semi_max_orig - if inner_semi_latus_rectum_max: - inner_semi_max = inner_semi_max_orig /(1-self.inner_ecc**2) - - random_nr = flat_distr(0, 1) - logP_min = 0.15 - logP_max = 8.5 - c_s = (logP_max**0.45 - logP_min**0.45) - logP = (random_nr*c_s +logP_min**0.45)**(1./0.45) - P0 = 10**logP|units.day - M_inner = self.inner_primary_mass + self.inner_secondary_mass - self.inner_semi = ((P0/2./np.pi)**2 * M_inner*constants.G ) ** (1./3.) - - elif inner_semi_distr == 6: # flat distr (uniform) - self.inner_semi = flat_distr( inner_semi_min.value_in(units.RSun), inner_semi_max.value_in(units.RSun))|units.RSun - elif inner_semi_distr == 7: # Galicher 2016: powerlaw, slope -0.61 - self.inner_semi = powerlaw_distr( inner_semi_min, inner_semi_max, slope= -0.61) - - else: # log flat distribution - maximal_semi = min(inner_semi_max, outer_semi_max) - if inner_semi_min > maximal_semi: #possible for extreme eccentricities - return False - self.inner_semi = log_flat_distr(inner_semi_min.value_in(units.RSun), maximal_semi.value_in(units.RSun))|units.RSun - - - - if outer_semi_max == outer_semi_min: - self.outer_semi = outer_semi_min - else: - if outer_semi_distr == 1: #Constant - if REPORT_USER_WARNINGS_TPS: - print('TPS::generate_semi: unambiguous choise of constant semi-major axis') - print('--a_min option to set the value of the semi-major axis in the outer binary') - self.outer_semi = outer_semi_min - elif outer_semi_distr == 2: #Tokovinin Lognormal mu=10^5.5d, sigma=2.3 - self.outer_semi = 0.|units.RSun - while (self.outer_semi < outer_semi_min or self.outer_semi > outer_semi_max): - self.outer_ecc = self.generate_ecc_1d(outer_ecc_max, outer_ecc_min, outer_ecc_distr, outer_mass) - outer_semi_min = outer_semi_min_orig - if outer_semi_latus_rectum_min: - outer_semi_min = outer_semi_min_orig /(1-self.outer_ecc**2) - outer_semi_max = outer_semi_max_orig - if outer_semi_latus_rectum_max: - outer_semi_max = outer_semi_max_orig /(1-self.outer_ecc**2) - - logP_out = np.random.normal(5, 2.3, 1) - P_out = (10**logP_out[0])|units.day - self.outer_semi = ((P_out/2./np.pi)**2 * constants.G* (self.inner_primary_mass + self.inner_secondary_mass + self.outer_mass))**(1./3.) - if logP_out < -0.3 or logP_out > 10:#truncation of Gaussian wings - self.outer_semi = 0.|units.RSun - if logP_out < 3: # no bifurcation - self.outer_semi = 0.|units.RSun - - elif outer_semi_distr == 3: #Lognormal mu=10^3.5d, sigma=2.3 - self.outer_semi = 0.|units.RSun - while (self.outer_semi < outer_semi_min or self.outer_semi > outer_semi_max): - self.outer_ecc = self.generate_ecc_1d(outer_ecc_max, outer_ecc_min, outer_ecc_distr, outer_mass) - outer_semi_min = outer_semi_min_orig - if outer_semi_latus_rectum_min: - outer_semi_min = outer_semi_min_orig /(1-self.outer_ecc**2) - outer_semi_max = outer_semi_max_orig - if outer_semi_latus_rectum_max: - outer_semi_max = outer_semi_max_orig /(1-self.outer_ecc**2) - - logP_out = np.random.normal(5, 2.3, 1) - P_out = (10**logP_out[0])|units.day - self.outer_semi = ((P_out/2./np.pi)**2 * constants.G* (self.inner_primary_mass + self.inner_secondary_mass + self.outer_mass))**(1./3.) - if logP_out < -0.3 or logP_out > 10:#truncation of Gaussian wings - self.outer_semi = 0.|units.RSun - if logP_out < 3: # no bifurcation - self.outer_semi = 0.|units.RSun - - elif outer_semi_distr == 4: #Rizzuto et al 2013, 436, 1694, Lognormal mu=10^0.95AU, sigma=1.35 - self.outer_semi = 0.|units.RSun - while (self.outer_semi < outer_semi_min or self.outer_semi > outer_semi_max): - self.outer_ecc = self.generate_ecc_1d(outer_ecc_max, outer_ecc_min, outer_ecc_distr, outer_mass) - outer_semi_min = outer_semi_min_orig - if outer_semi_latus_rectum_min: - outer_semi_min = outer_semi_min_orig /(1-self.outer_ecc**2) - outer_semi_max = outer_semi_max_orig - if outer_semi_latus_rectum_max: - outer_semi_max = outer_semi_max_orig /(1-self.outer_ecc**2) - - logAU = np.random.normal(0.95, 1.35, 1) - self.outer_semi = (10**logAU[0])|units.AU - if self.outer_semi < 0.5|units.RSun or self.outer_semi > 5e8|units.RSun:#truncation of Gaussian wings - self.outer_semi = 0.|units.RSun - - elif outer_semi_distr == 5: #Sana - self.outer_semi = 0.|units.RSun - # (logP)^-0.55 - while (self.outer_semi < outer_semi_min or self.outer_semi > outer_semi_max): - self.outer_ecc = self.generate_ecc_1d(outer_ecc_max, outer_ecc_min, outer_ecc_distr, outer_mass) - outer_semi_min = outer_semi_min_orig - if outer_semi_latus_rectum_min: - outer_semi_min = outer_semi_min_orig /(1-self.outer_ecc**2) - outer_semi_max = outer_semi_max_orig - if outer_semi_latus_rectum_max: - outer_semi_max = outer_semi_max_orig /(1-self.outer_ecc**2) - - random_nr = flat_distr(0, 1) - logP_min = 0.15 - logP_max = 8.5 - c_s = (logP_max**0.45 - logP_min**0.45) - logP = (random_nr*c_s +logP_min**0.45)**(1./0.45) - P0 = 10**logP|units.day - mass_tot = self.inner_primary_mass + self.inner_secondary_mass + self.outer_mass - self.outer_semi = ((P0/2./np.pi)**2 * mass_tot*constants.G) ** (1./3.) - - elif outer_semi_distr == 6: # flat distr (uniform) - self.outer_semi = flat_distr( outer_semi_min.value_in(units.RSun), outer_semi_max.value_in(units.RSun))|units.RSun - elif outer_semi_distr == 7: # Galicher 2016: powerlaw, slope -0.61 - self.outer_semi = powerlaw_distr( outer_semi_min, outer_semi_max, slope= -0.61) - - else: # log flat distribution - if outer_semi_min > outer_semi_max: #possible for extreme eccentricities - return False - self.outer_semi = log_flat_distr(outer_semi_min.value_in(units.RSun), outer_semi_max.value_in(units.RSun))|units.RSun - - - if inner_semi_distr == outer_semi_distr and inner_semi_min_orig == outer_semi_min_orig and inner_semi_max == outer_semi_max and self.outer_semi < self.inner_semi and inner_ecc_distr == outer_ecc_distr and inner_ecc_min == outer_ecc_min and inner_ecc_max == outer_ecc_max: - swap = self.outer_semi - self.outer_semi = self.inner_semi - self.inner_semi = swap - swap = self.outer_ecc - self.outer_ecc = self.inner_ecc - self.inner_ecc = swap - return True - elif self.outer_semi < self.inner_semi: - return False - return True - - - def generate_ecc_1d(self, ecc_max, ecc_min, ecc_distr, mass): - if REPORT_TPS: - print('generate_ecc_1d') - - if ecc_max == ecc_min: - return ecc_min - else: - if ecc_distr == 1: #Constant - if REPORT_USER_WARNINGS_TPS: - print('TPS::generate_ecc: unambiguous choise of constant eccentricity') - print('--E_min and --e_min option to set the value of the eccentricity') - return ecc_min - elif ecc_distr == 2: #Sana - return powerlaw_distr(ecc_min+precision, ecc_max, -0.45) - elif ecc_distr == 3: #flat distribution - return flat_distr(ecc_min, ecc_max) - elif ecc_distr == 4: #Powerlaw - return powerlaw_distr(ecc_min+precision, ecc_max, 0.5) - elif ecc_distr == 5: # Beta distribution - return beta_distr_SSOs(ecc_min, ecc_max, mass) - else: #Thermal distribution - return np.sqrt(np.random.uniform(ecc_min*ecc_min, ecc_max*ecc_max)) - - - - - def generate_incl(self, incl_max, incl_min, incl_distr): - if REPORT_TPS: - print('generate_incl') - if incl_max == incl_min: - self.incl = incl_min - else: - if incl_distr == 1: #Constant - if REPORT_USER_WARNINGS_TPS: - print('TPS::generate_incl: unambiguous choise of constant relative inclination') - print('--i_min option to set the value of the relative inclination in the inner triple') - self.incl = incl_min - else: #Circular uniform distribution - self.incl = np.arccos(np.random.uniform(np.cos(incl_min), np.cos(incl_max))) - - def generate_aop(self, - inner_aop_max, inner_aop_min, - outer_aop_max, outer_aop_min, - inner_aop_distr, outer_aop_distr): - if REPORT_TPS: - print('generate_aop') - - if inner_aop_max == inner_aop_min: - self.inner_aop = inner_aop_min - else: - if inner_aop_distr == 1: #Constant - if REPORT_USER_WARNINGS_TPS: - print('TPS::generate_aop: unambiguous choise of constant argument of pericenter') - print('--G_min option to set the value of the argument of pericenter of the inner binary') - self.inner_aop = inner_aop_min - else: #Uniform distribution - self.inner_aop = np.random.uniform(inner_aop_min, inner_aop_max) - - - if outer_aop_max == outer_aop_min: - self.outer_aop = outer_aop_min - else: - if outer_aop_distr == 1: #Constant - if REPORT_USER_WARNINGS_TPS: - print('TPS::generate_aop: unambiguous choise of constant argument of pericenter') - print('--g_min option to set the value of the argument of pericenter of the outer binary') - self.outer_aop = outer_aop_min - else: #Uniform distribution - self.outer_aop = np.random.uniform(outer_aop_min, outer_aop_max) - - - def generate_loan(self, inner_loan_max, inner_loan_min, inner_loan_distr): - if REPORT_TPS: - print('generate_loan') - - if inner_loan_max == inner_loan_min: - self.inner_loan = inner_loan_min - else: - if inner_loan_distr == 0: #Circular uniform distribution - self.inner_loan = np.arccos(np.random.uniform(np.cos(inner_loan_min), np.cos(inner_loan_max))) - else: #Constant - if REPORT_USER_WARNINGS_TPS: - print('TPS::generate_loan: unambiguous choise of constant longitude of ascending nodes') - print('--O_min option to set the value of the argument of pericenter of the inner binary') - self.inner_loan = inner_loan_min - - -#------- - -# Eggleton 2009, 399, 1471 - def generate_mass_and_semi_eggleton(self, inner_primary_mass_max, inner_primary_mass_min, - inner_secondary_mass_min,outer_mass_min,outer_mass_max, - inner_semi_max, inner_semi_min, outer_semi_max, outer_semi_min): - if REPORT_TPS: - print('generate_mass_and_semi_eggleton') - U0_mass = [0., .01, .09, .32, 1., 3.2, 11, 32, np.inf]#solar mass - U0_l0 = [0.40, 0.40, 0.40, 0.40, 0.50, 0.75, 0.88, 0.94, 0.96] - U0_l1 = [0.18, 0.18, 0.18, 0.18, 0.18, 0.18, 0.20, 0.60, 0.80] - U0_l2 = [0.00, 0.00, 0.00, 0.00, 0.00, 0.20, 0.33, 0.82, 0.90] - U0_l3 = [0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00] - - Mt = eggleton_mass_distr(min_mass, absolute_max_mass) - U = np.random.uniform(0, 1) - f_l0 = interp1d (U0_mass, U0_l0) - U0 = f_l0(Mt.value_in(units.MSun)) #messy, but otherwise cluster crashes - - while U >= U0: - U = np.random.uniform(0, 1) - f_l0 = interp1d (U0_mass, U0_l0) - U0 = f_l0(Mt.value_in(units.MSun)) - - if U < U0: - V = np.random.uniform(0, 1) - P0 = 1.e5 * V**2 / (1-V)**2.5 |units.day - while P0 > 1e10|units.day: - V = np.random.uniform(0, 1) - P0 = 1.e5 * V**2 / (1-V)**2.5|units.day - - x_p = np.random.uniform(0, 1) - if P0 > 25|units.day or x_p > 0.25: - Q0 = ( (U0-U)/U0 )**0.8 - else: - Q0 = 0.9+0.09*(U0-U)/U0 - if Q0 < 0.01: - Q0 = 0.01 - - M1 = Mt / (1+Q0) - M2 = M1 * Q0 - f_l1 = interp1d(U0_mass, U0_l1) - - U1 = np.random.uniform(0, 1) - U1_0 = f_l1(M1.value_in(units.MSun)) - U2 = np.random.uniform(0, 1) - U2_0 = f_l1(M2.value_in(units.MSun)) - - #M1 bifurcutas and M2 not - if U1< U1_0 and U2>=U2_0: - M_bin = M1 - U_bin = U1 - U0_bin = U1_0 - M_comp = M2 - #M2 bifurcutas and M1 not - elif U1>= U1_0 and U2 higher order multiplicity -# print(U1, U1_0, U2, U2_0) -# exit(1) - return False - - V_bin = np.random.uniform(0, 1) - P_bin = 0.2 * P0 * 10**(-5*V_bin) - - x_pb = np.random.uniform(0, 1) - if P_bin > 25|units.day or x_pb > 0.25: - Q_bin = ( (U0_bin-U_bin)/U0_bin )**0.8 - else: - Q_bin = 0.9+0.09*(U0_bin-U_bin)/U0_bin - if Q_bin < 0.01: - Q_bin = 0.01 - - M1_bin = M_bin / (1+Q_bin) - M2_bin = M1_bin * Q_bin - - self.inner_primary_mass = M1_bin - self.inner_secondary_mass = M2_bin - self.outer_mass = M_comp - - self.inner_semi = ((P_bin/2./np.pi)**2 * M_bin*constants.G ) ** (1./3.) - self.outer_semi = ((P0/2./np.pi)**2 * Mt*constants.G ) ** (1./3.) - - if self.inner_primary_mass < inner_primary_mass_min or self.inner_primary_mass > inner_primary_mass_max: - return False - if self.inner_secondary_mass < inner_secondary_mass_min: - return False - if self.outer_mass < outer_mass_min or self.outer_mass > outer_mass_max: - return False - if self.inner_semi < inner_semi_min or self.inner_semi > inner_semi_max: - return False - if self.outer_semi < outer_semi_min or self.outer_semi > outer_semi_max: - return False - - return True - else: - sys.exit('not possible in eggleton distribution') - - - -#------- - -#------- - def print_triple(self): - print('\nTriple - ') - print('m =', self.inner_primary_mass, self.inner_secondary_mass, self.outer_mass) - print('a =', self.inner_semi, self.outer_semi) - print('e =', self.inner_ecc, self.outer_ecc) - print('i =', self.incl) - print('g =', self.inner_aop, self.outer_aop) - print('o =', self.inner_loan, self.inner_loan -np.pi) - + +lib_inner_primary_mass_distr = { + 0: "Kroupa", # default + 1: "Scalo", + 2: "Miller & Scalo", + 3: "Salpeter", + 4: "Logarithmically flat", + 5: "Eggleton", + 6: "Kroupa for massive stars M>0.5 powerlaw with exp=-2.3", +} + +lib_inner_mass_ratio_distr = { + 0: "Uniform distribution", # default + 1: "Kroupa IMF", # draws from mass distribution instead of mass ratio distribution + 2: "Galicher et al. 2016 powerlaw (M^-1.31)", +} # draws from mass distribution instead of mass ratio distribution, appropriate for planets + +lib_outer_mass_ratio_distr = { + 0: "Uniform distribution", # default + 1: "Kroupa IMF", # draws from mass distribution instead of mass ratio distribution + 2: "Galicher et al. 2016 powerlaw (M^-1.31)", +} # draws from mass distribution instead of mass ratio distribution, appropriate for planets + +lib_inner_semi_distr = { + 0: "Log Uniform distribution", # default + 1: "Constant semi-major axis", + 2: "Tokovinin lognormal mu = 10^5d, sigma = 2.3", + 3: "Lognormal mu = 10^3.5d, sigma = 2.3", + 4: "Rizzuto Lognormal mu = 10^0.95 AU, sigma = 1.35", + 5: "Sana et al. 2012", + 6: "flat distribution", + 7: "Galicher et al. 2016 powerlaw (a^-0.61)", +} # appropriate for planets + +lib_outer_semi_distr = { + 0: "Log Uniform distribution", # default + 1: "Constant semi-major axis", + 2: "Tokovinin lognormal mu = 10^5d, sigma = 2.3", + 3: "Lognormal mu = 10^3.5d, sigma = 2.3", + 4: "Rizzuto Lognormal mu = 10^0.95 AU, sigma = 1.35", + 5: "Sana et al. 2012", + 6: "flat distribution", + 7: "Galicher et al. 2016 powerlaw (a^-0.61)", +} # appropriate for planets + +lib_inner_ecc_distr = { + 0: "Thermal", # default + 1: "Constant eccentricity", + 2: "Sana et al. 2012 e^-0.45", # -> close binaries + 3: "Flat distribution", + 4: "Powerlaw e^0.5", + 5: "Bowler et al. 2020 Beta distribution", +} # appropriate for planets + +lib_incl_distr = { + 0: "Circular uniform distribution", # default + 1: "Constant inclination", +} + +lib_inner_aop_distr = { + 0: "Uniform distribution", # default + 1: "Constant argument of pericenter", +} + +lib_outer_aop_distr = { + 0: "Uniform distribution", # default + 1: "Constant argument of pericenter", +} + +lib_inner_loan_distr = { + 0: "Circular niform distribution", + 1: "Constant longitude of ascending nodes", +} # default + +lib_SN_kick_distr = { + 0: "No kick", + 1: "Hobbs", # Hobbs, Lorimer, Lyne & Kramer 2005, 360, 974 + 2: "Arzoumanian", # Arzoumanian ea 2002, 568, 289 + 3: "Hansen", # Hansen & Phinney 1997, 291, 569 + 4: "Paczynski", # Paczynski 1990, 348, 485 + 5: "Verbunt", # Verbunt, Igoshev & Cator, 2017, 608, 57 +} # default + + +lib_CE = { + 0: "alpha-ce + alpha-dce", + 1: "gamma-ce + alpha-dce", + 2: "seba style; combination of gamma-ce, alpha-ce & alpha-dce", +} + + +def flat_distr(lower, upper): + return np.random.uniform(lower, upper) + + +def log_flat_distr(lower, upper): + x = np.random.uniform(np.log10(lower), np.log10(upper)) + return 10**x + + +def eggleton_mass_distr(lower_mass, upper_mass): + turnover_mass = 0.3 | units.MSun + power = 0.85 + + y_max = (upper_mass / turnover_mass) ** (1 / power) + upper = y_max / (1 + y_max) + y_min = (lower_mass / turnover_mass) ** (1 / power) + lower = y_min / (1 + y_min) + + x = np.random.uniform(lower, upper) + y = turnover_mass * (x / (1 - x)) ** power + return turnover_mass * (x / (1 - x)) ** power + + +def powerlaw_distr(m_min, m_max, slope): + if slope == -1 or slope == 0: + sys.exit("slope of powerlaw distribution incorrect") + slope1 = slope + 1 + factor = pow(m_max / m_min, slope1) - 1.0 + x = np.random.uniform(0, 1) + return m_min * (1.0 + factor * x) ** (1.0 / slope1) + + +def beta_distr_SSOs(lower, upper, mass): # (Bowler et al. 2020) + min_mass_BD = 16 | units.MJupiter # brown dwarf boundary + if absolute_min_mass < mass <= min_mass_BD: + A, B = 30, 200 # for exoplanets + elif min_mass_BD < mass < min_mass: + A, B = 2.30, 1.65 # for brown dwarfs + else: + sys.exit("You may be using a SSOs distribution for a stellar object, exiting") + + e_sample = beta_distribution.rvs(A, B) + if lower <= e_sample <= upper: + return e_sample + + return beta_distr_SSOs( + lower, upper, mass + ) # pick another sample within given bounds + + +class Generate_initial_triple: + # ------- + # setup stellar system + def __init__( + self, + inner_primary_mass_max, + inner_primary_mass_min, + inner_secondary_mass_max, + inner_secondary_mass_min, + outer_mass_min, + outer_mass_max, + inner_mass_ratio_max, + inner_mass_ratio_min, + outer_mass_ratio_max, + outer_mass_ratio_min, + inner_semi_max, + inner_semi_min, + outer_semi_max, + outer_semi_min, + inner_semi_latus_rectum_min, + outer_semi_latus_rectum_min, + inner_semi_latus_rectum_max, + outer_semi_latus_rectum_max, + inner_ecc_max, + inner_ecc_min, + outer_ecc_max, + outer_ecc_min, + incl_max, + incl_min, + inner_aop_max, + inner_aop_min, + outer_aop_max, + outer_aop_min, + inner_loan_max, + inner_loan_min, + inner_primary_mass_distr, + inner_mass_ratio_distr, + outer_mass_ratio_distr, + inner_semi_distr, + outer_semi_distr, + inner_ecc_distr, + outer_ecc_distr, + incl_distr, + inner_aop_distr, + outer_aop_distr, + inner_loan_distr, + ): + + if inner_primary_mass_distr == 5: + mass_convergence = False + while mass_convergence is False: + mass_convergence = self.generate_mass_and_semi_eggleton( + inner_primary_mass_max, + inner_primary_mass_min, + inner_secondary_mass_min, + outer_mass_min, + outer_mass_max, + inner_semi_max, + inner_semi_min, + outer_semi_max, + outer_semi_min, + ) + + # Does not use boolean inner/outer _semi_latus_rectum_ min/max + self.inner_ecc = self.generate_ecc_1d( + inner_ecc_max, inner_ecc_min, inner_ecc_distr, self.inner_secondary_mass + ) + self.outer_ecc = self.generate_ecc_1d( + outer_ecc_max, outer_ecc_min, outer_ecc_distr, self.outer_mass + ) + + else: + self.generate_mass( + inner_primary_mass_max, + inner_primary_mass_min, + inner_secondary_mass_max, + inner_secondary_mass_min, + outer_mass_min, + outer_mass_max, + inner_mass_ratio_max, + inner_mass_ratio_min, + outer_mass_ratio_max, + outer_mass_ratio_min, + inner_primary_mass_distr, + inner_mass_ratio_distr, + outer_mass_ratio_distr, + ) + + orbit_convergence = False + while orbit_convergence is False: + orbit_convergence = self.generate_semi_and_ecc( + inner_semi_max, + inner_semi_min, + outer_semi_max, + outer_semi_min, + inner_semi_distr, + outer_semi_distr, + inner_semi_latus_rectum_min, + outer_semi_latus_rectum_min, + inner_semi_latus_rectum_max, + outer_semi_latus_rectum_max, + inner_ecc_max, + inner_ecc_min, + outer_ecc_max, + outer_ecc_min, + inner_ecc_distr, + outer_ecc_distr, + self.inner_secondary_mass, + self.outer_mass, + ) + + self.generate_incl(incl_max, incl_min, incl_distr) + + self.generate_aop( + inner_aop_max, + inner_aop_min, + outer_aop_max, + outer_aop_min, + inner_aop_distr, + outer_aop_distr, + ) + + self.generate_loan(inner_loan_max, inner_loan_min, inner_loan_distr) + + # ------- + def generate_mass( + self, + inner_primary_mass_max, + inner_primary_mass_min, + inner_secondary_mass_max, + inner_secondary_mass_min, + outer_mass_min, + outer_mass_max, + inner_mass_ratio_max, + inner_mass_ratio_min, + outer_mass_ratio_max, + outer_mass_ratio_min, + inner_primary_mass_distr, + inner_mass_ratio_distr, + outer_mass_ratio_distr, + ): + if REPORT_TPS: + print("generate_mass") + + if inner_primary_mass_max == inner_primary_mass_min: + self.inner_primary_mass = inner_primary_mass_min + else: + if inner_primary_mass_distr == 1: # Scalo 1986 + self.inner_primary_mass = new_scalo_mass_distribution( + 1, inner_primary_mass_max + )[0] + while self.inner_primary_mass < inner_primary_mass_min: + self.inner_primary_mass = new_scalo_mass_distribution( + 1, inner_primary_mass_max + )[0] + elif inner_primary_mass_distr == 2: # Miller & Scale 1979 + self.inner_primary_mass = new_miller_scalo_mass_distribution( + 1, inner_primary_mass_max + )[0] + while self.inner_primary_mass < inner_primary_mass_min: + self.inner_primary_mass = new_miller_scalo_mass_distribution( + 1, inner_primary_mass_max + )[0] + elif inner_primary_mass_distr == 3: # Salpeter with slope 2.35 + self.inner_primary_mass = new_salpeter_mass_distribution( + 1, inner_primary_mass_min, inner_primary_mass_max + )[0] + elif inner_primary_mass_distr == 4: # Flat in log space + self.inner_primary_mass = new_flat_mass_distribution( + 1, inner_primary_mass_min, inner_primary_mass_max + )[0] + elif ( + inner_primary_mass_distr == 5 + ): # Eggleton 2009, 399, 1471, Salpeter-like with turnover at low masses + self.inner_primary_mass = eggleton_mass_distr( + inner_primary_mass_min, inner_primary_mass_max + ) + elif ( + inner_primary_mass_distr == 6 + ): # Salpeter with slope 2.3 -> Kroupa for M>0.5 + self.inner_primary_mass = powerlaw_distr( + inner_primary_mass_min, inner_primary_mass_max, -2.3 + ) + else: # Kroupa 2001 + self.inner_primary_mass = new_kroupa_mass_distribution( + 1, mass_min=inner_primary_mass_min, mass_max=inner_primary_mass_max + )[0] + + if inner_mass_ratio_max == inner_mass_ratio_min: + inner_mass_ratio = inner_mass_ratio_min + self.inner_secondary_mass = inner_mass_ratio * self.inner_primary_mass + else: + if inner_mass_ratio_distr == 1: # Kroupa 2001 + self.inner_secondary_mass = new_kroupa_mass_distribution( + 1, + mass_min=inner_secondary_mass_min, + mass_max=inner_secondary_mass_max, + )[0] + # self.inner_secondary_mass = new_kroupa_mass_distribution(1, mass_min=inner_secondary_mass_min, mass_max=inner_primary_mass_max)[0] + # self.inner_secondary_mass = new_kroupa_mass_distribution(1, mass_min=inner_secondary_mass_min, mass_max=inner_primary_mass)[0] + elif inner_mass_ratio_distr == 2: # Galicher et al 2016 + self.inner_secondary_mass = powerlaw_distr( + m_min=inner_secondary_mass_min, + m_max=inner_secondary_mass_max, + slope=-1.31, + ) + else: # flat distribution + inner_mass_ratio = flat_distr( + max( + inner_mass_ratio_min, + inner_secondary_mass_min / self.inner_primary_mass, + ), + min( + inner_mass_ratio_max, + inner_secondary_mass_max / self.inner_primary_mass, + ), + ) + self.inner_secondary_mass = inner_mass_ratio * self.inner_primary_mass + + if outer_mass_ratio_max == outer_mass_ratio_min: + outer_mass_ratio = outer_mass_ratio_min + self.outer_mass = outer_mass_ratio * ( + self.inner_primary_mass + self.inner_secondary_mass + ) + else: + if outer_mass_ratio_distr == 1: # Kroupa 2001 + self.outer_mass = new_kroupa_mass_distribution( + 1, mass_min=outer_mass_min, mass_max=outer_mass_max + )[0] + elif outer_mass_ratio_distr == 2: # Galicher et al 2016 + self.outer_mass = powerlaw_distr( + m_min=outer_mass_min, m_max=outer_mass_max, slope=-1.31 + ) + else: # flat distribution + inner_mass_tot = self.inner_primary_mass + self.inner_secondary_mass + outer_mass_ratio = flat_distr( + max(outer_mass_ratio_min, outer_mass_min / inner_mass_tot), + min(outer_mass_ratio_max, outer_mass_max / inner_mass_tot), + ) + self.outer_mass = outer_mass_ratio * inner_mass_tot + + def generate_semi_and_ecc( + self, + inner_semi_max_orig, + inner_semi_min_orig, + outer_semi_max_orig, + outer_semi_min_orig, + inner_semi_distr, + outer_semi_distr, + inner_semi_latus_rectum_min, + outer_semi_latus_rectum_min, + inner_semi_latus_rectum_max, + outer_semi_latus_rectum_max, + inner_ecc_max, + inner_ecc_min, + outer_ecc_max, + outer_ecc_min, + inner_ecc_distr, + outer_ecc_distr, + inner_secondary_mass, + outer_mass, + ): + if REPORT_TPS: + print("generate_semi_and_ecc") + + self.inner_ecc = self.generate_ecc_1d( + inner_ecc_max, inner_ecc_min, inner_ecc_distr, inner_secondary_mass + ) + self.outer_ecc = self.generate_ecc_1d( + outer_ecc_max, outer_ecc_min, outer_ecc_distr, outer_mass + ) + + inner_semi_min = inner_semi_min_orig + if inner_semi_latus_rectum_min: + inner_semi_min = inner_semi_min_orig / (1 - self.inner_ecc**2) + outer_semi_min = outer_semi_min_orig + if outer_semi_latus_rectum_min: + outer_semi_min = outer_semi_min_orig / (1 - self.outer_ecc**2) + + inner_semi_max = inner_semi_max_orig + if inner_semi_latus_rectum_max: + inner_semi_max = inner_semi_max_orig / (1 - self.inner_ecc**2) + outer_semi_max = outer_semi_max_orig + if outer_semi_latus_rectum_max: + outer_semi_max = outer_semi_max_orig / (1 - self.outer_ecc**2) + + if inner_semi_max == inner_semi_min: + self.inner_semi = inner_semi_min + else: + if inner_semi_distr == 1: # Constant + if REPORT_USER_WARNINGS_TPS: + print( + "TPS::generate_semi: unambiguous choice of constant semi-major axis" + ) + print( + "--A_min option to set the value of the semi-major axis in the inner binary" + ) + self.inner_semi = inner_semi_min + elif inner_semi_distr == 2: # Tokovinin Lognormal mu=10^5d, sigma=2.3 + self.inner_semi = 0.0 | units.RSun + while ( + self.inner_semi < inner_semi_min or self.inner_semi > inner_semi_max + ): + self.inner_ecc = self.generate_ecc_1d( + inner_ecc_max, + inner_ecc_min, + inner_ecc_distr, + inner_secondary_mass, + ) + inner_semi_min = inner_semi_min_orig + if inner_semi_latus_rectum_min: + inner_semi_min = inner_semi_min_orig / (1 - self.inner_ecc**2) + + logP = np.random.normal(5, 2.3, 1) + P = (10 ** logP[0]) | units.day + self.inner_semi = ( + (P / 2.0 / np.pi) ** 2 + * constants.G + * (self.inner_primary_mass + self.inner_secondary_mass) + ) ** (1.0 / 3.0) + if logP < -0.3 or logP > 10: # truncation of Gaussian wings + self.inner_semi = 0.0 | units.RSun + elif inner_semi_distr == 3: # Lognormal mu=10^3.5d, sigma=2.3 + self.inner_semi = 0.0 | units.RSun + while ( + self.inner_semi < inner_semi_min or self.inner_semi > inner_semi_max + ): + self.inner_ecc = self.generate_ecc_1d( + inner_ecc_max, + inner_ecc_min, + inner_ecc_distr, + inner_secondary_mass, + ) + inner_semi_min = inner_semi_min_orig + if inner_semi_latus_rectum_min: + inner_semi_min = inner_semi_min_orig / (1 - self.inner_ecc**2) + inner_semi_max = inner_semi_max_orig + if inner_semi_latus_rectum_max: + inner_semi_max = inner_semi_max_orig / (1 - self.inner_ecc**2) + + logP = np.random.normal(3.5, 2.3, 1) + P = (10 ** logP[0]) | units.day + self.inner_semi = ( + (P / 2.0 / np.pi) ** 2 + * constants.G + * (self.inner_primary_mass + self.inner_secondary_mass) + ) ** (1.0 / 3.0) + if logP < -0.3 or logP > 10: # truncation of Gaussian wings + self.inner_semi = 0.0 | units.RSun + elif ( + inner_semi_distr == 4 + ): # Rizzuto et al 2013, 436, 1694, Lognormal mu=10^0.95AU, sigma=1.35 + self.inner_semi = 0.0 | units.RSun + while ( + self.inner_semi < inner_semi_min or self.inner_semi > inner_semi_max + ): + self.inner_ecc = self.generate_ecc_1d( + inner_ecc_max, + inner_ecc_min, + inner_ecc_distr, + inner_secondary_mass, + ) + inner_semi_min = inner_semi_min_orig + if inner_semi_latus_rectum_min: + inner_semi_min = inner_semi_min_orig / (1 - self.inner_ecc**2) + inner_semi_max = inner_semi_max_orig + if inner_semi_latus_rectum_max: + inner_semi_max = inner_semi_max_orig / (1 - self.inner_ecc**2) + + logAU = np.random.normal(0.95, 1.35, 1) + self.inner_semi = (10 ** logAU[0]) | units.AU + if ( + self.inner_semi < 0.5 | units.RSun + or self.inner_semi > 5e8 | units.RSun + ): # truncation of Gaussian wings + self.inner_semi = 0.0 | units.RSun + + elif inner_semi_distr == 5: # Sana + self.inner_semi = 0.0 | units.RSun + # (logP)^-0.55 + while ( + self.inner_semi < inner_semi_min or self.inner_semi > inner_semi_max + ): + self.inner_ecc = self.generate_ecc_1d( + inner_ecc_max, + inner_ecc_min, + inner_ecc_distr, + inner_secondary_mass, + ) + inner_semi_min = inner_semi_min_orig + if inner_semi_latus_rectum_min: + inner_semi_min = inner_semi_min_orig / (1 - self.inner_ecc**2) + inner_semi_max = inner_semi_max_orig + if inner_semi_latus_rectum_max: + inner_semi_max = inner_semi_max_orig / (1 - self.inner_ecc**2) + + random_nr = flat_distr(0, 1) + logP_min = 0.15 + logP_max = 8.5 + c_s = logP_max**0.45 - logP_min**0.45 + logP = (random_nr * c_s + logP_min**0.45) ** (1.0 / 0.45) + P0 = 10**logP | units.day + M_inner = self.inner_primary_mass + self.inner_secondary_mass + self.inner_semi = ( + (P0 / 2.0 / np.pi) ** 2 * M_inner * constants.G + ) ** (1.0 / 3.0) + + elif inner_semi_distr == 6: # flat distr (uniform) + self.inner_semi = ( + flat_distr( + inner_semi_min.value_in(units.RSun), + inner_semi_max.value_in(units.RSun), + ) + | units.RSun + ) + elif inner_semi_distr == 7: # Galicher 2016: powerlaw, slope -0.61 + self.inner_semi = powerlaw_distr( + inner_semi_min, inner_semi_max, slope=-0.61 + ) + + else: # log flat distribution + maximal_semi = min(inner_semi_max, outer_semi_max) + if inner_semi_min > maximal_semi: # possible for extreme eccentricities + return False + self.inner_semi = ( + log_flat_distr( + inner_semi_min.value_in(units.RSun), + maximal_semi.value_in(units.RSun), + ) + | units.RSun + ) + + if outer_semi_max == outer_semi_min: + self.outer_semi = outer_semi_min + else: + if outer_semi_distr == 1: # Constant + if REPORT_USER_WARNINGS_TPS: + print( + "TPS::generate_semi: unambiguous choice of constant semi-major axis" + ) + print( + "--a_min option to set the value of the semi-major axis in the outer binary" + ) + self.outer_semi = outer_semi_min + elif outer_semi_distr == 2: # Tokovinin Lognormal mu=10^5.5d, sigma=2.3 + self.outer_semi = 0.0 | units.RSun + while ( + self.outer_semi < outer_semi_min or self.outer_semi > outer_semi_max + ): + self.outer_ecc = self.generate_ecc_1d( + outer_ecc_max, outer_ecc_min, outer_ecc_distr, outer_mass + ) + outer_semi_min = outer_semi_min_orig + if outer_semi_latus_rectum_min: + outer_semi_min = outer_semi_min_orig / (1 - self.outer_ecc**2) + outer_semi_max = outer_semi_max_orig + if outer_semi_latus_rectum_max: + outer_semi_max = outer_semi_max_orig / (1 - self.outer_ecc**2) + + logP_out = np.random.normal(5, 2.3, 1) + P_out = (10 ** logP_out[0]) | units.day + self.outer_semi = ( + (P_out / 2.0 / np.pi) ** 2 + * constants.G + * ( + self.inner_primary_mass + + self.inner_secondary_mass + + self.outer_mass + ) + ) ** (1.0 / 3.0) + if logP_out < -0.3 or logP_out > 10: # truncation of Gaussian wings + self.outer_semi = 0.0 | units.RSun + if logP_out < 3: # no bifurcation + self.outer_semi = 0.0 | units.RSun + + elif outer_semi_distr == 3: # Lognormal mu=10^3.5d, sigma=2.3 + self.outer_semi = 0.0 | units.RSun + while ( + self.outer_semi < outer_semi_min or self.outer_semi > outer_semi_max + ): + self.outer_ecc = self.generate_ecc_1d( + outer_ecc_max, outer_ecc_min, outer_ecc_distr, outer_mass + ) + outer_semi_min = outer_semi_min_orig + if outer_semi_latus_rectum_min: + outer_semi_min = outer_semi_min_orig / (1 - self.outer_ecc**2) + outer_semi_max = outer_semi_max_orig + if outer_semi_latus_rectum_max: + outer_semi_max = outer_semi_max_orig / (1 - self.outer_ecc**2) + + logP_out = np.random.normal(5, 2.3, 1) + P_out = (10 ** logP_out[0]) | units.day + self.outer_semi = ( + (P_out / 2.0 / np.pi) ** 2 + * constants.G + * ( + self.inner_primary_mass + + self.inner_secondary_mass + + self.outer_mass + ) + ) ** (1.0 / 3.0) + if logP_out < -0.3 or logP_out > 10: # truncation of Gaussian wings + self.outer_semi = 0.0 | units.RSun + if logP_out < 3: # no bifurcation + self.outer_semi = 0.0 | units.RSun + + elif ( + outer_semi_distr == 4 + ): # Rizzuto et al 2013, 436, 1694, Lognormal mu=10^0.95AU, sigma=1.35 + self.outer_semi = 0.0 | units.RSun + while ( + self.outer_semi < outer_semi_min or self.outer_semi > outer_semi_max + ): + self.outer_ecc = self.generate_ecc_1d( + outer_ecc_max, outer_ecc_min, outer_ecc_distr, outer_mass + ) + outer_semi_min = outer_semi_min_orig + if outer_semi_latus_rectum_min: + outer_semi_min = outer_semi_min_orig / (1 - self.outer_ecc**2) + outer_semi_max = outer_semi_max_orig + if outer_semi_latus_rectum_max: + outer_semi_max = outer_semi_max_orig / (1 - self.outer_ecc**2) + + logAU = np.random.normal(0.95, 1.35, 1) + self.outer_semi = (10 ** logAU[0]) | units.AU + if ( + self.outer_semi < 0.5 | units.RSun + or self.outer_semi > 5e8 | units.RSun + ): # truncation of Gaussian wings + self.outer_semi = 0.0 | units.RSun + + elif outer_semi_distr == 5: # Sana + self.outer_semi = 0.0 | units.RSun + # (logP)^-0.55 + while ( + self.outer_semi < outer_semi_min or self.outer_semi > outer_semi_max + ): + self.outer_ecc = self.generate_ecc_1d( + outer_ecc_max, outer_ecc_min, outer_ecc_distr, outer_mass + ) + outer_semi_min = outer_semi_min_orig + if outer_semi_latus_rectum_min: + outer_semi_min = outer_semi_min_orig / (1 - self.outer_ecc**2) + outer_semi_max = outer_semi_max_orig + if outer_semi_latus_rectum_max: + outer_semi_max = outer_semi_max_orig / (1 - self.outer_ecc**2) + + random_nr = flat_distr(0, 1) + logP_min = 0.15 + logP_max = 8.5 + c_s = logP_max**0.45 - logP_min**0.45 + logP = (random_nr * c_s + logP_min**0.45) ** (1.0 / 0.45) + P0 = 10**logP | units.day + mass_tot = ( + self.inner_primary_mass + + self.inner_secondary_mass + + self.outer_mass + ) + self.outer_semi = ( + (P0 / 2.0 / np.pi) ** 2 * mass_tot * constants.G + ) ** (1.0 / 3.0) + + elif outer_semi_distr == 6: # flat distr (uniform) + self.outer_semi = ( + flat_distr( + outer_semi_min.value_in(units.RSun), + outer_semi_max.value_in(units.RSun), + ) + | units.RSun + ) + elif outer_semi_distr == 7: # Galicher 2016: powerlaw, slope -0.61 + self.outer_semi = powerlaw_distr( + outer_semi_min, outer_semi_max, slope=-0.61 + ) + + else: # log flat distribution + if ( + outer_semi_min > outer_semi_max + ): # possible for extreme eccentricities + return False + self.outer_semi = ( + log_flat_distr( + outer_semi_min.value_in(units.RSun), + outer_semi_max.value_in(units.RSun), + ) + | units.RSun + ) + + if ( + inner_semi_distr == outer_semi_distr + and inner_semi_min_orig == outer_semi_min_orig + and inner_semi_max == outer_semi_max + and self.outer_semi < self.inner_semi + and inner_ecc_distr == outer_ecc_distr + and inner_ecc_min == outer_ecc_min + and inner_ecc_max == outer_ecc_max + ): + swap = self.outer_semi + self.outer_semi = self.inner_semi + self.inner_semi = swap + swap = self.outer_ecc + self.outer_ecc = self.inner_ecc + self.inner_ecc = swap + return True + elif self.outer_semi < self.inner_semi: + return False + return True + + def generate_ecc_1d(self, ecc_max, ecc_min, ecc_distr, mass): + if REPORT_TPS: + print("generate_ecc_1d") + + if ecc_max == ecc_min: + return ecc_min + else: + if ecc_distr == 1: # Constant + if REPORT_USER_WARNINGS_TPS: + print( + "TPS::generate_ecc: unambiguous choice of constant eccentricity" + ) + print( + "--E_min and --e_min option to set the value of the eccentricity" + ) + return ecc_min + elif ecc_distr == 2: # Sana + return powerlaw_distr(ecc_min + precision, ecc_max, -0.45) + elif ecc_distr == 3: # flat distribution + return flat_distr(ecc_min, ecc_max) + elif ecc_distr == 4: # Powerlaw + return powerlaw_distr(ecc_min + precision, ecc_max, 0.5) + elif ecc_distr == 5: # Beta distribution + return beta_distr_SSOs(ecc_min, ecc_max, mass) + else: # Thermal distribution + return np.sqrt(np.random.uniform(ecc_min * ecc_min, ecc_max * ecc_max)) + + def generate_incl(self, incl_max, incl_min, incl_distr): + if REPORT_TPS: + print("generate_incl") + if incl_max == incl_min: + self.incl = incl_min + else: + if incl_distr == 1: # Constant + if REPORT_USER_WARNINGS_TPS: + print( + "TPS::generate_incl: unambiguous choice of constant relative inclination" + ) + print( + "--i_min option to set the value of the relative inclination in the inner triple" + ) + self.incl = incl_min + else: # Circular uniform distribution + self.incl = np.arccos( + np.random.uniform(np.cos(incl_min), np.cos(incl_max)) + ) + + def generate_aop( + self, + inner_aop_max, + inner_aop_min, + outer_aop_max, + outer_aop_min, + inner_aop_distr, + outer_aop_distr, + ): + if REPORT_TPS: + print("generate_aop") + + if inner_aop_max == inner_aop_min: + self.inner_aop = inner_aop_min + else: + if inner_aop_distr == 1: # Constant + if REPORT_USER_WARNINGS_TPS: + print( + "TPS::generate_aop: unambiguous choice of constant argument of pericenter" + ) + print( + "--G_min option to set the value of the argument of pericenter of the inner binary" + ) + self.inner_aop = inner_aop_min + else: # Uniform distribution + self.inner_aop = np.random.uniform(inner_aop_min, inner_aop_max) + + if outer_aop_max == outer_aop_min: + self.outer_aop = outer_aop_min + else: + if outer_aop_distr == 1: # Constant + if REPORT_USER_WARNINGS_TPS: + print( + "TPS::generate_aop: unambiguous choice of constant argument of pericenter" + ) + print( + "--g_min option to set the value of the argument of pericenter of the outer binary" + ) + self.outer_aop = outer_aop_min + else: # Uniform distribution + self.outer_aop = np.random.uniform(outer_aop_min, outer_aop_max) + + def generate_loan(self, inner_loan_max, inner_loan_min, inner_loan_distr): + if REPORT_TPS: + print("generate_loan") + + if inner_loan_max == inner_loan_min: + self.inner_loan = inner_loan_min + else: + if inner_loan_distr == 0: # Circular uniform distribution + self.inner_loan = np.arccos( + np.random.uniform(np.cos(inner_loan_min), np.cos(inner_loan_max)) + ) + else: # Constant + if REPORT_USER_WARNINGS_TPS: + print( + "TPS::generate_loan: unambiguous choice of constant longitude of ascending nodes" + ) + print( + "--O_min option to set the value of the argument of pericenter of the inner binary" + ) + self.inner_loan = inner_loan_min + + # ------- + + # Eggleton 2009, 399, 1471 + def generate_mass_and_semi_eggleton( + self, + inner_primary_mass_max, + inner_primary_mass_min, + inner_secondary_mass_min, + outer_mass_min, + outer_mass_max, + inner_semi_max, + inner_semi_min, + outer_semi_max, + outer_semi_min, + ): + if REPORT_TPS: + print("generate_mass_and_semi_eggleton") + U0_mass = [0.0, 0.01, 0.09, 0.32, 1.0, 3.2, 11, 32, np.inf] # solar mass + U0_l0 = [0.40, 0.40, 0.40, 0.40, 0.50, 0.75, 0.88, 0.94, 0.96] + U0_l1 = [0.18, 0.18, 0.18, 0.18, 0.18, 0.18, 0.20, 0.60, 0.80] + U0_l2 = [0.00, 0.00, 0.00, 0.00, 0.00, 0.20, 0.33, 0.82, 0.90] + U0_l3 = [0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00] + + Mt = eggleton_mass_distr(min_mass, absolute_max_mass) + U = np.random.uniform(0, 1) + f_l0 = interp1d(U0_mass, U0_l0) + U0 = f_l0(Mt.value_in(units.MSun)) # messy, but otherwise cluster crashes + + while U >= U0: + U = np.random.uniform(0, 1) + f_l0 = interp1d(U0_mass, U0_l0) + U0 = f_l0(Mt.value_in(units.MSun)) + + if U < U0: + V = np.random.uniform(0, 1) + P0 = 1.0e5 * V**2 / (1 - V) ** 2.5 | units.day + while P0 > 1e10 | units.day: + V = np.random.uniform(0, 1) + P0 = 1.0e5 * V**2 / (1 - V) ** 2.5 | units.day + + x_p = np.random.uniform(0, 1) + if P0 > 25 | units.day or x_p > 0.25: + Q0 = ((U0 - U) / U0) ** 0.8 + else: + Q0 = 0.9 + 0.09 * (U0 - U) / U0 + if Q0 < 0.01: + Q0 = 0.01 + + M1 = Mt / (1 + Q0) + M2 = M1 * Q0 + f_l1 = interp1d(U0_mass, U0_l1) + + U1 = np.random.uniform(0, 1) + U1_0 = f_l1(M1.value_in(units.MSun)) + U2 = np.random.uniform(0, 1) + U2_0 = f_l1(M2.value_in(units.MSun)) + + # M1 bifurcutas and M2 not + if U1 < U1_0 and U2 >= U2_0: + M_bin = M1 + U_bin = U1 + U0_bin = U1_0 + M_comp = M2 + # M2 bifurcutas and M1 not + elif U1 >= U1_0 and U2 < U2_0: + M_bin = M2 + U_bin = U2 + U0_bin = U2_0 + M_comp = M1 + else: # two bifurcations -> higher order multiplicity + # print(U1, U1_0, U2, U2_0) + # exit(1) + return False + + V_bin = np.random.uniform(0, 1) + P_bin = 0.2 * P0 * 10 ** (-5 * V_bin) + + x_pb = np.random.uniform(0, 1) + if P_bin > 25 | units.day or x_pb > 0.25: + Q_bin = ((U0_bin - U_bin) / U0_bin) ** 0.8 + else: + Q_bin = 0.9 + 0.09 * (U0_bin - U_bin) / U0_bin + if Q_bin < 0.01: + Q_bin = 0.01 + + M1_bin = M_bin / (1 + Q_bin) + M2_bin = M1_bin * Q_bin + + self.inner_primary_mass = M1_bin + self.inner_secondary_mass = M2_bin + self.outer_mass = M_comp + + self.inner_semi = ((P_bin / 2.0 / np.pi) ** 2 * M_bin * constants.G) ** ( + 1.0 / 3.0 + ) + self.outer_semi = ((P0 / 2.0 / np.pi) ** 2 * Mt * constants.G) ** ( + 1.0 / 3.0 + ) + + if ( + self.inner_primary_mass < inner_primary_mass_min + or self.inner_primary_mass > inner_primary_mass_max + ): + return False + if self.inner_secondary_mass < inner_secondary_mass_min: + return False + if self.outer_mass < outer_mass_min or self.outer_mass > outer_mass_max: + return False + if self.inner_semi < inner_semi_min or self.inner_semi > inner_semi_max: + return False + if self.outer_semi < outer_semi_min or self.outer_semi > outer_semi_max: + return False + + return True + else: + sys.exit("not possible in eggleton distribution") + + # ------- + + # ------- + def print_triple(self): + print("\nTriple - ") + print( + "m =", self.inner_primary_mass, self.inner_secondary_mass, self.outer_mass + ) + print("a =", self.inner_semi, self.outer_semi) + print("e =", self.inner_ecc, self.outer_ecc) + print("i =", self.incl) + print("g =", self.inner_aop, self.outer_aop) + print("o =", self.inner_loan, self.inner_loan - np.pi) + def print_triple_short(self): - print( self.inner_primary_mass.value_in(units.MSun), self.inner_secondary_mass.value_in(units.MSun), self.outer_mass.value_in(units.MSun), end=" ") - print( self.inner_semi.value_in(units.RSun), self.outer_semi.value_in(units.RSun), end=" ") - print( self.inner_ecc, self.outer_ecc, end=" ") - print( self.incl, end=" ") - print( self.inner_aop, self.outer_aop, end=" ") - print( self.inner_loan, self.inner_loan -np.pi, end=" ") - -#------- - -#------- - -def evolve_model(inner_primary_mass_max, inner_primary_mass_min,inner_secondary_mass_max, - inner_secondary_mass_min,outer_mass_min,outer_mass_max, - inner_mass_ratio_max, inner_mass_ratio_min, - outer_mass_ratio_max, outer_mass_ratio_min, - inner_semi_max, inner_semi_min, outer_semi_max, outer_semi_min, - inner_semi_latus_rectum_min, outer_semi_latus_rectum_min, - inner_semi_latus_rectum_max, outer_semi_latus_rectum_max, - inner_ecc_max, inner_ecc_min, outer_ecc_max, outer_ecc_min, - incl_max, incl_min, - inner_aop_max, inner_aop_min, outer_aop_max, outer_aop_min, - inner_loan_max, inner_loan_min, - inner_primary_mass_distr, inner_mass_ratio_distr, outer_mass_ratio_distr, - inner_semi_distr, outer_semi_distr, inner_ecc_distr, outer_ecc_distr, incl_distr, - inner_aop_distr, outer_aop_distr, inner_loan_distr, - metallicity, tend, number, initial_number, seed, - stop_at_mass_transfer, stop_at_init_mass_transfer, stop_at_outer_mass_transfer, - stop_at_stable_mass_transfer, stop_at_eccentric_stable_mass_transfer, - stop_at_unstable_mass_transfer, stop_at_eccentric_unstable_mass_transfer, which_common_envelope, - stop_at_no_CHE, include_CHE, include_circ, - stop_at_merger, stop_at_disintegrated, stop_at_inner_collision, stop_at_outer_collision, - stop_at_dynamical_instability, stop_at_semisecular_regime, - stop_at_SN, SN_kick_distr, impulse_kick_for_black_holes,fallback_kick_for_black_holes, - stop_at_CPU_time, max_CPU_time, file_name, file_type, dir_plots): - - - i_n = 0 - nr_ids = 0 #number of systems that is dynamically unstable at initialisation - nr_iss = 0 #number of systems that is in the semisecular regime at initialisation - nr_imt = 0 #number of systems that has mass transfer at initialisation - nr_cp = 0 #number of systems with incorrect parameters - while i_n < number: - triple_system = Generate_initial_triple(inner_primary_mass_max, inner_primary_mass_min, - inner_secondary_mass_max, inner_secondary_mass_min, outer_mass_min, outer_mass_max, - inner_mass_ratio_max, inner_mass_ratio_min, - outer_mass_ratio_max, outer_mass_ratio_min, - inner_semi_max, inner_semi_min, outer_semi_max, outer_semi_min, - inner_semi_latus_rectum_min, outer_semi_latus_rectum_min, - inner_semi_latus_rectum_max, outer_semi_latus_rectum_max, - inner_ecc_max, inner_ecc_min, outer_ecc_max, outer_ecc_min, - incl_max, incl_min, - inner_aop_max, inner_aop_min, outer_aop_max, outer_aop_min, - inner_loan_max, inner_loan_min, - inner_primary_mass_distr, inner_mass_ratio_distr, outer_mass_ratio_distr, - inner_semi_distr, outer_semi_distr, inner_ecc_distr, outer_ecc_distr, incl_distr, - inner_aop_distr, outer_aop_distr, inner_loan_distr) - - if REPORT_TPS: - triple_system.print_triple() - - if (min_mass > triple_system.inner_primary_mass): - if REPORT_TPS: - print('non-star primary included: ', triple_system.inner_primary_mass) - continue - - if EXCLUDE_SSO: - if (min_mass > triple_system.inner_secondary_mass) or (min_mass > triple_system.outer_mass): - if REPORT_TPS: - print('non-star secondary & tertiary included: ', triple_system.inner_secondary_mass, triple_system.outer_mass) - continue - - number_of_system = initial_number + i_n - if REPORT_TPS: - print('number of system = ', number_of_system) - - #do not use main_developer in TPS.py - #memory of SeBa needs to be cleaned, in particular SeBa time - #otherwise use evolve_for for particles indivicually -> many calls - tr = TRES.main(inner_primary_mass = triple_system.inner_primary_mass, - inner_secondary_mass = triple_system.inner_secondary_mass, - outer_mass = triple_system.outer_mass, - inner_semimajor_axis = triple_system.inner_semi, - outer_semimajor_axis = triple_system.outer_semi, - inner_eccentricity = triple_system.inner_ecc, - outer_eccentricity = triple_system.outer_ecc, - relative_inclination = triple_system.incl, metallicity = metallicity, tend = tend, number = number_of_system, - stop_at_mass_transfer = stop_at_mass_transfer, stop_at_init_mass_transfer = stop_at_init_mass_transfer, - stop_at_outer_mass_transfer = stop_at_outer_mass_transfer, - stop_at_stable_mass_transfer = stop_at_stable_mass_transfer, - stop_at_eccentric_stable_mass_transfer = stop_at_eccentric_stable_mass_transfer, - stop_at_unstable_mass_transfer = stop_at_unstable_mass_transfer, - stop_at_eccentric_unstable_mass_transfer = stop_at_eccentric_unstable_mass_transfer, - stop_at_merger = stop_at_merger, stop_at_disintegrated = stop_at_disintegrated, - stop_at_inner_collision = stop_at_inner_collision, stop_at_outer_collision = stop_at_outer_collision, - stop_at_dynamical_instability = stop_at_dynamical_instability, - stop_at_semisecular_regime = stop_at_semisecular_regime, - stop_at_SN = stop_at_SN, SN_kick_distr = SN_kick_distr, - impulse_kick_for_black_holes = impulse_kick_for_black_holes, - fallback_kick_for_black_holes = fallback_kick_for_black_holes, - which_common_envelope = which_common_envelope, - stop_at_CPU_time = stop_at_CPU_time, - max_CPU_time = max_CPU_time, file_name = file_name, file_type = file_type, dir_plots = dir_plots, secular_code = secular_code) - + print( + self.inner_primary_mass.value_in(units.MSun), + self.inner_secondary_mass.value_in(units.MSun), + self.outer_mass.value_in(units.MSun), + end=" ", + ) + print( + self.inner_semi.value_in(units.RSun), + self.outer_semi.value_in(units.RSun), + end=" ", + ) + print(self.inner_ecc, self.outer_ecc, end=" ") + print(self.incl, end=" ") + print(self.inner_aop, self.outer_aop, end=" ") + print(self.inner_loan, self.inner_loan - np.pi, end=" ") + + +# ------- + +# ------- + + +def evolve_model( + inner_primary_mass_max, + inner_primary_mass_min, + inner_secondary_mass_max, + inner_secondary_mass_min, + outer_mass_min, + outer_mass_max, + inner_mass_ratio_max, + inner_mass_ratio_min, + outer_mass_ratio_max, + outer_mass_ratio_min, + inner_semi_max, + inner_semi_min, + outer_semi_max, + outer_semi_min, + inner_semi_latus_rectum_min, + outer_semi_latus_rectum_min, + inner_semi_latus_rectum_max, + outer_semi_latus_rectum_max, + inner_ecc_max, + inner_ecc_min, + outer_ecc_max, + outer_ecc_min, + incl_max, + incl_min, + inner_aop_max, + inner_aop_min, + outer_aop_max, + outer_aop_min, + inner_loan_max, + inner_loan_min, + inner_primary_mass_distr, + inner_mass_ratio_distr, + outer_mass_ratio_distr, + inner_semi_distr, + outer_semi_distr, + inner_ecc_distr, + outer_ecc_distr, + incl_distr, + inner_aop_distr, + outer_aop_distr, + inner_loan_distr, + metallicity, + tend, + number, + initial_number, + seed, + stop_at_mass_transfer, + stop_at_init_mass_transfer, + stop_at_outer_mass_transfer, + stop_at_stable_mass_transfer, + stop_at_eccentric_stable_mass_transfer, + stop_at_unstable_mass_transfer, + stop_at_eccentric_unstable_mass_transfer, + which_common_envelope, + stop_at_no_CHE, + include_CHE, + include_circ, + stop_at_merger, + stop_at_disintegrated, + stop_at_inner_collision, + stop_at_outer_collision, + stop_at_dynamical_instability, + stop_at_semisecular_regime, + stop_at_SN, + SN_kick_distr, + impulse_kick_for_black_holes, + fallback_kick_for_black_holes, + stop_at_CPU_time, + max_CPU_time, + file_name, + file_type, + dir_plots, +): + + i_n = 0 + nr_ids = 0 # number of systems that is dynamically unstable at initialisation + nr_iss = 0 # number of systems that is in the semisecular regime at initialisation + nr_imt = 0 # number of systems that has mass transfer at initialisation + nr_cp = 0 # number of systems with incorrect parameters + while i_n < number: + triple_system = Generate_initial_triple( + inner_primary_mass_max, + inner_primary_mass_min, + inner_secondary_mass_max, + inner_secondary_mass_min, + outer_mass_min, + outer_mass_max, + inner_mass_ratio_max, + inner_mass_ratio_min, + outer_mass_ratio_max, + outer_mass_ratio_min, + inner_semi_max, + inner_semi_min, + outer_semi_max, + outer_semi_min, + inner_semi_latus_rectum_min, + outer_semi_latus_rectum_min, + inner_semi_latus_rectum_max, + outer_semi_latus_rectum_max, + inner_ecc_max, + inner_ecc_min, + outer_ecc_max, + outer_ecc_min, + incl_max, + incl_min, + inner_aop_max, + inner_aop_min, + outer_aop_max, + outer_aop_min, + inner_loan_max, + inner_loan_min, + inner_primary_mass_distr, + inner_mass_ratio_distr, + outer_mass_ratio_distr, + inner_semi_distr, + outer_semi_distr, + inner_ecc_distr, + outer_ecc_distr, + incl_distr, + inner_aop_distr, + outer_aop_distr, + inner_loan_distr, + ) + + if REPORT_TPS: + triple_system.print_triple() + + if min_mass > triple_system.inner_primary_mass: + if REPORT_TPS: + print("non-star primary included: ", triple_system.inner_primary_mass) + continue + + if EXCLUDE_SSO: + if (min_mass > triple_system.inner_secondary_mass) or ( + min_mass > triple_system.outer_mass + ): + if REPORT_TPS: + print( + "non-star secondary & tertiary included: ", + triple_system.inner_secondary_mass, + triple_system.outer_mass, + ) + continue + + number_of_system = initial_number + i_n + if REPORT_TPS: + print("number of system = ", number_of_system) + + # do not use main_developer in TPS.py + # memory of SeBa needs to be cleaned, in particular SeBa time + # otherwise use evolve_for for particles indivicually -> many calls + tr = TRES.main( + inner_primary_mass=triple_system.inner_primary_mass, + inner_secondary_mass=triple_system.inner_secondary_mass, + outer_mass=triple_system.outer_mass, + inner_semimajor_axis=triple_system.inner_semi, + outer_semimajor_axis=triple_system.outer_semi, + inner_eccentricity=triple_system.inner_ecc, + outer_eccentricity=triple_system.outer_ecc, + relative_inclination=triple_system.incl, + metallicity=metallicity, + tend=tend, + number=number_of_system, + stop_at_mass_transfer=stop_at_mass_transfer, + stop_at_init_mass_transfer=stop_at_init_mass_transfer, + stop_at_outer_mass_transfer=stop_at_outer_mass_transfer, + stop_at_stable_mass_transfer=stop_at_stable_mass_transfer, + stop_at_eccentric_stable_mass_transfer=stop_at_eccentric_stable_mass_transfer, + stop_at_unstable_mass_transfer=stop_at_unstable_mass_transfer, + stop_at_eccentric_unstable_mass_transfer=stop_at_eccentric_unstable_mass_transfer, + stop_at_merger=stop_at_merger, + stop_at_disintegrated=stop_at_disintegrated, + stop_at_inner_collision=stop_at_inner_collision, + stop_at_outer_collision=stop_at_outer_collision, + stop_at_dynamical_instability=stop_at_dynamical_instability, + stop_at_semisecular_regime=stop_at_semisecular_regime, + stop_at_SN=stop_at_SN, + SN_kick_distr=SN_kick_distr, + impulse_kick_for_black_holes=impulse_kick_for_black_holes, + fallback_kick_for_black_holes=fallback_kick_for_black_holes, + which_common_envelope=which_common_envelope, + stop_at_CPU_time=stop_at_CPU_time, + max_CPU_time=max_CPU_time, + file_name=file_name, + file_type=file_type, + dir_plots=dir_plots, + secular_code=secular_code, + ) + if tr.correct_params == False: - if REPORT_TPS: - print('Incorrect parameters') - nr_cp += 1 - elif tr.semisecular_regime_at_initialisation == True: - nr_iss +=1 - elif tr.dynamical_instability_at_initialisation == True: - nr_ids +=1 - elif tr.mass_transfer_at_initialisation == True: - if tr.has_tertiary_donor(): - nr_imt +=1 - elif include_CHE: - nr_imt +=1 + if REPORT_TPS: + print("Incorrect parameters") + nr_cp += 1 + elif tr.semisecular_regime_at_initialisation == True: + nr_iss += 1 + elif tr.dynamical_instability_at_initialisation == True: + nr_ids += 1 + elif tr.mass_transfer_at_initialisation == True: + if tr.has_tertiary_donor(): + nr_imt += 1 + elif include_CHE: + nr_imt += 1 # todo reset so that no olof - else: - nr_imt += 1 - + else: + nr_imt += 1 + if include_circ: i_ecc = 0 max_nr_tries_ecc = 10 - while(i_ecc < max_nr_tries_ecc and tr.mass_transfer_at_initialisation): + while ( + i_ecc < max_nr_tries_ecc and tr.mass_transfer_at_initialisation + ): i_ecc += 1 - new_ecc = triple_system.generate_ecc_1d(triple_system.inner_ecc, inner_ecc_min, inner_ecc_distr, triple_system.inner_secondary_mass) - #resetting semi-major axis creates too many short orbit systems - for now only eccentricity is reset -# tr.triple.child2.semimajor_axis *= (1- tr.triple.child2.eccentricity**2)/(1-new_ecc**2) -# triple_system.inner_semi = tr.triple.child2.semimajor_axis + new_ecc = triple_system.generate_ecc_1d( + triple_system.inner_ecc, + inner_ecc_min, + inner_ecc_distr, + triple_system.inner_secondary_mass, + ) + # resetting semi-major axis creates too many short orbit systems - for now only eccentricity is reset + # tr.triple.child2.semimajor_axis *= (1- tr.triple.child2.eccentricity**2)/(1-new_ecc**2) + # triple_system.inner_semi = tr.triple.child2.semimajor_axis triple_system.inner_ecc = new_ecc tr.triple.child2.eccentricity = new_ecc tr.check_RLOF() if not tr.has_donor(): - i_ecc = max_nr_tries_ecc+1 - i_n += 1 + i_ecc = max_nr_tries_ecc + 1 + i_n += 1 nr_imt -= 1 - tr = TRES.main(inner_primary_mass = triple_system.inner_primary_mass, - inner_secondary_mass = triple_system.inner_secondary_mass, - outer_mass = triple_system.outer_mass, - inner_semimajor_axis = triple_system.inner_semi, - outer_semimajor_axis = triple_system.outer_semi, - inner_eccentricity = triple_system.inner_ecc, - outer_eccentricity = triple_system.outer_ecc, - relative_inclination = triple_system.incl, metallicity = metallicity, tend = tend, number = number_of_system, - stop_at_mass_transfer = stop_at_mass_transfer, stop_at_init_mass_transfer = stop_at_init_mass_transfer, - stop_at_outer_mass_transfer = stop_at_outer_mass_transfer, - stop_at_stable_mass_transfer = stop_at_stable_mass_transfer, - stop_at_eccentric_stable_mass_transfer = stop_at_eccentric_stable_mass_transfer, - stop_at_unstable_mass_transfer = stop_at_unstable_mass_transfer, - stop_at_eccentric_unstable_mass_transfer = stop_at_eccentric_unstable_mass_transfer, - stop_at_merger = stop_at_merger, stop_at_disintegrated = stop_at_disintegrated, - stop_at_inner_collision = stop_at_inner_collision, stop_at_outer_collision = stop_at_outer_collision, - stop_at_dynamical_instability = stop_at_dynamical_instability, - stop_at_semisecular_regime = stop_at_semisecular_regime, - stop_at_SN = stop_at_SN, SN_kick_distr = SN_kick_distr, - impulse_kick_for_black_holes = impulse_kick_for_black_holes, - fallback_kick_for_black_holes = fallback_kick_for_black_holes, - which_common_envelope = which_common_envelope, - stop_at_CPU_time = stop_at_CPU_time, - max_CPU_time = max_CPU_time, file_name = file_name, file_type = file_type, dir_plots = dir_plots, secular_code = secular_code) - - else: - i_n += 1 - - del tr - - if REPORT_TPS: - print(number, i_n, nr_iss, nr_ids, nr_imt, nr_cp) + tr = TRES.main( + inner_primary_mass=triple_system.inner_primary_mass, + inner_secondary_mass=triple_system.inner_secondary_mass, + outer_mass=triple_system.outer_mass, + inner_semimajor_axis=triple_system.inner_semi, + outer_semimajor_axis=triple_system.outer_semi, + inner_eccentricity=triple_system.inner_ecc, + outer_eccentricity=triple_system.outer_ecc, + relative_inclination=triple_system.incl, + metallicity=metallicity, + tend=tend, + number=number_of_system, + stop_at_mass_transfer=stop_at_mass_transfer, + stop_at_init_mass_transfer=stop_at_init_mass_transfer, + stop_at_outer_mass_transfer=stop_at_outer_mass_transfer, + stop_at_stable_mass_transfer=stop_at_stable_mass_transfer, + stop_at_eccentric_stable_mass_transfer=stop_at_eccentric_stable_mass_transfer, + stop_at_unstable_mass_transfer=stop_at_unstable_mass_transfer, + stop_at_eccentric_unstable_mass_transfer=stop_at_eccentric_unstable_mass_transfer, + stop_at_merger=stop_at_merger, + stop_at_disintegrated=stop_at_disintegrated, + stop_at_inner_collision=stop_at_inner_collision, + stop_at_outer_collision=stop_at_outer_collision, + stop_at_dynamical_instability=stop_at_dynamical_instability, + stop_at_semisecular_regime=stop_at_semisecular_regime, + stop_at_SN=stop_at_SN, + SN_kick_distr=SN_kick_distr, + impulse_kick_for_black_holes=impulse_kick_for_black_holes, + fallback_kick_for_black_holes=fallback_kick_for_black_holes, + which_common_envelope=which_common_envelope, + stop_at_CPU_time=stop_at_CPU_time, + max_CPU_time=max_CPU_time, + file_name=file_name, + file_type=file_type, + dir_plots=dir_plots, + secular_code=secular_code, + ) + + else: + i_n += 1 + + del tr + + if REPORT_TPS: + print(number, i_n, nr_iss, nr_ids, nr_imt, nr_cp) secular_code.stop() - - -def print_distr(inner_primary_mass_max, inner_primary_mass_min, - inner_secondary_mass_max, inner_secondary_mass_min, outer_mass_min, outer_mass_max, - inner_mass_ratio_max, inner_mass_ratio_min, - outer_mass_ratio_max, outer_mass_ratio_min, - inner_semi_max, inner_semi_min, outer_semi_max, outer_semi_min, - inner_semi_latus_rectum_min, outer_semi_latus_rectum_min, - inner_semi_latus_rectum_max, outer_semi_latus_rectum_max, - inner_ecc_max, inner_ecc_min, outer_ecc_max, outer_ecc_min, - incl_max, incl_min, - inner_aop_max, inner_aop_min, outer_aop_max, outer_aop_min, - inner_loan_max, inner_loan_min, - inner_primary_mass_distr, inner_mass_ratio_distr, outer_mass_ratio_distr, - inner_semi_distr, outer_semi_distr, inner_ecc_distr, outer_ecc_distr, incl_distr, - inner_aop_distr, outer_aop_distr, inner_loan_distr, - metallicity, tend, number, initial_number, seed, - stop_at_mass_transfer, stop_at_init_mass_transfer, stop_at_outer_mass_transfer, - stop_at_stable_mass_transfer, stop_at_eccentric_stable_mass_transfer, - stop_at_unstable_mass_transfer, stop_at_eccentric_unstable_mass_transfer, which_common_envelope, - stop_at_no_CHE, include_CHE, include_circ, - stop_at_merger, stop_at_disintegrated, stop_at_inner_collision, stop_at_outer_collision, - stop_at_dynamical_instability, stop_at_semisecular_regime, - stop_at_SN, SN_kick_distr, impulse_kick_for_black_holes,fallback_kick_for_black_holes, - stop_at_CPU_time, max_CPU_time, file_name, file_type, dir_plots): - - print('Based on the following distributions:') - print('Primary mass: \t\t', inner_primary_mass_distr, ' ',lib_inner_primary_mass_distr[inner_primary_mass_distr] ) - print('Inner mass ratio: \t', inner_mass_ratio_distr, ' ',lib_inner_mass_ratio_distr[inner_mass_ratio_distr] ) - print('Outer mass ratio: \t', outer_mass_ratio_distr, ' ',lib_outer_mass_ratio_distr[outer_mass_ratio_distr] ) - print('Inner semi-major axis: \t', inner_semi_distr, ' ',lib_inner_semi_distr[inner_semi_distr] ) - print('Outer semi-major axis: \t', outer_semi_distr, ' ',lib_outer_semi_distr[outer_semi_distr] ) - print('Inner eccentricity: \t', inner_ecc_distr, ' ',lib_inner_ecc_distr[inner_ecc_distr] ) - print('Outer eccentricity: \t', outer_ecc_distr, ' ',lib_outer_ecc_distr[outer_ecc_distr] ) - print('Inclination: \t\t', incl_distr, ' ',lib_incl_distr[incl_distr] ) - print('Inner aop: \t\t', inner_aop_distr, ' ',lib_inner_aop_distr[inner_aop_distr] ) - print('Outer aop: \t\t', outer_aop_distr, ' ',lib_outer_aop_distr[outer_aop_distr] ) - print('Inner loan: \t\t', inner_loan_distr, ' ',lib_inner_loan_distr[inner_loan_distr] ) - print('Common envelope model: \t', which_common_envelope, ' ', lib_CE[which_common_envelope]) - print('SN kick distr: \t\t', SN_kick_distr, ' ', lib_SN_kick_distr[SN_kick_distr]) - print('Metallicity: \t\t', '-', ' ', metallicity.value_in(units.none)) - print('\n') - - - print('Based on the following assumptions:') - print('Include CHE: \t\t', include_CHE) - print('Include circularisation during pre-MS: \t\t', include_circ) - print('\n') - - print('Based on the following stopping conditions:') - print(stop_at_mass_transfer, '\t Stop at mass transfer') - print(stop_at_init_mass_transfer, '\t Stop at mass transfer initially') - print(stop_at_outer_mass_transfer, '\t Stop at outer mass transfer') - print(stop_at_stable_mass_transfer, '\t Stop at stable mass transfer') - print(stop_at_eccentric_stable_mass_transfer, '\t Stop at eccentric stable mass transfer') - print(stop_at_unstable_mass_transfer, '\t Stop at unstable mass transfer') - print(stop_at_eccentric_unstable_mass_transfer, '\t Stop at eccentric unstable mass transfer') - print(stop_at_no_CHE, '\t Stop if no chemically homogeneous evolution') - print(stop_at_merger, '\t Stop at merger') - print(stop_at_disintegrated, '\t Stop at disintegration') - print(stop_at_inner_collision, '\t Stop at collision in inner binary') - print(stop_at_outer_collision, '\t Stop at collision with outer star') - print(stop_at_dynamical_instability, '\t Stop at dynamical instability') - print(stop_at_semisecular_regime, '\t Stop at semisecular regime') - print(stop_at_CPU_time, '\t Stop at maximum CPU time') - print('\n') - - -def test_initial_parameters(inner_primary_mass_max, inner_primary_mass_min, - inner_secondary_mass_max, inner_secondary_mass_min, outer_mass_min, outer_mass_max, - inner_mass_ratio_max, inner_mass_ratio_min, - outer_mass_ratio_max, outer_mass_ratio_min, - inner_semi_max, inner_semi_min, outer_semi_max, outer_semi_min, - inner_semi_latus_rectum_min, outer_semi_latus_rectum_min, - inner_semi_latus_rectum_max, outer_semi_latus_rectum_max, - inner_ecc_max, inner_ecc_min, outer_ecc_max, outer_ecc_min, - incl_max, incl_min, - inner_aop_max, inner_aop_min, outer_aop_max, outer_aop_min, - inner_loan_max, inner_loan_min, - inner_primary_mass_distr, inner_mass_ratio_distr, outer_mass_ratio_distr, - inner_semi_distr, outer_semi_distr, inner_ecc_distr, outer_ecc_distr, incl_distr, - inner_aop_distr, outer_aop_distr, inner_loan_distr, - metallicity, tend, number, initial_number, seed, - stop_at_mass_transfer, stop_at_init_mass_transfer, stop_at_outer_mass_transfer, - stop_at_stable_mass_transfer, stop_at_eccentric_stable_mass_transfer, - stop_at_unstable_mass_transfer, stop_at_eccentric_unstable_mass_transfer, which_common_envelope, - stop_at_no_CHE, include_CHE, include_circ, - stop_at_merger, stop_at_disintegrated, stop_at_inner_collision, stop_at_outer_collision, - stop_at_dynamical_instability, stop_at_semisecular_regime, - stop_at_SN, SN_kick_distr, impulse_kick_for_black_holes,fallback_kick_for_black_holes, - stop_at_CPU_time, max_CPU_time, file_name, file_type, dir_plots): - - if (inner_primary_mass_min < min_mass) or (inner_primary_mass_max > absolute_max_mass): - sys.exit("'error: inner primary mass not in allowed range [', min_mass, ',', absolute_max_mass, ']'. min_mass and absolute_max_mass settable in TRES_options.py") - - if (inner_secondary_mass_max > absolute_max_mass) : - sys.exit("'error: inner secondary mass not in allowed range [ < ', absolute_max_mass, ']'. absolute_max_mass settable in TRES_options.py") - - if (outer_mass_max > absolute_max_mass) : - sys.exit("'error: outer mass not in allowed range [ < ', absolute_max_mass, ']'. absolute_max_mass settable in TRES_options.py") - - if (inner_secondary_mass_min < absolute_min_mass) : - sys.exit("'error: inner secondary mass not in allowed range [ >', absolute_min_mass, ']'. absolute_min_mass settable in TRES_options.py") - if (outer_mass_min < absolute_min_mass) : - sys.exit("'error: outer mass not in allowed range [>', absolute_min_mass, ']'. absolute_min_mass settable in TRES_options.py") - - if (inner_primary_mass_max < inner_primary_mass_min): - sys.exit('error: maximum inner primary mass smaller than minimum in primary mass') - - if (inner_secondary_mass_max < inner_secondary_mass_min): - sys.exit('error: maximum inner secondary mass smaller than minimum in secondary mass') - - if (outer_mass_max < outer_mass_min): - sys.exit('error: maximum outer mass smaller than minimum in outer mass') - - - if (inner_mass_ratio_min < 0.) or (inner_mass_ratio_max > 1.): - sys.exit('error: inner mass ratio not in allowed range') - - if (inner_mass_ratio_max < inner_mass_ratio_min): - sys.exit('error: maximum inner mass ratio smaller than minimum mass ratio') - - - if (outer_mass_ratio_min < 0.) or (outer_mass_ratio_max > 1.): - sys.exit('error: outer mass ratio not in allowed range') - - if (outer_mass_ratio_max < outer_mass_ratio_min): - sys.exit('error: maximum outer mass ratio smaller than minimum mass ratio') - - - if (inner_semi_min < 0.5|units.RSun): - sys.exit('error: inner separation not in allowed range >5 RSun') - - if (outer_semi_min < 0.5|units.RSun): - sys.exit('error: outer separation not in allowed range >5 RSun') - - if (inner_semi_max < inner_semi_min): - sys.exit('error: maximum inner separation smaller than minimum in separation') - - if (outer_semi_max < outer_semi_min): - sys.exit('error: maximum outer separation smaller than minimum outer separation') - - if (inner_semi_min > outer_semi_max): - sys.exit('error: maximum outer separation smaller than minimum inner separation - no overlap for inner and outer orbit') - - - if (inner_ecc_min < 0.) or (inner_ecc_max > 1.): - sys.exit('error: inner eccentricity not in allowed range [0,1]') - - if (outer_ecc_min < 0.) or (outer_ecc_max > 1.): - sys.exit('error: outer eccentricity not in allowed range [0,1]') - - if (inner_ecc_max < inner_ecc_min): - sys.exit('error: maximum inner eccentricity smaller than minimum ecc') - - if (outer_ecc_max < outer_ecc_min): - sys.exit('error: maximum outer eccentricity smaller than minimum ecc') - - - if (incl_min < 0.) or (incl_max > np.pi): - sys.exit('error: relative inclination not in allowed range [0, pi]') - - if (incl_max < incl_min): - sys.exit('error: maximum relative inclination smaller than minimum relative inclination') - - - - if (inner_aop_min < -np.pi) or (inner_aop_max > np.pi): - sys.exit('error: inner argument of pericenter not in allowed range [-pi,pi]') - - if (outer_aop_min < -np.pi) or (outer_aop_max > np.pi): - sys.exit('error: outer argument of pericenter not in allowed range [-pi,pi]') - - if (inner_aop_max < inner_aop_min): - sys.exit('error: maximum inner argument of pericenter smaller than minimum argument of pericenter') - - if (outer_aop_max < outer_aop_min): - sys.exit('error: maximum outer argument of pericenter smaller than minimum argument of pericenter') - - - if (inner_loan_min < -1*np.pi) or (inner_loan_max > np.pi): - sys.exit('error: inner longitude of ascending node not in allowed range [-pi,pi]') - - if (inner_loan_max < inner_loan_min): - sys.exit('error: maximum inner longitude of ascending node smaller than minimum argument of pericenter') - - if (number < 1): - sys.exit('Requested number of systems < 1') - - if (initial_number < 0): - sys.exit('Initial number of system < 0') - - -def parse_arguments(): - parser = OptionParser() - parser.add_option("--M_min", "--M1_min",unit=units.MSun, - dest="inner_primary_mass_min", type="float", default = 1.|units.MSun, - help="minimum of inner primary mass [%default]") - parser.add_option("--M_max", "--M1_max",unit=units.MSun, - dest="inner_primary_mass_max", type="float", default = absolute_max_mass, - help="maximum of inner primary mass [%default]") - parser.add_option("--M_distr", "--M1_distr",dest="inner_primary_mass_distr", type="int", default = 0, - help="inner primary mass distribution [Kroupa]") - - parser.add_option("--m_min", "--M2_min",unit=units.MSun, - dest="inner_secondary_mass_min", type="float", default = absolute_min_mass, - help="minimum of inner secondary mass [%default]") - #only used for inner_mass_ratio_distr == 1:# Kroupa 2001 - parser.add_option("--m_max", "--M2_max",unit=units.MSun, - dest="inner_secondary_mass_max", type="float", default = absolute_max_mass, - help="maximum of inner secondary mass [%default]") - parser.add_option("--l_min", "--M3_min",unit=units.MSun, - dest="outer_mass_min", type="float", default = absolute_min_mass, - help="minimum of outer mass [%default]") - parser.add_option("--l_max", "--M3_max",unit=units.MSun, - dest="outer_mass_max", type="float", default = absolute_max_mass, - help="maximum of outer mass [%default]") - - parser.add_option("--Q_max", "--Qin_max",dest="inner_mass_ratio_max", type="float", default = 1.0, - help="maximum of inner mass ratio [%default]") - parser.add_option("--Q_min", "--Qin_min", dest="inner_mass_ratio_min", type="float", default = 0., - help="minimum of inner mass ratio [%default]") - parser.add_option("--Q_distr", "--Qin_distr", dest="inner_mass_ratio_distr", type="int", default = 0, - help="inner mass ratio distribution [Flat]") - - parser.add_option("--q_max", "--Qout_max", dest="outer_mass_ratio_max", type="float", default = 1.0, - help="maximum of outer mass ratio [%default]") - parser.add_option("--q_min", "--Qout_min", dest="outer_mass_ratio_min", type="float", default = 0., - help="minimum of outer mass ratio [%default]") - parser.add_option("--q_distr", "--Qout_distr", dest="outer_mass_ratio_distr", type="int", default = 0, - help="outer mass ratio distribution [Flat]") - - parser.add_option("--A_min", "--Ain_min", unit=units.RSun, - dest="inner_semi_min", type="float", - default = 0.5|units.RSun, - help="minimum of inner semi major axis [%default]") - parser.add_option("--A_max", "--Ain_max",unit=units.RSun, - dest="inner_semi_max", type="float", - default = 5e6|units.RSun, - help="maximum of inner semi major axis [%default]") - parser.add_option("--A_distr", "--Ain_distr",dest="inner_semi_distr", type="int", default = 0, - help="inner semimajor axis distribution [logFlat]") - - parser.add_option("--a_min", "--Aout_min",unit=units.RSun, - dest="outer_semi_min", type="float", - default = 0.5|units.RSun, - help="minimum of outer semi major axis [%default]") - parser.add_option("--a_max", "--Aout_max", unit=units.RSun, - dest="outer_semi_max", type="float", - default = 5e6|units.RSun, - help="maximum of outer semi major axis [%default]") - parser.add_option("--a_distr", "--Aout_distr", dest="outer_semi_distr", type="int", default = 0, - help="outer semimajor axis distribution [logFlat]") - - parser.add_option("--Ar_min", "--Arin_min", dest="inner_semi_latus_rectum_min", action="store_true", default = False, - help="minimum inner semi latus rectrum [%default] %unit") - parser.add_option("--ar_min", "--Arout_min",dest="outer_semi_latus_rectum_min", action="store_true", default = False, - help="minimum outer semi latus rectrum [%default] %unit") - parser.add_option("--Ar_max", "--Arin_max",dest="inner_semi_latus_rectum_max", action="store_true", default = False, - help="maximum inner semi latus rectrum [%default] %unit") - parser.add_option("--ar_max", "--Arout_max",dest="outer_semi_latus_rectum_max", action="store_true", default = False, - help="maximum outer semi latus rectrum [%default] %unit") - - parser.add_option("--E_min", "--Ein_min", - dest="inner_ecc_min", type="float", default = 0., - help="minimum of inner eccentricity [%default]") - parser.add_option("--E_max", "--Ein_max", - dest="inner_ecc_max", type="float", default = 0.9, - help="maximum of inner eccentricity [%default]") - parser.add_option("--E_distr", "--Ein_distr", dest="inner_ecc_distr", type="int", default = 0, - help="inner eccentricity distribution [Thermal]") - - parser.add_option("--e_min", "--Eout_min", - dest="outer_ecc_min", type="float", default = 0., - help="minimum of outer eccentricity [%default]") - parser.add_option("--e_max", "--Eout_max", - dest="outer_ecc_max", type="float", default = 0.9, - help="maximum of outer eccentricity [%default]") - parser.add_option("--e_distr", "--Eout_distr",dest="outer_ecc_distr", type="int", default = 0, - help="outer eccentricity distribution [Thermal]") - - - parser.add_option("--i_min, --I_min", - dest="incl_min", type="float", default = 0.0, - help="minimum of relative inclination [rad] [%default]") - parser.add_option("--i_max, --I_max", - dest="incl_max", type="float", default = np.pi, - help="maximum of relative inclination [rad] [%default]") - parser.add_option("--i_distr, --I_distr", dest="incl_distr", type="int", default = 0, - help="relative inclination distribution [Circular uniform]") - - - parser.add_option("--G_min", "--Gin_min", - dest="inner_aop_min", type="float", default = -np.pi, - help="minimum of inner argument of pericenter [rad] [%default]") - parser.add_option("--G_max", "--Gin_max", - dest="inner_aop_max", type="float", default = np.pi, - help="maximum of inner argument of pericenter [rad] [%default]") - parser.add_option("--G_distr", "--Gin_distr",dest="inner_aop_distr", type="int", default = 0, - help="inner argument of pericenter distribution [Uniform]") - - parser.add_option("--g_min", "--Gout_min", - dest="outer_aop_min", type="float", default = -np.pi, - help="minimum of outer argument of pericenter [rad] [%default]") - parser.add_option("--g_max", "--Gout_max", - dest="outer_aop_max", type="float", default = np.pi, - help="maximum of outer argument of pericenter [rad] [%default]") - parser.add_option("--g_distr", "--Gout_distr", dest="outer_aop_distr", type="int", default = 0, - help="outer argument of pericenter distribution [Uniform]") - - parser.add_option("--O_min", "--Oin_min", - dest="inner_loan_min", type="float", default = -np.pi, - help="minimum of inner longitude of ascending node [rad] [%default]") - parser.add_option("--O_max", "--Oin_max", - dest="inner_loan_max", type="float", default = np.pi, - help="maximum of inner longitude of ascending node [rad] [%default]") - parser.add_option("--O_distr", "--Oin_distr",dest="inner_loan_distr", type="int", default = 1, - help="inner longitude of ascending node distribution [Constant]") - - - parser.add_option("-z", "-Z",unit=units.none, - dest="metallicity", type="float", default = 0.02|units.none, - help="metallicity [%default] %unit") - parser.add_option("-t", "-T", unit=units.Myr, - dest="tend", type="float", default = 13500|units.Myr, - help="end time [%default] %unit") - parser.add_option("-n", dest="number", type="int", default = 10, - help="total number of systems to be simulated [%default]") - parser.add_option("-N", dest="initial_number", type="int", default = 0, - help="number ID of first system [%default]") - parser.add_option("-s", unit=units.none, - dest="seed", type="float", default = 0.|units.none, - help="seed [%default] %unit") -# int actual_seed = srandinter(input_seed); - - parser.add_option("--no_stop_at_mass_transfer", dest="stop_at_mass_transfer", action="store_false", default = True, - help="stop at mass transfer [%default] %unit") - parser.add_option("--no_stop_at_init_mass_transfer", dest="stop_at_init_mass_transfer", action="store_false", default = True, - help="stop if initially mass transfer[%default] %unit") - parser.add_option("--no_stop_at_outer_mass_transfer", dest="stop_at_outer_mass_transfer", action="store_false", default = True, - help="stop at outer mass transfer [%default] %unit") - -# if stop_at_mass_transfer is False, the following 4 stopping conditions can be used to further specify. -# if stop_at_mass_transfer is True, the following 4 are ignored. - parser.add_option("--stop_at_stable_mass_transfer", dest="stop_at_stable_mass_transfer", action="store_true", default = False, - help="stop at stable mass transfer [%default] %unit") - parser.add_option("--stop_at_eccentric_stable_mass_transfer", dest="stop_at_eccentric_stable_mass_transfer", action="store_true", - default = False, help="stop at eccentric stable mass transfer [%default] %unit") - #unstable mass transfer leads to common-envelope evolution - parser.add_option("--stop_at_unstable_mass_transfer", dest="stop_at_unstable_mass_transfer", action="store_true", - default = False, help="stop at unstable mass transfer [%default] %unit") - parser.add_option("--stop_at_eccentric_unstable_mass_transfer", dest="stop_at_eccentric_unstable_mass_transfer", - action="store_true", default = False, help="stop at eccentric unstable mass transfer [%default] %unit") - parser.add_option("--CE", dest="which_common_envelope", type="int", default = 2, - help="which common envelope modeling [%default]") - - parser.add_option("--stop_at_no_CHE",dest="stop_at_no_CHE", action="store_true", default = False, - help="stop if no chemically homogeneous evolution [%default] %unit") - parser.add_option("--include_CHE", dest="include_CHE", - action="store_true", default = False, help="include chemically homogeneous evolution in the stellar evolution [%default] %unit") - parser.add_option("--include_circularisation_during_preMS", dest="include_circ", - action="store_true", default = False, help="include circularisation during pre-MS [%default] %unit") - - parser.add_option("--no_stop_at_merger", dest="stop_at_merger", action="store_false", default = True, - help="stop at merger [%default] %unit") - parser.add_option("--no_stop_at_disintegrated", dest="stop_at_disintegrated", action="store_false", default = True, - help="stop at disintegrated [%default] %unit") - parser.add_option("--no_stop_at_inner_collision", dest="stop_at_inner_collision", action="store_false",default = True, - help="stop at collision in inner binary[%default] %unit") - parser.add_option("--no_stop_at_outer_collision", dest="stop_at_outer_collision", action="store_false",default = True, - help="stop at collision in outer binary[%default] %unit") - parser.add_option("--no_stop_at_dynamical_instability", dest="stop_at_dynamical_instability", action="store_false", default = True, - help="stop at dynamical instability [%default] %unit") - parser.add_option("--stop_at_semisecular_regime", dest="stop_at_semisecular_regime", action="store_true", default = False, - help="stop at semisecular regime [%default] %unit") - - parser.add_option("--stop_at_SN", dest="stop_at_SN", action="store_true", default = False, - help="stop at supernova [%default] %unit") - parser.add_option("--SN_kick_distr", dest="SN_kick_distr", type="int", default = 5, - help="which supernova kick distribution [%default]") - parser.add_option("--no_impulse_kick_for_black_holes", dest="impulse_kick_for_black_holes", action="store_false", default = True, - help="do not rescale the BH SN kick by mass -> impulse kick [%default]") - parser.add_option("--no_fallback_kick_for_black_holes", dest="fallback_kick_for_black_holes", action="store_false", default = True, - help="do not rescale the BH SN kick with fallback [%default]") - - parser.add_option("--stop_at_CPU_time", dest="stop_at_CPU_time", action="store_true", default = False, - help="stop at CPU time [%default] %unit") - parser.add_option("--max_CPU_time", dest="max_CPU_time", type="float", default = 3600.0, - help="max CPU time [%default] %unit") - - - parser.add_option("-f", dest="file_name", type ="string", default = "TRES.hdf",#"TRES.txt" - help="file name[%default]") - parser.add_option("-F", dest="file_type", type ="string", default = "hdf5",#"txt" - help="file type[%default]") - parser.add_option("--dir_plots", dest="dir_plots", type ="string", default = "",#"txt" - help="directory for plots for debugging mode [%default]") - - - - options, args = parser.parse_args() - return options.__dict__ - - - -if __name__ == '__main__': - options = parse_arguments() - set_printing_strategy("custom", - preferred_units = [units.MSun, units.RSun, units.Myr], - precision = 11, prefix = "", - separator = " [", suffix = "]") - - test_initial_parameters(**options) - print_distr(**options) - evolve_model(**options) - -# stellar_code.stop() -# secular_code.stop() - - print('\nYou have used the TRES triple evolution code. Literature reference:') - print('** Toonen, Hamers & Portegies Zwart 2016, ComAC, 3, 6T:') - print('... "The evolution of hierarchical triple star-systems" ') - - + + +def print_distr( + inner_primary_mass_max, + inner_primary_mass_min, + inner_secondary_mass_max, + inner_secondary_mass_min, + outer_mass_min, + outer_mass_max, + inner_mass_ratio_max, + inner_mass_ratio_min, + outer_mass_ratio_max, + outer_mass_ratio_min, + inner_semi_max, + inner_semi_min, + outer_semi_max, + outer_semi_min, + inner_semi_latus_rectum_min, + outer_semi_latus_rectum_min, + inner_semi_latus_rectum_max, + outer_semi_latus_rectum_max, + inner_ecc_max, + inner_ecc_min, + outer_ecc_max, + outer_ecc_min, + incl_max, + incl_min, + inner_aop_max, + inner_aop_min, + outer_aop_max, + outer_aop_min, + inner_loan_max, + inner_loan_min, + inner_primary_mass_distr, + inner_mass_ratio_distr, + outer_mass_ratio_distr, + inner_semi_distr, + outer_semi_distr, + inner_ecc_distr, + outer_ecc_distr, + incl_distr, + inner_aop_distr, + outer_aop_distr, + inner_loan_distr, + metallicity, + tend, + number, + initial_number, + seed, + stop_at_mass_transfer, + stop_at_init_mass_transfer, + stop_at_outer_mass_transfer, + stop_at_stable_mass_transfer, + stop_at_eccentric_stable_mass_transfer, + stop_at_unstable_mass_transfer, + stop_at_eccentric_unstable_mass_transfer, + which_common_envelope, + stop_at_no_CHE, + include_CHE, + include_circ, + stop_at_merger, + stop_at_disintegrated, + stop_at_inner_collision, + stop_at_outer_collision, + stop_at_dynamical_instability, + stop_at_semisecular_regime, + stop_at_SN, + SN_kick_distr, + impulse_kick_for_black_holes, + fallback_kick_for_black_holes, + stop_at_CPU_time, + max_CPU_time, + file_name, + file_type, + dir_plots, +): + + print("Based on the following distributions:") + print( + "Primary mass: \t\t", + inner_primary_mass_distr, + " ", + lib_inner_primary_mass_distr[inner_primary_mass_distr], + ) + print( + "Inner mass ratio: \t", + inner_mass_ratio_distr, + " ", + lib_inner_mass_ratio_distr[inner_mass_ratio_distr], + ) + print( + "Outer mass ratio: \t", + outer_mass_ratio_distr, + " ", + lib_outer_mass_ratio_distr[outer_mass_ratio_distr], + ) + print( + "Inner semi-major axis: \t", + inner_semi_distr, + " ", + lib_inner_semi_distr[inner_semi_distr], + ) + print( + "Outer semi-major axis: \t", + outer_semi_distr, + " ", + lib_outer_semi_distr[outer_semi_distr], + ) + print( + "Inner eccentricity: \t", + inner_ecc_distr, + " ", + lib_inner_ecc_distr[inner_ecc_distr], + ) + print( + "Outer eccentricity: \t", + outer_ecc_distr, + " ", + lib_outer_ecc_distr[outer_ecc_distr], + ) + print("Inclination: \t\t", incl_distr, " ", lib_incl_distr[incl_distr]) + print("Inner aop: \t\t", inner_aop_distr, " ", lib_inner_aop_distr[inner_aop_distr]) + print("Outer aop: \t\t", outer_aop_distr, " ", lib_outer_aop_distr[outer_aop_distr]) + print( + "Inner loan: \t\t", + inner_loan_distr, + " ", + lib_inner_loan_distr[inner_loan_distr], + ) + print( + "Common envelope model: \t", + which_common_envelope, + " ", + lib_CE[which_common_envelope], + ) + print("SN kick distr: \t\t", SN_kick_distr, " ", lib_SN_kick_distr[SN_kick_distr]) + print("Metallicity: \t\t", "-", " ", metallicity.value_in(units.none)) + print("\n") + + print("Based on the following assumptions:") + print("Include CHE: \t\t", include_CHE) + print("Include circularisation during pre-MS: \t\t", include_circ) + print("\n") + + print("Based on the following stopping conditions:") + print(stop_at_mass_transfer, "\t Stop at mass transfer") + print(stop_at_init_mass_transfer, "\t Stop at mass transfer initially") + print(stop_at_outer_mass_transfer, "\t Stop at outer mass transfer") + print(stop_at_stable_mass_transfer, "\t Stop at stable mass transfer") + print( + stop_at_eccentric_stable_mass_transfer, + "\t Stop at eccentric stable mass transfer", + ) + print(stop_at_unstable_mass_transfer, "\t Stop at unstable mass transfer") + print( + stop_at_eccentric_unstable_mass_transfer, + "\t Stop at eccentric unstable mass transfer", + ) + print(stop_at_no_CHE, "\t Stop if no chemically homogeneous evolution") + print(stop_at_merger, "\t Stop at merger") + print(stop_at_disintegrated, "\t Stop at disintegration") + print(stop_at_inner_collision, "\t Stop at collision in inner binary") + print(stop_at_outer_collision, "\t Stop at collision with outer star") + print(stop_at_dynamical_instability, "\t Stop at dynamical instability") + print(stop_at_semisecular_regime, "\t Stop at semisecular regime") + print(stop_at_CPU_time, "\t Stop at maximum CPU time") + print("\n") + + +def test_initial_parameters( + inner_primary_mass_max, + inner_primary_mass_min, + inner_secondary_mass_max, + inner_secondary_mass_min, + outer_mass_min, + outer_mass_max, + inner_mass_ratio_max, + inner_mass_ratio_min, + outer_mass_ratio_max, + outer_mass_ratio_min, + inner_semi_max, + inner_semi_min, + outer_semi_max, + outer_semi_min, + inner_semi_latus_rectum_min, + outer_semi_latus_rectum_min, + inner_semi_latus_rectum_max, + outer_semi_latus_rectum_max, + inner_ecc_max, + inner_ecc_min, + outer_ecc_max, + outer_ecc_min, + incl_max, + incl_min, + inner_aop_max, + inner_aop_min, + outer_aop_max, + outer_aop_min, + inner_loan_max, + inner_loan_min, + inner_primary_mass_distr, + inner_mass_ratio_distr, + outer_mass_ratio_distr, + inner_semi_distr, + outer_semi_distr, + inner_ecc_distr, + outer_ecc_distr, + incl_distr, + inner_aop_distr, + outer_aop_distr, + inner_loan_distr, + metallicity, + tend, + number, + initial_number, + seed, + stop_at_mass_transfer, + stop_at_init_mass_transfer, + stop_at_outer_mass_transfer, + stop_at_stable_mass_transfer, + stop_at_eccentric_stable_mass_transfer, + stop_at_unstable_mass_transfer, + stop_at_eccentric_unstable_mass_transfer, + which_common_envelope, + stop_at_no_CHE, + include_CHE, + include_circ, + stop_at_merger, + stop_at_disintegrated, + stop_at_inner_collision, + stop_at_outer_collision, + stop_at_dynamical_instability, + stop_at_semisecular_regime, + stop_at_SN, + SN_kick_distr, + impulse_kick_for_black_holes, + fallback_kick_for_black_holes, + stop_at_CPU_time, + max_CPU_time, + file_name, + file_type, + dir_plots, +): + + if (inner_primary_mass_min < min_mass) or ( + inner_primary_mass_max > absolute_max_mass + ): + sys.exit( + "'error: inner primary mass not in allowed range [', min_mass, ',', absolute_max_mass, ']'. min_mass and absolute_max_mass settable in TRES_options.py" + ) + + if inner_secondary_mass_max > absolute_max_mass: + sys.exit( + "'error: inner secondary mass not in allowed range [ < ', absolute_max_mass, ']'. absolute_max_mass settable in TRES_options.py" + ) + + if outer_mass_max > absolute_max_mass: + sys.exit( + "'error: outer mass not in allowed range [ < ', absolute_max_mass, ']'. absolute_max_mass settable in TRES_options.py" + ) + + if inner_secondary_mass_min < absolute_min_mass: + sys.exit( + "'error: inner secondary mass not in allowed range [ >', absolute_min_mass, ']'. absolute_min_mass settable in TRES_options.py" + ) + if outer_mass_min < absolute_min_mass: + sys.exit( + "'error: outer mass not in allowed range [>', absolute_min_mass, ']'. absolute_min_mass settable in TRES_options.py" + ) + + if inner_primary_mass_max < inner_primary_mass_min: + sys.exit( + "error: maximum inner primary mass smaller than minimum in primary mass" + ) + + if inner_secondary_mass_max < inner_secondary_mass_min: + sys.exit( + "error: maximum inner secondary mass smaller than minimum in secondary mass" + ) + + if outer_mass_max < outer_mass_min: + sys.exit("error: maximum outer mass smaller than minimum in outer mass") + + if (inner_mass_ratio_min < 0.0) or (inner_mass_ratio_max > 1.0): + sys.exit("error: inner mass ratio not in allowed range") + + if inner_mass_ratio_max < inner_mass_ratio_min: + sys.exit("error: maximum inner mass ratio smaller than minimum mass ratio") + + if (outer_mass_ratio_min < 0.0) or (outer_mass_ratio_max > 1.0): + sys.exit("error: outer mass ratio not in allowed range") + + if outer_mass_ratio_max < outer_mass_ratio_min: + sys.exit("error: maximum outer mass ratio smaller than minimum mass ratio") + + if inner_semi_min < 0.5 | units.RSun: + sys.exit("error: inner separation not in allowed range >5 RSun") + + if outer_semi_min < 0.5 | units.RSun: + sys.exit("error: outer separation not in allowed range >5 RSun") + + if inner_semi_max < inner_semi_min: + sys.exit("error: maximum inner separation smaller than minimum in separation") + + if outer_semi_max < outer_semi_min: + sys.exit( + "error: maximum outer separation smaller than minimum outer separation" + ) + + if inner_semi_min > outer_semi_max: + sys.exit( + "error: maximum outer separation smaller than minimum inner separation - no overlap for inner and outer orbit" + ) + + if (inner_ecc_min < 0.0) or (inner_ecc_max > 1.0): + sys.exit("error: inner eccentricity not in allowed range [0,1]") + + if (outer_ecc_min < 0.0) or (outer_ecc_max > 1.0): + sys.exit("error: outer eccentricity not in allowed range [0,1]") + + if inner_ecc_max < inner_ecc_min: + sys.exit("error: maximum inner eccentricity smaller than minimum ecc") + + if outer_ecc_max < outer_ecc_min: + sys.exit("error: maximum outer eccentricity smaller than minimum ecc") + + if (incl_min < 0.0) or (incl_max > np.pi): + sys.exit("error: relative inclination not in allowed range [0, pi]") + + if incl_max < incl_min: + sys.exit( + "error: maximum relative inclination smaller than minimum relative inclination" + ) + + if (inner_aop_min < -np.pi) or (inner_aop_max > np.pi): + sys.exit("error: inner argument of pericenter not in allowed range [-pi,pi]") + + if (outer_aop_min < -np.pi) or (outer_aop_max > np.pi): + sys.exit("error: outer argument of pericenter not in allowed range [-pi,pi]") + + if inner_aop_max < inner_aop_min: + sys.exit( + "error: maximum inner argument of pericenter smaller than minimum argument of pericenter" + ) + + if outer_aop_max < outer_aop_min: + sys.exit( + "error: maximum outer argument of pericenter smaller than minimum argument of pericenter" + ) + + if (inner_loan_min < -1 * np.pi) or (inner_loan_max > np.pi): + sys.exit( + "error: inner longitude of ascending node not in allowed range [-pi,pi]" + ) + + if inner_loan_max < inner_loan_min: + sys.exit( + "error: maximum inner longitude of ascending node smaller than minimum argument of pericenter" + ) + + if number < 1: + sys.exit("Requested number of systems < 1") + + if initial_number < 0: + sys.exit("Initial number of system < 0") + + +def parse_arguments(): + parser = OptionParser() + parser.add_option( + "--M_min", + "--M1_min", + unit=units.MSun, + dest="inner_primary_mass_min", + type="float", + default=1.0 | units.MSun, + help="minimum of inner primary mass [%default]", + ) + parser.add_option( + "--M_max", + "--M1_max", + unit=units.MSun, + dest="inner_primary_mass_max", + type="float", + default=absolute_max_mass, + help="maximum of inner primary mass [%default]", + ) + parser.add_option( + "--M_distr", + "--M1_distr", + dest="inner_primary_mass_distr", + type="int", + default=0, + help="inner primary mass distribution [Kroupa]", + ) + + parser.add_option( + "--m_min", + "--M2_min", + unit=units.MSun, + dest="inner_secondary_mass_min", + type="float", + default=absolute_min_mass, + help="minimum of inner secondary mass [%default]", + ) + # only used for inner_mass_ratio_distr == 1:# Kroupa 2001 + parser.add_option( + "--m_max", + "--M2_max", + unit=units.MSun, + dest="inner_secondary_mass_max", + type="float", + default=absolute_max_mass, + help="maximum of inner secondary mass [%default]", + ) + parser.add_option( + "--l_min", + "--M3_min", + unit=units.MSun, + dest="outer_mass_min", + type="float", + default=absolute_min_mass, + help="minimum of outer mass [%default]", + ) + parser.add_option( + "--l_max", + "--M3_max", + unit=units.MSun, + dest="outer_mass_max", + type="float", + default=absolute_max_mass, + help="maximum of outer mass [%default]", + ) + + parser.add_option( + "--Q_max", + "--Qin_max", + dest="inner_mass_ratio_max", + type="float", + default=1.0, + help="maximum of inner mass ratio [%default]", + ) + parser.add_option( + "--Q_min", + "--Qin_min", + dest="inner_mass_ratio_min", + type="float", + default=0.0, + help="minimum of inner mass ratio [%default]", + ) + parser.add_option( + "--Q_distr", + "--Qin_distr", + dest="inner_mass_ratio_distr", + type="int", + default=0, + help="inner mass ratio distribution [Flat]", + ) + + parser.add_option( + "--q_max", + "--Qout_max", + dest="outer_mass_ratio_max", + type="float", + default=1.0, + help="maximum of outer mass ratio [%default]", + ) + parser.add_option( + "--q_min", + "--Qout_min", + dest="outer_mass_ratio_min", + type="float", + default=0.0, + help="minimum of outer mass ratio [%default]", + ) + parser.add_option( + "--q_distr", + "--Qout_distr", + dest="outer_mass_ratio_distr", + type="int", + default=0, + help="outer mass ratio distribution [Flat]", + ) + + parser.add_option( + "--A_min", + "--Ain_min", + unit=units.RSun, + dest="inner_semi_min", + type="float", + default=0.5 | units.RSun, + help="minimum of inner semi major axis [%default]", + ) + parser.add_option( + "--A_max", + "--Ain_max", + unit=units.RSun, + dest="inner_semi_max", + type="float", + default=5e6 | units.RSun, + help="maximum of inner semi major axis [%default]", + ) + parser.add_option( + "--A_distr", + "--Ain_distr", + dest="inner_semi_distr", + type="int", + default=0, + help="inner semimajor axis distribution [logFlat]", + ) + + parser.add_option( + "--a_min", + "--Aout_min", + unit=units.RSun, + dest="outer_semi_min", + type="float", + default=0.5 | units.RSun, + help="minimum of outer semi major axis [%default]", + ) + parser.add_option( + "--a_max", + "--Aout_max", + unit=units.RSun, + dest="outer_semi_max", + type="float", + default=5e6 | units.RSun, + help="maximum of outer semi major axis [%default]", + ) + parser.add_option( + "--a_distr", + "--Aout_distr", + dest="outer_semi_distr", + type="int", + default=0, + help="outer semimajor axis distribution [logFlat]", + ) + + parser.add_option( + "--Ar_min", + "--Arin_min", + dest="inner_semi_latus_rectum_min", + action="store_true", + default=False, + help="minimum inner semi latus rectrum [%default] %unit", + ) + parser.add_option( + "--ar_min", + "--Arout_min", + dest="outer_semi_latus_rectum_min", + action="store_true", + default=False, + help="minimum outer semi latus rectrum [%default] %unit", + ) + parser.add_option( + "--Ar_max", + "--Arin_max", + dest="inner_semi_latus_rectum_max", + action="store_true", + default=False, + help="maximum inner semi latus rectrum [%default] %unit", + ) + parser.add_option( + "--ar_max", + "--Arout_max", + dest="outer_semi_latus_rectum_max", + action="store_true", + default=False, + help="maximum outer semi latus rectrum [%default] %unit", + ) + + parser.add_option( + "--E_min", + "--Ein_min", + dest="inner_ecc_min", + type="float", + default=0.0, + help="minimum of inner eccentricity [%default]", + ) + parser.add_option( + "--E_max", + "--Ein_max", + dest="inner_ecc_max", + type="float", + default=0.9, + help="maximum of inner eccentricity [%default]", + ) + parser.add_option( + "--E_distr", + "--Ein_distr", + dest="inner_ecc_distr", + type="int", + default=0, + help="inner eccentricity distribution [Thermal]", + ) + + parser.add_option( + "--e_min", + "--Eout_min", + dest="outer_ecc_min", + type="float", + default=0.0, + help="minimum of outer eccentricity [%default]", + ) + parser.add_option( + "--e_max", + "--Eout_max", + dest="outer_ecc_max", + type="float", + default=0.9, + help="maximum of outer eccentricity [%default]", + ) + parser.add_option( + "--e_distr", + "--Eout_distr", + dest="outer_ecc_distr", + type="int", + default=0, + help="outer eccentricity distribution [Thermal]", + ) + + parser.add_option( + "--i_min, --I_min", + dest="incl_min", + type="float", + default=0.0, + help="minimum of relative inclination [rad] [%default]", + ) + parser.add_option( + "--i_max, --I_max", + dest="incl_max", + type="float", + default=np.pi, + help="maximum of relative inclination [rad] [%default]", + ) + parser.add_option( + "--i_distr, --I_distr", + dest="incl_distr", + type="int", + default=0, + help="relative inclination distribution [Circular uniform]", + ) + + parser.add_option( + "--G_min", + "--Gin_min", + dest="inner_aop_min", + type="float", + default=-np.pi, + help="minimum of inner argument of pericenter [rad] [%default]", + ) + parser.add_option( + "--G_max", + "--Gin_max", + dest="inner_aop_max", + type="float", + default=np.pi, + help="maximum of inner argument of pericenter [rad] [%default]", + ) + parser.add_option( + "--G_distr", + "--Gin_distr", + dest="inner_aop_distr", + type="int", + default=0, + help="inner argument of pericenter distribution [Uniform]", + ) + + parser.add_option( + "--g_min", + "--Gout_min", + dest="outer_aop_min", + type="float", + default=-np.pi, + help="minimum of outer argument of pericenter [rad] [%default]", + ) + parser.add_option( + "--g_max", + "--Gout_max", + dest="outer_aop_max", + type="float", + default=np.pi, + help="maximum of outer argument of pericenter [rad] [%default]", + ) + parser.add_option( + "--g_distr", + "--Gout_distr", + dest="outer_aop_distr", + type="int", + default=0, + help="outer argument of pericenter distribution [Uniform]", + ) + + parser.add_option( + "--O_min", + "--Oin_min", + dest="inner_loan_min", + type="float", + default=-np.pi, + help="minimum of inner longitude of ascending node [rad] [%default]", + ) + parser.add_option( + "--O_max", + "--Oin_max", + dest="inner_loan_max", + type="float", + default=np.pi, + help="maximum of inner longitude of ascending node [rad] [%default]", + ) + parser.add_option( + "--O_distr", + "--Oin_distr", + dest="inner_loan_distr", + type="int", + default=1, + help="inner longitude of ascending node distribution [Constant]", + ) + + parser.add_option( + "-z", + "-Z", + unit=units.none, + dest="metallicity", + type="float", + default=0.02 | units.none, + help="metallicity [%default] %unit", + ) + parser.add_option( + "-t", + "-T", + unit=units.Myr, + dest="tend", + type="float", + default=13500 | units.Myr, + help="end time [%default] %unit", + ) + parser.add_option( + "-n", + dest="number", + type="int", + default=10, + help="total number of systems to be simulated [%default]", + ) + parser.add_option( + "-N", + dest="initial_number", + type="int", + default=0, + help="number ID of first system [%default]", + ) + parser.add_option( + "-s", + unit=units.none, + dest="seed", + type="float", + default=0.0 | units.none, + help="seed [%default] %unit", + ) + # int actual_seed = srandinter(input_seed); + + parser.add_option( + "--no_stop_at_mass_transfer", + dest="stop_at_mass_transfer", + action="store_false", + default=True, + help="stop at mass transfer [%default] %unit", + ) + parser.add_option( + "--no_stop_at_init_mass_transfer", + dest="stop_at_init_mass_transfer", + action="store_false", + default=True, + help="stop if initially mass transfer[%default] %unit", + ) + parser.add_option( + "--no_stop_at_outer_mass_transfer", + dest="stop_at_outer_mass_transfer", + action="store_false", + default=True, + help="stop at outer mass transfer [%default] %unit", + ) + + # if stop_at_mass_transfer is False, the following 4 stopping conditions can be used to further specify. + # if stop_at_mass_transfer is True, the following 4 are ignored. + parser.add_option( + "--stop_at_stable_mass_transfer", + dest="stop_at_stable_mass_transfer", + action="store_true", + default=False, + help="stop at stable mass transfer [%default] %unit", + ) + parser.add_option( + "--stop_at_eccentric_stable_mass_transfer", + dest="stop_at_eccentric_stable_mass_transfer", + action="store_true", + default=False, + help="stop at eccentric stable mass transfer [%default] %unit", + ) + # unstable mass transfer leads to common-envelope evolution + parser.add_option( + "--stop_at_unstable_mass_transfer", + dest="stop_at_unstable_mass_transfer", + action="store_true", + default=False, + help="stop at unstable mass transfer [%default] %unit", + ) + parser.add_option( + "--stop_at_eccentric_unstable_mass_transfer", + dest="stop_at_eccentric_unstable_mass_transfer", + action="store_true", + default=False, + help="stop at eccentric unstable mass transfer [%default] %unit", + ) + parser.add_option( + "--CE", + dest="which_common_envelope", + type="int", + default=2, + help="which common envelope modeling [%default]", + ) + + parser.add_option( + "--stop_at_no_CHE", + dest="stop_at_no_CHE", + action="store_true", + default=False, + help="stop if no chemically homogeneous evolution [%default] %unit", + ) + parser.add_option( + "--include_CHE", + dest="include_CHE", + action="store_true", + default=False, + help="include chemically homogeneous evolution in the stellar evolution [%default] %unit", + ) + parser.add_option( + "--include_circularisation_during_preMS", + dest="include_circ", + action="store_true", + default=False, + help="include circularisation during pre-MS [%default] %unit", + ) + + parser.add_option( + "--no_stop_at_merger", + dest="stop_at_merger", + action="store_false", + default=True, + help="stop at merger [%default] %unit", + ) + parser.add_option( + "--no_stop_at_disintegrated", + dest="stop_at_disintegrated", + action="store_false", + default=True, + help="stop at disintegrated [%default] %unit", + ) + parser.add_option( + "--no_stop_at_inner_collision", + dest="stop_at_inner_collision", + action="store_false", + default=True, + help="stop at collision in inner binary[%default] %unit", + ) + parser.add_option( + "--no_stop_at_outer_collision", + dest="stop_at_outer_collision", + action="store_false", + default=True, + help="stop at collision in outer binary[%default] %unit", + ) + parser.add_option( + "--no_stop_at_dynamical_instability", + dest="stop_at_dynamical_instability", + action="store_false", + default=True, + help="stop at dynamical instability [%default] %unit", + ) + parser.add_option( + "--stop_at_semisecular_regime", + dest="stop_at_semisecular_regime", + action="store_true", + default=False, + help="stop at semisecular regime [%default] %unit", + ) + + parser.add_option( + "--stop_at_SN", + dest="stop_at_SN", + action="store_true", + default=False, + help="stop at supernova [%default] %unit", + ) + parser.add_option( + "--SN_kick_distr", + dest="SN_kick_distr", + type="int", + default=5, + help="which supernova kick distribution [%default]", + ) + parser.add_option( + "--no_impulse_kick_for_black_holes", + dest="impulse_kick_for_black_holes", + action="store_false", + default=True, + help="do not rescale the BH SN kick by mass -> impulse kick [%default]", + ) + parser.add_option( + "--no_fallback_kick_for_black_holes", + dest="fallback_kick_for_black_holes", + action="store_false", + default=True, + help="do not rescale the BH SN kick with fallback [%default]", + ) + + parser.add_option( + "--stop_at_CPU_time", + dest="stop_at_CPU_time", + action="store_true", + default=False, + help="stop at CPU time [%default] %unit", + ) + parser.add_option( + "--max_CPU_time", + dest="max_CPU_time", + type="float", + default=3600.0, + help="max CPU time [%default] %unit", + ) + + parser.add_option( + "-f", + dest="file_name", + type="string", + default="TRES.hdf", # "TRES.txt" + help="file name[%default]", + ) + parser.add_option( + "-F", + dest="file_type", + type="string", + default="hdf5", # "txt" + help="file type[%default]", + ) + parser.add_option( + "--dir_plots", + dest="dir_plots", + type="string", + default="", # "txt" + help="directory for plots for debugging mode [%default]", + ) + + options, args = parser.parse_args() + return options.__dict__ + + +if __name__ == "__main__": + options = parse_arguments() + set_printing_strategy( + "custom", + preferred_units=[units.MSun, units.RSun, units.Myr], + precision=11, + prefix="", + separator=" [", + suffix="]", + ) + + test_initial_parameters(**options) + print_distr(**options) + evolve_model(**options) + + # stellar_code.stop() + # secular_code.stop() + + print("\nYou have used the TRES triple evolution code. Literature reference:") + print("** Toonen, Hamers & Portegies Zwart 2016, ComAC, 3, 6T:") + print('... "The evolution of hierarchical triple star-systems" ') From 55285bd37183cb49b5ba74148c1808c608aa6a1d Mon Sep 17 00:00:00 2001 From: Steven Rieder Date: Fri, 1 Nov 2024 14:17:53 +0100 Subject: [PATCH 04/30] initial refactor of tres.py --- src/tres/TRES.py | 1095 ++++++++++++++++++++++++++++++++-------------- 1 file changed, 778 insertions(+), 317 deletions(-) diff --git a/src/tres/TRES.py b/src/tres/TRES.py index d9dd944..63c5a49 100644 --- a/src/tres/TRES.py +++ b/src/tres/TRES.py @@ -1,13 +1,14 @@ -# to do +# to do # min teken in mean anomaly - -## Triple: Triple evolution -## computes the evolution of a given triple -## given any initial conditions (M, m, l, A, a, E, e, i, G, g, O, o, T, z). - +""" +Triple: Triple evolution + computes the evolution of a given triple + given any initial conditions (M, m, l, A, a, E, e, i, G, g, O, o, T, z). +""" import sys import numpy as np + # from interactions import * # from tidal_friction_constant import * from amuse.units import units @@ -20,68 +21,157 @@ from triple_class import Triple_Class from TRES_plotting import plot_data_container, plot_function from TRES_setup import make_particle_sets, setup_stellar_code -from TRES_options import REPORT_DEBUG, \ - REPORT_TRIPLE_EVOLUTION, \ - MAKE_PLOTS, \ - REPORT_USER_WARNINGS -from interactions import corotating_spin_angular_frequency_binary, \ - lang_spin_angular_frequency, \ - break_up_angular_frequency, \ - criticial_angular_frequency_CHE - -def initialize_triple_class(stars, bins, correct_params, - stellar_code, secular_code, relative_inclination = 80.0*np.pi/180.0, - metallicity = 0.02, tend = 5.0 |units.Myr, tinit = 0.0|units.Myr, - number = 0, maximum_radius_change_factor = 0.005, - stop_at_mass_transfer = True, stop_at_init_mass_transfer = True, stop_at_outer_mass_transfer = True, - stop_at_stable_mass_transfer = True, stop_at_eccentric_stable_mass_transfer = True, - stop_at_unstable_mass_transfer = False, stop_at_eccentric_unstable_mass_transfer = False, which_common_envelope = 2, - stop_at_no_CHE = False, include_CHE = False, - stop_at_merger = True, stop_at_disintegrated = True, stop_at_inner_collision = True, stop_at_outer_collision = True, - stop_at_dynamical_instability = True, stop_at_semisecular_regime = False, - stop_at_SN = False, SN_kick_distr = 2, impulse_kick_for_black_holes = True, fallback_kick_for_black_holes = True, - stop_at_CPU_time = False, max_CPU_time = 3600.0, file_name = "TRES.hdf", file_type = "hdf5", dir_plots = ""): - - triple = Triple_Class(stars, bins, correct_params, stellar_code, secular_code, - relative_inclination, tend, tinit, - number, maximum_radius_change_factor, - stop_at_mass_transfer, stop_at_init_mass_transfer, stop_at_outer_mass_transfer, - stop_at_stable_mass_transfer, stop_at_eccentric_stable_mass_transfer, - stop_at_unstable_mass_transfer, stop_at_eccentric_unstable_mass_transfer, which_common_envelope, - stop_at_no_CHE, include_CHE, - stop_at_merger, stop_at_disintegrated, stop_at_inner_collision, stop_at_outer_collision, - stop_at_dynamical_instability, stop_at_semisecular_regime, - stop_at_SN, SN_kick_distr, impulse_kick_for_black_holes, fallback_kick_for_black_holes, - stop_at_CPU_time, max_CPU_time, file_name, file_type, dir_plots) +from TRES_options import ( + REPORT_DEBUG, + REPORT_TRIPLE_EVOLUTION, + MAKE_PLOTS, + REPORT_USER_WARNINGS, +) +from interactions import ( + corotating_spin_angular_frequency_binary, + lang_spin_angular_frequency, + break_up_angular_frequency, + criticial_angular_frequency_CHE, +) + + +def initialize_triple_class( + stars, + bins, + correct_params, + stellar_code, + secular_code, + relative_inclination=80.0 * np.pi / 180.0, + metallicity=0.02, + tend=5.0 | units.Myr, + tinit=0.0 | units.Myr, + number=0, + maximum_radius_change_factor=0.005, + stop_at_mass_transfer=True, + stop_at_init_mass_transfer=True, + stop_at_outer_mass_transfer=True, + stop_at_stable_mass_transfer=True, + stop_at_eccentric_stable_mass_transfer=True, + stop_at_unstable_mass_transfer=False, + stop_at_eccentric_unstable_mass_transfer=False, + which_common_envelope=2, + stop_at_no_CHE=False, + include_CHE=False, + stop_at_merger=True, + stop_at_disintegrated=True, + stop_at_inner_collision=True, + stop_at_outer_collision=True, + stop_at_dynamical_instability=True, + stop_at_semisecular_regime=False, + stop_at_SN=False, + SN_kick_distr=2, + impulse_kick_for_black_holes=True, + fallback_kick_for_black_holes=True, + stop_at_CPU_time=False, + max_CPU_time=3600.0, + file_name="TRES.hdf", + file_type="hdf5", + dir_plots="", +): + + triple = Triple_Class( + stars, + bins, + correct_params, + stellar_code, + secular_code, + relative_inclination, + tend, + tinit, + number, + maximum_radius_change_factor, + stop_at_mass_transfer, + stop_at_init_mass_transfer, + stop_at_outer_mass_transfer, + stop_at_stable_mass_transfer, + stop_at_eccentric_stable_mass_transfer, + stop_at_unstable_mass_transfer, + stop_at_eccentric_unstable_mass_transfer, + which_common_envelope, + stop_at_no_CHE, + include_CHE, + stop_at_merger, + stop_at_disintegrated, + stop_at_inner_collision, + stop_at_outer_collision, + stop_at_dynamical_instability, + stop_at_semisecular_regime, + stop_at_SN, + SN_kick_distr, + impulse_kick_for_black_holes, + fallback_kick_for_black_holes, + stop_at_CPU_time, + max_CPU_time, + file_name, + file_type, + dir_plots, + ) triple.stellar_code.parameters.metallicity = metallicity return triple -#----- -#for running TRES.py from other routines -def main(inner_primary_mass = 1.3|units.MSun, inner_secondary_mass = 0.5|units.MSun, outer_mass = 0.5|units.MSun, - inner_semimajor_axis = 1.0 |units.AU, outer_semimajor_axis = 100.0 |units.AU, - inner_eccentricity = 0.1, outer_eccentricity= 0.5, - relative_inclination = 80.0*np.pi/180.0, - inner_argument_of_pericenter = 0.1, outer_argument_of_pericenter = 0.5, - inner_longitude_of_ascending_node = 0.0, - metallicity = 0.02, tend = 5.0 |units.Myr, tinit = 0.0|units.Myr, - number = 0, maximum_radius_change_factor = 0.005, - stop_at_mass_transfer = True, stop_at_init_mass_transfer = True, stop_at_outer_mass_transfer = True, - stop_at_stable_mass_transfer = True, stop_at_eccentric_stable_mass_transfer = True, - stop_at_unstable_mass_transfer = False, stop_at_eccentric_unstable_mass_transfer = False, which_common_envelope = 2, - stop_at_no_CHE = False, include_CHE = False, - stop_at_merger = True, stop_at_disintegrated = True, stop_at_inner_collision = True, stop_at_outer_collision = True, - stop_at_dynamical_instability = True, stop_at_semisecular_regime = False, - stop_at_SN = False, SN_kick_distr = 2, impulse_kick_for_black_holes = True, fallback_kick_for_black_holes = True, - stop_at_CPU_time = False, max_CPU_time = 3600.0, file_name = "TRES.hdf", file_type = "hdf5", dir_plots = "", - stellar_code=None, secular_code=None): - - set_printing_strategy("custom", - preferred_units = [units.MSun, units.RSun, units.Myr], - precision = 11, prefix = "", - separator = " [", suffix = "]") +# ----- +# for running TRES.py from other routines +def main( + inner_primary_mass=1.3 | units.MSun, + inner_secondary_mass=0.5 | units.MSun, + outer_mass=0.5 | units.MSun, + inner_semimajor_axis=1.0 | units.AU, + outer_semimajor_axis=100.0 | units.AU, + inner_eccentricity=0.1, + outer_eccentricity=0.5, + relative_inclination=80.0 * np.pi / 180.0, + inner_argument_of_pericenter=0.1, + outer_argument_of_pericenter=0.5, + inner_longitude_of_ascending_node=0.0, + metallicity=0.02, + tend=5.0 | units.Myr, + tinit=0.0 | units.Myr, + number=0, + maximum_radius_change_factor=0.005, + stop_at_mass_transfer=True, + stop_at_init_mass_transfer=True, + stop_at_outer_mass_transfer=True, + stop_at_stable_mass_transfer=True, + stop_at_eccentric_stable_mass_transfer=True, + stop_at_unstable_mass_transfer=False, + stop_at_eccentric_unstable_mass_transfer=False, + which_common_envelope=2, + stop_at_no_CHE=False, + include_CHE=False, + stop_at_merger=True, + stop_at_disintegrated=True, + stop_at_inner_collision=True, + stop_at_outer_collision=True, + stop_at_dynamical_instability=True, + stop_at_semisecular_regime=False, + stop_at_SN=False, + SN_kick_distr=2, + impulse_kick_for_black_holes=True, + fallback_kick_for_black_holes=True, + stop_at_CPU_time=False, + max_CPU_time=3600.0, + file_name="TRES.hdf", + file_type="hdf5", + dir_plots="", + stellar_code=None, + secular_code=None, +): + + set_printing_strategy( + "custom", + preferred_units=[units.MSun, units.RSun, units.Myr], + precision=11, + prefix="", + separator=" [", + suffix="]", + ) inner_eccentricity = float(inner_eccentricity) outer_eccentricity = float(outer_eccentricity) @@ -90,352 +180,723 @@ def main(inner_primary_mass = 1.3|units.MSun, inner_secondary_mass = 0.5|units.M outer_argument_of_pericenter = float(outer_argument_of_pericenter) inner_longitude_of_ascending_node = float(inner_longitude_of_ascending_node) - stars, bins, correct_params = make_particle_sets(inner_primary_mass, inner_secondary_mass, outer_mass, - inner_semimajor_axis, outer_semimajor_axis, - inner_eccentricity, outer_eccentricity, - relative_inclination, - inner_argument_of_pericenter, outer_argument_of_pericenter, - inner_longitude_of_ascending_node) + stars, bins, correct_params = make_particle_sets( + inner_primary_mass, + inner_secondary_mass, + outer_mass, + inner_semimajor_axis, + outer_semimajor_axis, + inner_eccentricity, + outer_eccentricity, + relative_inclination, + inner_argument_of_pericenter, + outer_argument_of_pericenter, + inner_longitude_of_ascending_node, + ) clean_up_stellar_code = False clean_up_secular_code = False if stellar_code is None: stellar_code = SeBa() - # stellar_code = SeBa(redirection='none') - # stellar_code = SeBa(redirection='file', redirect_file='output_SeBa_TRES.txt') + # stellar_code = SeBa(redirection='none') + # stellar_code = SeBa(redirection='file', redirect_file='output_SeBa_TRES.txt') clean_up_stellar_code = True stellar_code.parameters.metallicity = metallicity if secular_code is None: secular_code = SecularTriple() - # secular_code = SecularTriple(redirection='none') - # secular_code = SecularTriple(redirection='file', redirect_file='output_SecularTriple_TRES.txt') + # secular_code = SecularTriple(redirection='none') + # secular_code = SecularTriple(redirection='file', redirect_file='output_SecularTriple_TRES.txt') clean_up_secular_code = True - triple_class_object = Triple_Class(stars, bins, correct_params, stellar_code, secular_code, - relative_inclination, tend, tinit, - number, maximum_radius_change_factor, - stop_at_mass_transfer, stop_at_init_mass_transfer, stop_at_outer_mass_transfer, - stop_at_stable_mass_transfer, stop_at_eccentric_stable_mass_transfer, - stop_at_unstable_mass_transfer, stop_at_eccentric_unstable_mass_transfer, which_common_envelope, - stop_at_no_CHE, include_CHE, - stop_at_merger, stop_at_disintegrated, stop_at_inner_collision, stop_at_outer_collision, - stop_at_dynamical_instability, stop_at_semisecular_regime, - stop_at_SN, SN_kick_distr, impulse_kick_for_black_holes, fallback_kick_for_black_holes, - stop_at_CPU_time, max_CPU_time, file_name, file_type, dir_plots) - + triple_class_object = Triple_Class( + stars, + bins, + correct_params, + stellar_code, + secular_code, + relative_inclination, + tend, + tinit, + number, + maximum_radius_change_factor, + stop_at_mass_transfer, + stop_at_init_mass_transfer, + stop_at_outer_mass_transfer, + stop_at_stable_mass_transfer, + stop_at_eccentric_stable_mass_transfer, + stop_at_unstable_mass_transfer, + stop_at_eccentric_unstable_mass_transfer, + which_common_envelope, + stop_at_no_CHE, + include_CHE, + stop_at_merger, + stop_at_disintegrated, + stop_at_inner_collision, + stop_at_outer_collision, + stop_at_dynamical_instability, + stop_at_semisecular_regime, + stop_at_SN, + SN_kick_distr, + impulse_kick_for_black_holes, + fallback_kick_for_black_holes, + stop_at_CPU_time, + max_CPU_time, + file_name, + file_type, + dir_plots, + ) if triple_class_object.correct_params == False: if REPORT_USER_WARNINGS: - print('Choose a different system. The parameters of the given triple are incorrect.') - return triple_class_object # no codes initialized yet - elif stop_at_semisecular_regime == True and triple_class_object.semisecular_regime_at_initialisation == True: + print( + "Choose a different system. The parameters of the given triple are incorrect." + ) + return triple_class_object # no codes initialized yet + elif ( + stop_at_semisecular_regime == True + and triple_class_object.semisecular_regime_at_initialisation == True + ): if REPORT_USER_WARNINGS: - print('Choose a different system. The given triple is in the semisecular regime at initialization.') + print( + "Choose a different system. The given triple is in the semisecular regime at initialization." + ) elif triple_class_object.dynamical_instability_at_initialisation == True: if REPORT_USER_WARNINGS: - print('Choose a different system. The given triple is dynamically unstable at initialization.') + print( + "Choose a different system. The given triple is dynamically unstable at initialization." + ) elif triple_class_object.mass_transfer_at_initialisation == True: if REPORT_USER_WARNINGS: - print('Choose a different system. There is mass transfer in the given triple at initialization.') + print( + "Choose a different system. There is mass transfer in the given triple at initialization." + ) elif stop_at_no_CHE == True and triple_class_object.CHE_at_initialisation == False: if REPORT_USER_WARNINGS: - print('Choose a different system. No chemically homogeneous evolution at initialization') - else: + print( + "Choose a different system. No chemically homogeneous evolution at initialization" + ) + else: triple_class_object.evolve_model(tend) if REPORT_DEBUG or MAKE_PLOTS: plot_function(triple_class_object, dir_plots) triple_class_object.print_stellar_system() - stellar_code.particles.remove_particles(stars) - triple_set = triple_class_object.triple.as_set() - secular_code.triples.remove_particles(triple_set) + triple_set = triple_class_object.triple.as_set() + secular_code.triples.remove_particles(triple_set) del stars, bins, triple_set if clean_up_stellar_code: triple_class_object.stellar_code.stop() - print('cleaning se') + print("cleaning se") if clean_up_secular_code: triple_class_object.secular_code.stop() - print('cleaning sec') - - return triple_class_object - + print("cleaning sec") -def main_developer(stars, bins, correct_params, stellar_code, secular_code, - relative_inclination = 80.0*np.pi/180.0, - metallicity = 0.02, tend = 5.0 |units.Myr, tinit = 0.0 |units.Myr, - number = 0, maximum_radius_change_factor = 0.005, - stop_at_mass_transfer = True, stop_at_init_mass_transfer = True, stop_at_outer_mass_transfer = True, - stop_at_stable_mass_transfer = True, stop_at_eccentric_stable_mass_transfer = True, - stop_at_unstable_mass_transfer = False, stop_at_eccentric_unstable_mass_transfer = False, which_common_envelope = 2, - stop_at_no_CHE = False, include_CHE = False, - stop_at_merger = True, stop_at_disintegrated = True, stop_at_inner_collision = True, stop_at_outer_collision = True, - stop_at_dynamical_instability = True, stop_at_semisecular_regime = False, - stop_at_SN = False, SN_kick_distr = 2, impulse_kick_for_black_holes = True, fallback_kick_for_black_holes = True, - stop_at_CPU_time = False, max_CPU_time = 3600.0, file_name = "TRES.hdf", file_type = "hdf5", dir_plots = ""): + return triple_class_object - set_printing_strategy("custom", - preferred_units = [units.MSun, units.RSun, units.Myr], - precision = 11, prefix = "", - separator = " [", suffix = "]") +def main_developer( + stars, + bins, + correct_params, + stellar_code, + secular_code, + relative_inclination=80.0 * np.pi / 180.0, + metallicity=0.02, + tend=5.0 | units.Myr, + tinit=0.0 | units.Myr, + number=0, + maximum_radius_change_factor=0.005, + stop_at_mass_transfer=True, + stop_at_init_mass_transfer=True, + stop_at_outer_mass_transfer=True, + stop_at_stable_mass_transfer=True, + stop_at_eccentric_stable_mass_transfer=True, + stop_at_unstable_mass_transfer=False, + stop_at_eccentric_unstable_mass_transfer=False, + which_common_envelope=2, + stop_at_no_CHE=False, + include_CHE=False, + stop_at_merger=True, + stop_at_disintegrated=True, + stop_at_inner_collision=True, + stop_at_outer_collision=True, + stop_at_dynamical_instability=True, + stop_at_semisecular_regime=False, + stop_at_SN=False, + SN_kick_distr=2, + impulse_kick_for_black_holes=True, + fallback_kick_for_black_holes=True, + stop_at_CPU_time=False, + max_CPU_time=3600.0, + file_name="TRES.hdf", + file_type="hdf5", + dir_plots="", +): + + set_printing_strategy( + "custom", + preferred_units=[units.MSun, units.RSun, units.Myr], + precision=11, + prefix="", + separator=" [", + suffix="]", + ) bins.eccentricity[0] = float(bins.eccentricity[0]) bins.eccentricity[1] = float(bins.eccentricity[1]) bins.argument_of_pericenter[0] = float(bins.argument_of_pericenter[0]) bins.argument_of_pericenter[1] = float(bins.argument_of_pericenter[1]) bins.longitude_of_ascending_node[0] = float(bins.longitude_of_ascending_node[0]) - bins.longitude_of_ascending_node[1] = float(bins.longitude_of_ascending_node[1]) + bins.longitude_of_ascending_node[1] = float(bins.longitude_of_ascending_node[1]) relative_inclination = float(relative_inclination) - triple_class_object = Triple_Class(stars, bins, correct_params, stellar_code, secular_code, - relative_inclination, tend, tinit, - number, maximum_radius_change_factor, - stop_at_mass_transfer, stop_at_init_mass_transfer, stop_at_outer_mass_transfer, - stop_at_stable_mass_transfer, stop_at_eccentric_stable_mass_transfer, - stop_at_unstable_mass_transfer, stop_at_eccentric_unstable_mass_transfer, which_common_envelope, - stop_at_no_CHE, include_CHE, - stop_at_merger, stop_at_disintegrated, stop_at_inner_collision, stop_at_outer_collision, - stop_at_dynamical_instability, stop_at_semisecular_regime, - stop_at_SN, SN_kick_distr, impulse_kick_for_black_holes, fallback_kick_for_black_holes, - stop_at_CPU_time, max_CPU_time, file_name, file_type, dir_plots) - + triple_class_object = Triple_Class( + stars, + bins, + correct_params, + stellar_code, + secular_code, + relative_inclination, + tend, + tinit, + number, + maximum_radius_change_factor, + stop_at_mass_transfer, + stop_at_init_mass_transfer, + stop_at_outer_mass_transfer, + stop_at_stable_mass_transfer, + stop_at_eccentric_stable_mass_transfer, + stop_at_unstable_mass_transfer, + stop_at_eccentric_unstable_mass_transfer, + which_common_envelope, + stop_at_no_CHE, + include_CHE, + stop_at_merger, + stop_at_disintegrated, + stop_at_inner_collision, + stop_at_outer_collision, + stop_at_dynamical_instability, + stop_at_semisecular_regime, + stop_at_SN, + SN_kick_distr, + impulse_kick_for_black_holes, + fallback_kick_for_black_holes, + stop_at_CPU_time, + max_CPU_time, + file_name, + file_type, + dir_plots, + ) if triple_class_object.correct_params == False: if REPORT_USER_WARNINGS: - print('Choose a different system. The parameters of the given triple are incorrect.') - return triple_class_object # no codes initialized yet - elif stop_at_semisecular_regime == True and triple_class_object.semisecular_regime_at_initialisation == True: + print( + "Choose a different system. The parameters of the given triple are incorrect." + ) + return triple_class_object # no codes initialized yet + elif ( + stop_at_semisecular_regime == True + and triple_class_object.semisecular_regime_at_initialisation == True + ): if REPORT_USER_WARNINGS: - print('Choose a different system. The given triple is in the semisecular regime at initialization.') + print( + "Choose a different system. The given triple is in the semisecular regime at initialization." + ) elif triple_class_object.dynamical_instability_at_initialisation == True: if REPORT_USER_WARNINGS: - print('Choose a different system. The given triple is dynamically unstable at initialization.') + print( + "Choose a different system. The given triple is dynamically unstable at initialization." + ) elif triple_class_object.mass_transfer_at_initialisation == True: if REPORT_USER_WARNINGS: - print('Choose a different system. There is mass transfer in the given triple at initialization.') + print( + "Choose a different system. There is mass transfer in the given triple at initialization." + ) elif stop_at_no_CHE == True and triple_class_object.CHE_at_initialisation == False: if REPORT_USER_WARNINGS: - print('Choose a different system. No chemically homogeneous evolution at initialization') - else: + print( + "Choose a different system. No chemically homogeneous evolution at initialization" + ) + else: triple_class_object.evolve_model(tend) if REPORT_DEBUG or MAKE_PLOTS: plot_function(triple_class_object, dir_plots) triple_class_object.print_stellar_system() - + return triple_class_object +# ----- -#----- -#----- -#for running triple.py from the commandline +# ----- +# for running triple.py from the commandline def parse_arguments(): from amuse.units.optparse import OptionParser + parser = OptionParser() - parser.add_option("-M", "--M1", unit=units.MSun, - dest="inner_primary_mass", type="float", default = 1.3|units.MSun, - help="inner primary mass [%default]") - parser.add_option("-m", "--M2", unit=units.MSun, - dest="inner_secondary_mass", type="float", default = 0.5|units.MSun, - help="inner secondary mass [%default]") - parser.add_option("-l", "--M3", unit=units.MSun, - dest="outer_mass", type="float", default = 0.5|units.MSun, - help="outer mass [%default]") - - parser.add_option("-A", "--Ain", unit=units.RSun, - dest="inner_semimajor_axis", type="float", - default = 200.0 |units.RSun, - help="inner semi major axis [%default]") - parser.add_option("-a", "--Aout",unit=units.RSun, - dest="outer_semimajor_axis", type="float", - default = 20000.0 |units.RSun, - help="outer semi major axis [%default]") - parser.add_option("-E", "--Ein", - dest="inner_eccentricity", type="float", default = 0.1, - help="inner eccentricity [%default]") - parser.add_option("-e", "--Eout", - dest="outer_eccentricity", type="float", default = 0.5, - help="outer eccentricity [%default]") - parser.add_option("-i","-I", - dest="relative_inclination", type="float", default = 80.0*np.pi/180.0, - help="relative inclination [rad] [%default]") - parser.add_option("-G", "--Gin", - dest="inner_argument_of_pericenter", type="float", default = 0.1, - help="inner argument of pericenter [rad] [%default]") - parser.add_option("-g","--Gout", - dest="outer_argument_of_pericenter", type="float", default = 0.5, - help="outer argument of pericenter [rad] [%default]") - parser.add_option("-O", "--Oin", - dest="inner_longitude_of_ascending_node", type="float", default = 0.0, - help="inner longitude of ascending node [rad] [%default]") -## outer longitude of ascending nodes = inner - pi -# parser.add_option("-o", -# dest="outer_longitude_of_ascending_node", type="float", default = 0.0, -# help="outer longitude of ascending node [rad] [%default]") - - parser.add_option("-z", "-Z", dest="metallicity", type="float", default = 0.02, - help="metallicity [%default] %unit") - parser.add_option("-t", "-T", unit=units.Myr, - dest="tend", type="float", default = 5.0 |units.Myr, - help="end time [%default] %unit") - parser.add_option("--initial_time", unit=units.Myr, - dest="tinit", type="float", default = 0.0 |units.Myr, - help="initial time [%default] %unit") - parser.add_option("-N", dest="number", type="int", default = 0, - help="number ID of system [%default]") - parser.add_option("-r", dest="maximum_radius_change_factor", type="float", default = 0.01, - help="maximum_radius_change_factor [%default] %unit") - -# parser.add_option("--tidal", dest="tidal_terms", action="store_false", default = True, -# help="tidal terms included [%default] %unit") - - parser.add_option("--no_stop_at_mass_transfer", dest="stop_at_mass_transfer", action="store_false", default = True, - help="stop at mass transfer [%default] %unit") - parser.add_option("--no_stop_at_init_mass_transfer", dest="stop_at_init_mass_transfer", action="store_false", default = True, - help="stop if initially mass transfer[%default] %unit") - parser.add_option("--no_stop_at_outer_mass_transfer", dest="stop_at_outer_mass_transfer", action="store_false", default = True, - help="stop at triple mass transfer [%default] %unit") - -# if stop_at_mass_transfer is False, the following 4 stopping conditions can be used to further specify. -# if stop_at_mass_transfer is True, the following 4 are ignored. - parser.add_option("--stop_at_stable_mass_transfer", dest="stop_at_stable_mass_transfer", action="store_true", default = False, - help="stop at stable mass transfer [%default] %unit") - parser.add_option("--stop_at_eccentric_stable_mass_transfer", dest="stop_at_eccentric_stable_mass_transfer", action="store_true", - default = False, help="stop at eccentric stable mass transfer [%default] %unit") - #unstable mass transfer leads to common-envelope evolution - parser.add_option("--stop_at_unstable_mass_transfer", dest="stop_at_unstable_mass_transfer", action="store_true", - default = False, help="stop at unstable mass transfer [%default] %unit") - parser.add_option("--stop_at_eccentric_unstable_mass_transfer", dest="stop_at_eccentric_unstable_mass_transfer", - action="store_true", default = False, help="stop at eccentric unstable mass transfer [%default] %unit") - #0 alpha-ce + alpha-dce - #1 gamma-ce + alpha-dce - #2 seba style; combination of gamma-ce, alpha-ce & alpha-dce - parser.add_option("--CE", dest="which_common_envelope", type="int", default = 2, - help="which common envelope modeling [%default]") - - parser.add_option("--stop_at_no_CHE", dest="stop_at_no_CHE", - action="store_true", default = False, help="stop if no chemically homogeneous evolution [%default] %unit") - parser.add_option("--include_CHE", dest="include_CHE", - action="store_true", default = False, help="include chemically homogeneous evolution in the stellar evolution [%default] %unit") - - parser.add_option("--no_stop_at_merger", dest="stop_at_merger", action="store_false", default = True, - help="stop at merger [%default] %unit") - parser.add_option("--no_stop_at_disintegrated", dest="stop_at_disintegrated", action="store_false", default = True, - help="stop at disintegrated [%default] %unit") - parser.add_option("--no_stop_at_inner_collision", dest="stop_at_inner_collision", action="store_false",default = True, - help="stop at collision in inner binary[%default] %unit") - parser.add_option("--no_stop_at_outer_collision", dest="stop_at_outer_collision", action="store_false",default = True, - help="stop at collision in outer binary[%default] %unit") - parser.add_option("--no_stop_at_dynamical_instability", dest="stop_at_dynamical_instability", action="store_false", default = True, - help="stop at dynamical instability [%default] %unit") - parser.add_option("--stop_at_semisecular_regime", dest="stop_at_semisecular_regime", action="store_true", default = False, - help="stop at semisecular regime [%default] %unit") - - parser.add_option("--stop_at_SN", dest="stop_at_SN", action="store_true", default = False, - help="stop at supernova [%default] %unit") - #0 No kick - #1 Hobbs, Lorimer, Lyne & Kramer 2005, 360, 974 - #2 Arzoumanian ea 2002, 568, 289 - #3 Hansen & Phinney 1997, 291, 569 - #4 Paczynski 1990, 348, 485 - #5 Verbunt, Igoshev & Cator, 2017, 608, 57 - parser.add_option("--SN_kick_distr", dest="SN_kick_distr", type="int", default = 5, - help="which supernova kick distribution [%default]") - parser.add_option("--no_impulse_kick_for_black_holes", dest="impulse_kick_for_black_holes", action="store_false", default = True, - help="do not rescale the BH SN kick by mass -> impulse kick [%default]") - parser.add_option("--no_fallback_kick_for_black_holes", dest="fallback_kick_for_black_holes", action="store_false", default = True, - help="do not rescale the BH SN kick with fallback [%default]") - - - - parser.add_option("--stop_at_CPU_time", dest="stop_at_CPU_time", action="store_true", default = False, - help="stop at CPU time [%default] %unit") - parser.add_option("--max_CPU_time", dest="max_CPU_time", type="float", default = 3600.0, - help="max CPU time [%default] %unit") - - - parser.add_option("-f", dest="file_name", type ="string", default = "TRES.hdf",#"TRES.txt" - help="file name[%default]") - parser.add_option("-F", dest="file_type", type ="string", default = "hdf5",#"txt" - help="file type[%default]") - parser.add_option("--dir_plots", dest="dir_plots", type ="string", default = "",#"txt" - help="directory for plots for debugging mode [%default]") - + parser.add_option( + "-M", + "--M1", + unit=units.MSun, + dest="inner_primary_mass", + type="float", + default=1.3 | units.MSun, + help="inner primary mass [%default]", + ) + parser.add_option( + "-m", + "--M2", + unit=units.MSun, + dest="inner_secondary_mass", + type="float", + default=0.5 | units.MSun, + help="inner secondary mass [%default]", + ) + parser.add_option( + "-l", + "--M3", + unit=units.MSun, + dest="outer_mass", + type="float", + default=0.5 | units.MSun, + help="outer mass [%default]", + ) + + parser.add_option( + "-A", + "--Ain", + unit=units.RSun, + dest="inner_semimajor_axis", + type="float", + default=200.0 | units.RSun, + help="inner semi major axis [%default]", + ) + parser.add_option( + "-a", + "--Aout", + unit=units.RSun, + dest="outer_semimajor_axis", + type="float", + default=20000.0 | units.RSun, + help="outer semi major axis [%default]", + ) + parser.add_option( + "-E", + "--Ein", + dest="inner_eccentricity", + type="float", + default=0.1, + help="inner eccentricity [%default]", + ) + parser.add_option( + "-e", + "--Eout", + dest="outer_eccentricity", + type="float", + default=0.5, + help="outer eccentricity [%default]", + ) + parser.add_option( + "-i", + "-I", + dest="relative_inclination", + type="float", + default=80.0 * np.pi / 180.0, + help="relative inclination [rad] [%default]", + ) + parser.add_option( + "-G", + "--Gin", + dest="inner_argument_of_pericenter", + type="float", + default=0.1, + help="inner argument of pericenter [rad] [%default]", + ) + parser.add_option( + "-g", + "--Gout", + dest="outer_argument_of_pericenter", + type="float", + default=0.5, + help="outer argument of pericenter [rad] [%default]", + ) + parser.add_option( + "-O", + "--Oin", + dest="inner_longitude_of_ascending_node", + type="float", + default=0.0, + help="inner longitude of ascending node [rad] [%default]", + ) + ## outer longitude of ascending nodes = inner - pi + # parser.add_option("-o", + # dest="outer_longitude_of_ascending_node", type="float", default = 0.0, + # help="outer longitude of ascending node [rad] [%default]") + + parser.add_option( + "-z", + "-Z", + dest="metallicity", + type="float", + default=0.02, + help="metallicity [%default] %unit", + ) + parser.add_option( + "-t", + "-T", + unit=units.Myr, + dest="tend", + type="float", + default=5.0 | units.Myr, + help="end time [%default] %unit", + ) + parser.add_option( + "--initial_time", + unit=units.Myr, + dest="tinit", + type="float", + default=0.0 | units.Myr, + help="initial time [%default] %unit", + ) + parser.add_option( + "-N", + dest="number", + type="int", + default=0, + help="number ID of system [%default]", + ) + parser.add_option( + "-r", + dest="maximum_radius_change_factor", + type="float", + default=0.01, + help="maximum_radius_change_factor [%default] %unit", + ) + + # parser.add_option("--tidal", dest="tidal_terms", action="store_false", default = True, + # help="tidal terms included [%default] %unit") + + parser.add_option( + "--no_stop_at_mass_transfer", + dest="stop_at_mass_transfer", + action="store_false", + default=True, + help="stop at mass transfer [%default] %unit", + ) + parser.add_option( + "--no_stop_at_init_mass_transfer", + dest="stop_at_init_mass_transfer", + action="store_false", + default=True, + help="stop if initially mass transfer[%default] %unit", + ) + parser.add_option( + "--no_stop_at_outer_mass_transfer", + dest="stop_at_outer_mass_transfer", + action="store_false", + default=True, + help="stop at triple mass transfer [%default] %unit", + ) + + # if stop_at_mass_transfer is False, the following 4 stopping conditions can be used to further specify. + # if stop_at_mass_transfer is True, the following 4 are ignored. + parser.add_option( + "--stop_at_stable_mass_transfer", + dest="stop_at_stable_mass_transfer", + action="store_true", + default=False, + help="stop at stable mass transfer [%default] %unit", + ) + parser.add_option( + "--stop_at_eccentric_stable_mass_transfer", + dest="stop_at_eccentric_stable_mass_transfer", + action="store_true", + default=False, + help="stop at eccentric stable mass transfer [%default] %unit", + ) + # unstable mass transfer leads to common-envelope evolution + parser.add_option( + "--stop_at_unstable_mass_transfer", + dest="stop_at_unstable_mass_transfer", + action="store_true", + default=False, + help="stop at unstable mass transfer [%default] %unit", + ) + parser.add_option( + "--stop_at_eccentric_unstable_mass_transfer", + dest="stop_at_eccentric_unstable_mass_transfer", + action="store_true", + default=False, + help="stop at eccentric unstable mass transfer [%default] %unit", + ) + # 0 alpha-ce + alpha-dce + # 1 gamma-ce + alpha-dce + # 2 seba style; combination of gamma-ce, alpha-ce & alpha-dce + parser.add_option( + "--CE", + dest="which_common_envelope", + type="int", + default=2, + help="which common envelope modeling [%default]", + ) + + parser.add_option( + "--stop_at_no_CHE", + dest="stop_at_no_CHE", + action="store_true", + default=False, + help="stop if no chemically homogeneous evolution [%default] %unit", + ) + parser.add_option( + "--include_CHE", + dest="include_CHE", + action="store_true", + default=False, + help="include chemically homogeneous evolution in the stellar evolution [%default] %unit", + ) + + parser.add_option( + "--no_stop_at_merger", + dest="stop_at_merger", + action="store_false", + default=True, + help="stop at merger [%default] %unit", + ) + parser.add_option( + "--no_stop_at_disintegrated", + dest="stop_at_disintegrated", + action="store_false", + default=True, + help="stop at disintegrated [%default] %unit", + ) + parser.add_option( + "--no_stop_at_inner_collision", + dest="stop_at_inner_collision", + action="store_false", + default=True, + help="stop at collision in inner binary[%default] %unit", + ) + parser.add_option( + "--no_stop_at_outer_collision", + dest="stop_at_outer_collision", + action="store_false", + default=True, + help="stop at collision in outer binary[%default] %unit", + ) + parser.add_option( + "--no_stop_at_dynamical_instability", + dest="stop_at_dynamical_instability", + action="store_false", + default=True, + help="stop at dynamical instability [%default] %unit", + ) + parser.add_option( + "--stop_at_semisecular_regime", + dest="stop_at_semisecular_regime", + action="store_true", + default=False, + help="stop at semisecular regime [%default] %unit", + ) + + parser.add_option( + "--stop_at_SN", + dest="stop_at_SN", + action="store_true", + default=False, + help="stop at supernova [%default] %unit", + ) + # 0 No kick + # 1 Hobbs, Lorimer, Lyne & Kramer 2005, 360, 974 + # 2 Arzoumanian ea 2002, 568, 289 + # 3 Hansen & Phinney 1997, 291, 569 + # 4 Paczynski 1990, 348, 485 + # 5 Verbunt, Igoshev & Cator, 2017, 608, 57 + parser.add_option( + "--SN_kick_distr", + dest="SN_kick_distr", + type="int", + default=5, + help="which supernova kick distribution [%default]", + ) + parser.add_option( + "--no_impulse_kick_for_black_holes", + dest="impulse_kick_for_black_holes", + action="store_false", + default=True, + help="do not rescale the BH SN kick by mass -> impulse kick [%default]", + ) + parser.add_option( + "--no_fallback_kick_for_black_holes", + dest="fallback_kick_for_black_holes", + action="store_false", + default=True, + help="do not rescale the BH SN kick with fallback [%default]", + ) + + parser.add_option( + "--stop_at_CPU_time", + dest="stop_at_CPU_time", + action="store_true", + default=False, + help="stop at CPU time [%default] %unit", + ) + parser.add_option( + "--max_CPU_time", + dest="max_CPU_time", + type="float", + default=3600.0, + help="max CPU time [%default] %unit", + ) + + parser.add_option( + "-f", + dest="file_name", + type="string", + default="TRES.hdf", # "TRES.txt" + help="file name[%default]", + ) + parser.add_option( + "-F", + dest="file_type", + type="string", + default="hdf5", # "txt" + help="file type[%default]", + ) + parser.add_option( + "--dir_plots", + dest="dir_plots", + type="string", + default="", # "txt" + help="directory for plots for debugging mode [%default]", + ) + options, args = parser.parse_args() return options.__dict__ -if __name__ == '__main__': +if __name__ == "__main__": opt = parse_arguments() - set_printing_strategy("custom", - preferred_units = [units.MSun, units.RSun, units.Myr], - precision = 11, prefix = "", - separator = " [", suffix = "]") - - stars, bins, correct_params = make_particle_sets(opt["inner_primary_mass"], opt["inner_secondary_mass"], opt["outer_mass"], - opt["inner_semimajor_axis"], opt["outer_semimajor_axis"], - opt["inner_eccentricity"], opt["outer_eccentricity"], - opt["relative_inclination"], - opt["inner_argument_of_pericenter"], opt["outer_argument_of_pericenter"], - opt["inner_longitude_of_ascending_node"]) + set_printing_strategy( + "custom", + preferred_units=[units.MSun, units.RSun, units.Myr], + precision=11, + prefix="", + separator=" [", + suffix="]", + ) + + stars, bins, correct_params = make_particle_sets( + opt["inner_primary_mass"], + opt["inner_secondary_mass"], + opt["outer_mass"], + opt["inner_semimajor_axis"], + opt["outer_semimajor_axis"], + opt["inner_eccentricity"], + opt["outer_eccentricity"], + opt["relative_inclination"], + opt["inner_argument_of_pericenter"], + opt["outer_argument_of_pericenter"], + opt["inner_longitude_of_ascending_node"], + ) stellar_code = SeBa() -# stellar_code = SeBa(redirection='none') -# stellar_code = SeBa(redirection='file', redirect_file='output_SeBa_TRES.txt') + # stellar_code = SeBa(redirection='none') + # stellar_code = SeBa(redirection='file', redirect_file='output_SeBa_TRES.txt') stellar_code.parameters.metallicity = opt["metallicity"] secular_code = SecularTriple() -# secular_code = SecularTriple(redirection='none') -# secular_code = SecularTriple(redirection='file', redirect_file='output_SecularTriple_TRES.txt') - - triple_class_object = Triple_Class(stars, bins, correct_params, stellar_code, secular_code, - opt["relative_inclination"], opt["tend"], opt["tinit"], - opt["number"], opt["maximum_radius_change_factor"], - opt["stop_at_mass_transfer"], opt["stop_at_init_mass_transfer"], opt["stop_at_outer_mass_transfer"], - opt["stop_at_stable_mass_transfer"], opt["stop_at_eccentric_stable_mass_transfer"], - opt["stop_at_unstable_mass_transfer"], opt["stop_at_eccentric_unstable_mass_transfer"], opt["which_common_envelope"], - opt["stop_at_no_CHE"], opt["include_CHE"], - opt["stop_at_merger"], opt["stop_at_disintegrated"], opt["stop_at_inner_collision"], opt["stop_at_outer_collision"], - opt["stop_at_dynamical_instability"], opt["stop_at_semisecular_regime"], - opt["stop_at_SN"], opt["SN_kick_distr"], opt["impulse_kick_for_black_holes"], opt["fallback_kick_for_black_holes"], - opt["stop_at_CPU_time"], opt["max_CPU_time"], opt["file_name"], opt["file_type"], opt["dir_plots"]) + # secular_code = SecularTriple(redirection='none') + # secular_code = SecularTriple(redirection='file', redirect_file='output_SecularTriple_TRES.txt') + + triple_class_object = Triple_Class( + stars, + bins, + correct_params, + stellar_code, + secular_code, + opt["relative_inclination"], + opt["tend"], + opt["tinit"], + opt["number"], + opt["maximum_radius_change_factor"], + opt["stop_at_mass_transfer"], + opt["stop_at_init_mass_transfer"], + opt["stop_at_outer_mass_transfer"], + opt["stop_at_stable_mass_transfer"], + opt["stop_at_eccentric_stable_mass_transfer"], + opt["stop_at_unstable_mass_transfer"], + opt["stop_at_eccentric_unstable_mass_transfer"], + opt["which_common_envelope"], + opt["stop_at_no_CHE"], + opt["include_CHE"], + opt["stop_at_merger"], + opt["stop_at_disintegrated"], + opt["stop_at_inner_collision"], + opt["stop_at_outer_collision"], + opt["stop_at_dynamical_instability"], + opt["stop_at_semisecular_regime"], + opt["stop_at_SN"], + opt["SN_kick_distr"], + opt["impulse_kick_for_black_holes"], + opt["fallback_kick_for_black_holes"], + opt["stop_at_CPU_time"], + opt["max_CPU_time"], + opt["file_name"], + opt["file_type"], + opt["dir_plots"], + ) if triple_class_object.correct_params == False: if REPORT_USER_WARNINGS: - print('Choose a different system. The parameters of the given triple are incorrect.' ) + print( + "Choose a different system. The parameters of the given triple are incorrect." + ) # no codes initialized yet - sys.exit('Choose a different system. The parameters of the given triple are incorrect.') - elif opt['stop_at_semisecular_regime'] == True and triple_class_object.semisecular_regime_at_initialisation == True: + sys.exit( + "Choose a different system. The parameters of the given triple are incorrect." + ) + elif ( + opt["stop_at_semisecular_regime"] == True + and triple_class_object.semisecular_regime_at_initialisation == True + ): if REPORT_USER_WARNINGS: - print('Choose a different system. The given triple is in the semisecular regime at initialization.') + print( + "Choose a different system. The given triple is in the semisecular regime at initialization." + ) elif triple_class_object.dynamical_instability_at_initialisation == True: if REPORT_USER_WARNINGS: - print('Choose a different system. The given triple is dynamically unstable at initialization.') + print( + "Choose a different system. The given triple is dynamically unstable at initialization." + ) elif triple_class_object.mass_transfer_at_initialisation == True: if REPORT_USER_WARNINGS: - print('Choose a different system. There is mass transfer in the given triple at initialization.') - elif opt["stop_at_no_CHE"] == True and triple_class_object.CHE_at_initialisation == False: + print( + "Choose a different system. There is mass transfer in the given triple at initialization." + ) + elif ( + opt["stop_at_no_CHE"] == True + and triple_class_object.CHE_at_initialisation == False + ): if REPORT_USER_WARNINGS: - print('Choose a different system. No chemically homogeneous evolution at initialization') - else: + print( + "Choose a different system. No chemically homogeneous evolution at initialization" + ) + else: triple_class_object.evolve_model(opt["tend"]) if REPORT_DEBUG or MAKE_PLOTS: - plot_function(triple_class_object, opt['dir_plots']) + plot_function(triple_class_object, opt["dir_plots"]) triple_class_object.print_stellar_system() - - if REPORT_TRIPLE_EVOLUTION: - print('Simulation has finished succesfully') - - print('\nYou have used the TRES triple evolution code. Literature reference:') - print('** Toonen, Hamers & Portegies Zwart 2016, ComAC, 3, 6T:') + print("Simulation has finished succesfully") + + print("\nYou have used the TRES triple evolution code. Literature reference:") + print("** Toonen, Hamers & Portegies Zwart 2016, ComAC, 3, 6T:") print('... "The evolution of hierarchical triple star-systems" ') - + triple_class_object.stellar_code.stop() triple_class_object.secular_code.stop() - From fd4cb8b502b5f62d39dfc170f19c56414f400f22 Mon Sep 17 00:00:00 2001 From: Steven Rieder Date: Fri, 1 Nov 2024 14:19:37 +0100 Subject: [PATCH 05/30] update imports --- src/tres/TRES.py | 50 ++++++++++++++++++++++++------------------------ 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/src/tres/TRES.py b/src/tres/TRES.py index 63c5a49..9e5bcec 100644 --- a/src/tres/TRES.py +++ b/src/tres/TRES.py @@ -15,19 +15,19 @@ from amuse.support.console import set_printing_strategy from amuse.community.seba.interface import SeBa -from seculartriple_TPS.interface import SecularTriple +from .seculartriple_TPS.interface import SecularTriple -from triple_class import Triple_Class -from TRES_plotting import plot_data_container, plot_function -from TRES_setup import make_particle_sets, setup_stellar_code -from TRES_options import ( +from .triple_class import Triple_Class +from .TRES_plotting import plot_data_container, plot_function +from .TRES_setup import make_particle_sets, setup_stellar_code +from .TRES_options import ( REPORT_DEBUG, REPORT_TRIPLE_EVOLUTION, MAKE_PLOTS, REPORT_USER_WARNINGS, ) -from interactions import ( +from .interactions import ( corotating_spin_angular_frequency_binary, lang_spin_angular_frequency, break_up_angular_frequency, @@ -247,31 +247,31 @@ def main( dir_plots, ) - if triple_class_object.correct_params == False: + if triple_class_object.correct_params is False: if REPORT_USER_WARNINGS: print( "Choose a different system. The parameters of the given triple are incorrect." ) return triple_class_object # no codes initialized yet elif ( - stop_at_semisecular_regime == True - and triple_class_object.semisecular_regime_at_initialisation == True + stop_at_semisecular_regime is True + and triple_class_object.semisecular_regime_at_initialisation is True ): if REPORT_USER_WARNINGS: print( "Choose a different system. The given triple is in the semisecular regime at initialization." ) - elif triple_class_object.dynamical_instability_at_initialisation == True: + elif triple_class_object.dynamical_instability_at_initialisation is True: if REPORT_USER_WARNINGS: print( "Choose a different system. The given triple is dynamically unstable at initialization." ) - elif triple_class_object.mass_transfer_at_initialisation == True: + elif triple_class_object.mass_transfer_at_initialisation is True: if REPORT_USER_WARNINGS: print( "Choose a different system. There is mass transfer in the given triple at initialization." ) - elif stop_at_no_CHE == True and triple_class_object.CHE_at_initialisation == False: + elif stop_at_no_CHE is True and triple_class_object.CHE_at_initialisation is False: if REPORT_USER_WARNINGS: print( "Choose a different system. No chemically homogeneous evolution at initialization" @@ -391,31 +391,31 @@ def main_developer( dir_plots, ) - if triple_class_object.correct_params == False: + if triple_class_object.correct_params is False: if REPORT_USER_WARNINGS: print( "Choose a different system. The parameters of the given triple are incorrect." ) return triple_class_object # no codes initialized yet elif ( - stop_at_semisecular_regime == True - and triple_class_object.semisecular_regime_at_initialisation == True + stop_at_semisecular_regime is True + and triple_class_object.semisecular_regime_at_initialisation is True ): if REPORT_USER_WARNINGS: print( "Choose a different system. The given triple is in the semisecular regime at initialization." ) - elif triple_class_object.dynamical_instability_at_initialisation == True: + elif triple_class_object.dynamical_instability_at_initialisation is True: if REPORT_USER_WARNINGS: print( "Choose a different system. The given triple is dynamically unstable at initialization." ) - elif triple_class_object.mass_transfer_at_initialisation == True: + elif triple_class_object.mass_transfer_at_initialisation is True: if REPORT_USER_WARNINGS: print( "Choose a different system. There is mass transfer in the given triple at initialization." ) - elif stop_at_no_CHE == True and triple_class_object.CHE_at_initialisation == False: + elif stop_at_no_CHE is True and triple_class_object.CHE_at_initialisation is False: if REPORT_USER_WARNINGS: print( "Choose a different system. No chemically homogeneous evolution at initialization" @@ -850,7 +850,7 @@ def parse_arguments(): opt["dir_plots"], ) - if triple_class_object.correct_params == False: + if triple_class_object.correct_params is False: if REPORT_USER_WARNINGS: print( "Choose a different system. The parameters of the given triple are incorrect." @@ -860,26 +860,26 @@ def parse_arguments(): "Choose a different system. The parameters of the given triple are incorrect." ) elif ( - opt["stop_at_semisecular_regime"] == True - and triple_class_object.semisecular_regime_at_initialisation == True + opt["stop_at_semisecular_regime"] is True + and triple_class_object.semisecular_regime_at_initialisation is True ): if REPORT_USER_WARNINGS: print( "Choose a different system. The given triple is in the semisecular regime at initialization." ) - elif triple_class_object.dynamical_instability_at_initialisation == True: + elif triple_class_object.dynamical_instability_at_initialisation is True: if REPORT_USER_WARNINGS: print( "Choose a different system. The given triple is dynamically unstable at initialization." ) - elif triple_class_object.mass_transfer_at_initialisation == True: + elif triple_class_object.mass_transfer_at_initialisation is True: if REPORT_USER_WARNINGS: print( "Choose a different system. There is mass transfer in the given triple at initialization." ) elif ( - opt["stop_at_no_CHE"] == True - and triple_class_object.CHE_at_initialisation == False + opt["stop_at_no_CHE"] is True + and triple_class_object.CHE_at_initialisation is False ): if REPORT_USER_WARNINGS: print( From 944a8f9a7012c7945f36746a3c44151130bb8596 Mon Sep 17 00:00:00 2001 From: Steven Rieder Date: Fri, 1 Nov 2024 15:27:44 +0100 Subject: [PATCH 06/30] move files --- src/tres/{TRES_options.py => options.py} | 0 src/tres/{TRES_plotting.py => plotting.py} | 0 src/tres/{TRES_setup.py => setup.py} | 0 src/tres/{TPS.py => tps.py} | 0 src/tres/{TRES.py => tres.py} | 0 5 files changed, 0 insertions(+), 0 deletions(-) rename src/tres/{TRES_options.py => options.py} (100%) rename src/tres/{TRES_plotting.py => plotting.py} (100%) rename src/tres/{TRES_setup.py => setup.py} (100%) rename src/tres/{TPS.py => tps.py} (100%) rename src/tres/{TRES.py => tres.py} (100%) diff --git a/src/tres/TRES_options.py b/src/tres/options.py similarity index 100% rename from src/tres/TRES_options.py rename to src/tres/options.py diff --git a/src/tres/TRES_plotting.py b/src/tres/plotting.py similarity index 100% rename from src/tres/TRES_plotting.py rename to src/tres/plotting.py diff --git a/src/tres/TRES_setup.py b/src/tres/setup.py similarity index 100% rename from src/tres/TRES_setup.py rename to src/tres/setup.py diff --git a/src/tres/TPS.py b/src/tres/tps.py similarity index 100% rename from src/tres/TPS.py rename to src/tres/tps.py diff --git a/src/tres/TRES.py b/src/tres/tres.py similarity index 100% rename from src/tres/TRES.py rename to src/tres/tres.py From 245bd2d6303e4eee011f11f974a5381a3654472c Mon Sep 17 00:00:00 2001 From: Steven Rieder Date: Fri, 1 Nov 2024 15:28:14 +0100 Subject: [PATCH 07/30] update files --- src/tres/__init__.py | 1 + src/tres/interactions.py | 2746 +++++++++++++++--------------- src/tres/setup.py | 10 +- src/tres/tps.py | 20 +- src/tres/tres.py | 354 ++-- src/tres/triple_class.py | 3500 +++++++++++++++++++++++--------------- 6 files changed, 3662 insertions(+), 2969 deletions(-) diff --git a/src/tres/__init__.py b/src/tres/__init__.py index e69de29..3dcec34 100644 --- a/src/tres/__init__.py +++ b/src/tres/__init__.py @@ -0,0 +1 @@ +from .tres import main diff --git a/src/tres/interactions.py b/src/tres/interactions.py index 0caff6a..28ba1bd 100644 --- a/src/tres/interactions.py +++ b/src/tres/interactions.py @@ -1,1378 +1,1378 @@ -from amuse.units import units, constants, quantities -import numpy as np -import sys -import scipy.integrate as integrate - -from TRES_options import REPORT_BINARY_EVOLUTION, REPORT_FUNCTION_NAMES, REPORT_MASS_TRANSFER_STABILITY - -#constants -numerical_error = 1.e-6 -small_numerical_error = 1.e-10 -minimum_eccentricity = 1.e-5 - -const_common_envelope_efficiency = 4.0 #1.0, 4 for now for easier testing with SeBa -const_envelope_structure_parameter = 0.5 -const_common_envelope_efficiency_gamma = 1.75 - -stellar_types_compact_objects = [10,11,12,13,14]|units.stellar_type -stellar_types_giants = [2,3,4,5,6,8,9]|units.stellar_type -stellar_types_planetary_objects = [18,19]|units.stellar_type # planets & brown dwarfs - -stellar_types_SN_remnants = [13,14,15]|units.stellar_type # remnant types created through a supernova -stellar_types_remnants = [7,8,9,10,11,12,13,14,15]|units.stellar_type -stellar_types_dr = [2,4,7,8,9,10,11,12,13,14,15]|units.stellar_type #stars which go through a instantaneous radius change at formation; hertzsprung gap stars (small envelope perturbation) + horizontal branch stars + remnants - - - -#q_crit = 3. -#q_crit_giants_conv_env = 0.9 -nucleair_efficiency = 0.007 # nuc. energy production eff, Delta E = 0.007 Mc^2 - - - - - -#dictionaries -bin_type = { - 'unknown': 'unknown', - 'merger': 'merger', - 'disintegrated': 'disintegrated', - 'dyn_inst': 'dynamical_instability', - - 'detached': 'detached', - 'contact': 'contact', - 'collision': 'collision', - 'semisecular': 'semisecular', - 'rlof': 'rlof', #only used for stopping conditions - 'olof' : 'olof', #only used for stopping conditions - - 'stable_mass_transfer': 'stable_mass_transfer', - 'common_envelope': 'common_envelope', - 'common_envelope_energy_balance': 'common_envelope_energy_balance', - 'common_envelope_angular_momentum_balance': 'common_envelope_angular_momentum_balance', - 'double_common_envelope': 'double_common_envelope', - - } - -#------------------------- -#general functions -def roche_radius_dimensionless(M, m): - # Assure that the q is calculated in identical units. - unit = M.unit - # and that q itself has no unit - q = M.value_in(unit)/m.value_in(unit) - q13 = q**(1./3.) - q23 = q13**2 - return 0.49*q23/(0.6*q23 + np.log(1 + q13)) - -def roche_radius(bin, primary, self): - if not bin.is_star and primary.is_star: - return bin.semimajor_axis * roche_radius_dimensionless(primary.mass, self.get_mass(bin)-primary.mass) - - sys.exit('error in roche radius: Roche radius can only be determined in a binary') - -def L2_radius_dimensionless(M,m): - # approximation for l2 overflow - # see Marchant+ 2016 equation 2 - q = M/m - rl1 = roche_radius_dimensionless(M, m) - rl2_div_rl1 = 0.299 * np.arctan(1.83*q**0.397) + 1 - return rl2_div_rl1 * rl1 - -def L2_radius(bin, primary, self): - # note: this prescription is based on the Eggleton approximation for how to adjust a circular RL to an eccentric one - # may not be consistent with Sepinsky's method for eccentric RL (L1) - if not bin.is_star and primary.is_star: - return bin.semimajor_axis * L2_radius_dimensionless(primary.mass, self.get_mass(bin)-primary.mass)*(1-bin.eccentricity) - sys.exit('Error: L2 radius can only be determined in a binary') - -#for comparison with kozai timescale -def stellar_evolution_timescale(star): - if REPORT_FUNCTION_NAMES: - print("Stellar evolution timescale") - - if star.stellar_type in [0,1,7]|units.stellar_type: - return (0.1 * star.mass * nucleair_efficiency * constants.c**2 / star.luminosity).in_(units.Gyr) - elif star.stellar_type in stellar_types_compact_objects: - return np.inf|units.Myr - elif star.stellar_type in stellar_types_planetary_objects: - return np.inf|units.Myr - else: - return 0.1*star.age - - -#for mass transfer rate -def nuclear_evolution_timescale(star): - if REPORT_FUNCTION_NAMES: - print("Nuclear evolution timescale:") - - if star.stellar_type in [0,1,7]|units.stellar_type: - return (0.1 * star.mass * nucleair_efficiency * constants.c**2 / star.luminosity).in_(units.Gyr) - elif star.stellar_type in stellar_types_planetary_objects: -# print('nuclear evolution timescale for planetary objects requested') -# return np.inf|units.Myr - return dynamic_timescale(star) - else: #t_nuc ~ delta t * R/ delta R, other prescription gave long timescales in SeBa which destables the mass transfer - if star.time_derivative_of_radius <= (quantities.zero+numerical_error**2)|units.RSun/units.yr: - #when star is shrinking -# t_nuc = 0.1*main_sequence_time() # in SeBa - t_nuc = 0.1*star.age - else: - t_nuc = star.radius / star.time_derivative_of_radius #does not include the effect of mass loss on R - - return t_nuc - -def kelvin_helmholds_timescale(star): - if star.stellar_type in stellar_types_planetary_objects: -# print('thermal evolution timescale for planetary objects requested') - return dynamic_timescale(star) - - if REPORT_FUNCTION_NAMES: - print("KH timescale:", (constants.G*star.mass**2/star.radius/star.luminosity).in_(units.Myr)) - return constants.G*star.mass**2/star.radius/star.luminosity - -def dynamic_timescale(star): - if REPORT_FUNCTION_NAMES: - print("Dynamic timescale:", (np.sqrt(star.radius**3/star.mass/constants.G)[0]).in_(units.yr)) - return np.sqrt(star.radius**3/star.mass/constants.G) - -def corotating_spin_angular_frequency_binary(semi, m1, m2): - return 1./np.sqrt(semi**3/constants.G / (m1+m2)) - -#Hurley, Pols en Tout 2000, eq 107-108 -def lang_spin_angular_frequency(star): - v_rot = 330*star.mass.value_in(units.MSun)**3.3/(15.0+star.mass.value_in(units.MSun)**3.45) - w = 45.35 * v_rot/star.radius.value_in(units.RSun) - return w|1./units.yr - -def break_up_angular_frequency(object): - return np.sqrt( constants.G * object.mass / object.radius ) / object.radius - - -def criticial_angular_frequency_CHE(m, Z): - #angular frequency of spin for CHE threshold - #Fitting formula for CHE from Riley+ 2021 - - a_coeff = np.array([5.7914 * 10 ** - 4, -1.9196 * 10 ** - 6, - -4.0602 * 10 ** - 7, 1.0150 * 10 ** - 8, - -9.1792 * 10 ** - 11, 2.9051 * 10 ** - 13]) - mass_power = np.linspace(0,5,6) - omega_at_z_0d004 = np.sum(a_coeff * m.value_in(units.MSun)** mass_power / m.value_in(units.MSun) ** 0.4) - omega_crit = omega_at_z_0d004/(0.09 * np.log(Z/0.004) + 1) |1./units.s - return omega_crit - - -def copy_outer_orbit_to_inner_orbit(bs, self): - if REPORT_FUNCTION_NAMES: - print('Copy_outer_orbit_to_inner_orbit') - - if self.is_triple(): - bs.semimajor_axis = self.triple.semimajor_axis - bs.eccentricity = self.triple.eccentricity - bs.argument_of_pericenter = self.triple.argument_of_pericenter - bs.longitude_of_ascending_node = self.triple.longitude_of_ascending_node - bs.mass_transfer_rate = self.triple.mass_transfer_rate - bs.accretion_efficiency_mass_transfer, = self.triple.accretion_efficiency_mass_transfer, - bs.accretion_efficiency_wind_child1_to_child2, = self.triple.accretion_efficiency_wind_child1_to_child2, - bs.accretion_efficiency_wind_child2_to_child1, = self.triple.accretion_efficiency_wind_child2_to_child1, - bs.specific_AM_loss_mass_transfer, = self.triple.specific_AM_loss_mass_transfer, - bs.is_mt_stable = self.triple.is_mt_stable - - self.triple.semimajor_axis = 1e100|units.RSun - self.triple.eccentricity = 0 - - - - -def copy_outer_star_to_accretor(self): - if REPORT_FUNCTION_NAMES: - print('Copy_outer_star_to_accretor') - - if self.is_triple(): - if self.triple.child1.is_star: - tertiary_star = self.triple.child1 - bs = self.triple.child2 - else: - tertiary_star = self.triple.child2 - bs = self.triple.child1 - - - if not bs.child1.is_donor: - bs.child1 = tertiary_star - else: - bs.child2 = tertiary_star - - -#------------------------- - -#------------------------- -# functions for mass transfer in a binary - -def perform_inner_collision(self): - if self.is_triple(): - if self.triple.child1.is_star: - self.triple.child2 - else: - self.triple.child1 - - # smaller star is added to big star - if bs.child1.radius >= bs.child2.radius: - donor = bs.child1 - accretor = bs.child2 - else: - donor = bs.child2 - accretor = bs.child1 - - donor_in_stellar_code = donor.as_set().get_intersecting_subset_in(self.stellar_code.particles)[0] - accretor_in_stellar_code = accretor.as_set().get_intersecting_subset_in(self.stellar_code.particles)[0] - - #no additional mass and Jspin loss from merged object for now - J_spin_donor_previous = self.spin_angular_momentum(donor) - J_spin_accretor_previous = self.spin_angular_momentum(accretor) - J_orbit = self.orbital_angular_momentum(bs) - J_spin_new = J_spin_donor_previous + J_spin_accretor_previous + J_orbit - - #merger - donor_in_stellar_code.merge_with_other_star(accretor_in_stellar_code) - self.copy_from_stellar() - - donor.moment_of_inertia_of_star = self.moment_of_inertia(donor) - - #assuming conservation of total angular momentum of the inner binary - spin_angular_frequency = J_spin_new / donor.moment_of_inertia_of_star - critical_spin_angular_frequency = np.sqrt(constants.G * donor.mass/donor.radius**3) - donor.spin_angular_frequency = min(donor.spin_angular_frequency, critical_spin_angular_frequency) - - self.stellar_code.particles.remove_particle(accretor) - accretor.mass = 0|units.MSun # necessary for adjust_system_after_ce_in_inner_binary - #adjust outer orbit, needs to be before the system becomes a binary - #and copy to inner orbit - # weird structure necessary for secular code -> outer orbit is redundant - adjust_system_after_ce_in_inner_binary(bs, self) - copy_outer_orbit_to_inner_orbit(bs, self) - copy_outer_star_to_accretor(self) - #functions are skipped in binaries, needs to be checked if this works well - - self.secular_code.parameters.ignore_tertiary = True - self.secular_code.parameters.check_for_dynamical_stability = False - self.secular_code.parameters.check_for_outer_collision = False - self.secular_code.parameters.check_for_outer_RLOF = False - - bs.bin_type = bin_type['collision'] - self.save_snapshot() # just to note that it the system has merged - -#use of stopping condition in this way (similar to perform inner merger) is not necessary. -#TRES.py takes care of it -# if self.check_stopping_conditions_stellar_interaction()==False: -# print('stopping conditions stellar interaction') -# return False - - self.check_RLOF() - if self.has_donor(): - print(self.triple.child2.child1.mass, self.triple.child2.child2.mass, self.triple.child2.semimajor_axis, self.triple.child2.eccentricity, self.triple.child2.child1.is_donor, self.triple.child2.child2.is_donor) - print(self.triple.child1.mass, self.triple.semimajor_axis, self.triple.eccentricity, self.triple.child1.is_donor) - sys.exit("error in adjusting triple after collision: RLOF") - - donor.is_donor = False - bs.is_mt_stable = True - bs.bin_type = bin_type['detached'] - - donor.spin_angular_frequency = corotating_spin_angular_frequency_binary(bs.semimajor_axis, bs.child1.mass, bs.child2.mass) - -#use of stopping condition in this way (similar to perform inner merger) is not necessary -#TRES.py takes care of it -# return True - -def perform_inner_merger(bs, donor, accretor, self): - if REPORT_BINARY_EVOLUTION: - print('Merger in inner binary through common envelope phase') - - donor_in_stellar_code = donor.as_set().get_intersecting_subset_in(self.stellar_code.particles)[0] - accretor_in_stellar_code = accretor.as_set().get_intersecting_subset_in(self.stellar_code.particles)[0] - - #no additional mass and Jspin loss from merged object for now - J_spin_donor_previous = self.spin_angular_momentum(donor) - J_spin_accretor_previous = self.spin_angular_momentum(accretor) - J_orbit = self.orbital_angular_momentum(bs) - J_spin_new = J_spin_donor_previous + J_spin_accretor_previous + J_orbit - - #merger - donor_in_stellar_code.merge_with_other_star(accretor_in_stellar_code) - self.copy_from_stellar() - - donor.moment_of_inertia_of_star = self.moment_of_inertia(donor) - - #assuming conservation of total angular momentum of the inner binary - spin_angular_momentum = J_spin_new / donor.moment_of_inertia_of_star - critical_spin_angular_frequency = np.sqrt(constants.G * donor.mass/donor.radius**3) - donor.spin_angular_frequency = min(donor.spin_angular_frequency, critical_spin_angular_frequency) - - self.stellar_code.particles.remove_particle(accretor) - accretor.mass = 0|units.MSun # necessary for adjust_system_after_ce_in_inner_binary - #adjust outer orbit, needs to be before the system becomes a binary - #and copy to inner orbit - # weird structure necessary for secular code -> outer orbit is redundant - adjust_system_after_ce_in_inner_binary(bs, self) - copy_outer_orbit_to_inner_orbit(bs, self) - copy_outer_star_to_accretor(self) - #functions are skipped in binaries, needs to be checked if this works well - - self.secular_code.parameters.ignore_tertiary = True - self.secular_code.parameters.check_for_dynamical_stability = False - self.secular_code.parameters.check_for_outer_collision = False - self.secular_code.parameters.check_for_outer_RLOF = False - bs.bin_type = bin_type['merger'] - self.save_snapshot() # just to note that the system has merged - - if self.check_stopping_conditions_stellar_interaction()==False: - print('stopping conditions stellar interaction') - return False - else: - return True - -# print(self.secular_code.give_roche_radii(self.triple),) -# print(roche_radius(self.triple.child2, self.triple.child2.child1, self), roche_radius(self.triple.child2, self.triple.child2.child2, self)) -# -# print(donor.spin_angular_frequency, corotating_spin_angular_frequency_binary(bs.semimajor_axis, bs.child1.mass, bs.child2.mass), critical_spin_angular_frequency) -# donor.spin_angular_frequency = corotating_spin_angular_frequency_binary(bs.semimajor_axis, bs.child1.mass, bs.child2.mass) - - - -def common_envelope_efficiency(donor, accretor): - return const_common_envelope_efficiency - -def envelope_structure_parameter(donor): - return const_envelope_structure_parameter - -def common_envelope_efficiency_gamma(donor, accretor): - return const_common_envelope_efficiency_gamma - - - -# ang.mom balance: \Delta J = \gamma * J * \Delta M / M -# See Eq. 5 of Nelemans VYPZ 2000, 360, 1011 A&A -def common_envelope_angular_momentum_balance(bs, donor, accretor, self): - if REPORT_FUNCTION_NAMES: - print('Common envelope angular momentum balance') - - if REPORT_BINARY_EVOLUTION: - if bs.eccentricity > 0.05: - print('gamma common envelope in eccentric binary') - print('Before common envelope angular momentum balance' ) - self.print_binary(bs) - - bs.bin_type = bin_type['common_envelope_angular_momentum_balance'] - self.save_snapshot() - - gamma = common_envelope_efficiency_gamma(donor, accretor) - J_init = np.sqrt(bs.semimajor_axis) * (donor.mass * accretor.mass) / np.sqrt(donor.mass + accretor.mass) * np.sqrt(1-bs.eccentricity**2) - J_f_over_sqrt_a_new = (donor.core_mass * accretor.mass) / np.sqrt(donor.core_mass + accretor.mass) - J_lost = gamma * (donor.mass-donor.core_mass) * J_init/(donor.mass + accretor.mass) - sqrt_a_new = max(0.|units.RSun**0.5, (J_init -J_lost)/J_f_over_sqrt_a_new) - a_new = pow(sqrt_a_new, 2) - - Rl_donor_new = roche_radius_dimensionless(donor.core_mass, accretor.mass)*a_new - Rl_accretor_new = roche_radius_dimensionless(accretor.mass, donor.core_mass)*a_new - if REPORT_BINARY_EVOLUTION: - print('donor:', donor.radius, donor.core_radius, Rl_donor_new) - print('accretor:', accretor.radius, accretor.core_radius, Rl_accretor_new) - - if (donor.core_radius > Rl_donor_new) or (accretor.radius > Rl_accretor_new): - stopping_condition = perform_inner_merger(bs, donor, accretor, self) - if not stopping_condition: #stellar interaction - return False - else: - donor_in_stellar_code = donor.as_set().get_intersecting_subset_in(self.stellar_code.particles)[0] - #reduce_mass not subtrac mass, want geen adjust_donor_radius - #check if star changes type - donor_in_stellar_code.change_mass(-1*(donor.mass-donor.core_mass+(small_numerical_error|units.MSun)), 0.|units.yr) - self.copy_from_stellar() - - donor.moment_of_inertia_of_star = self.moment_of_inertia(donor) - accretor.moment_of_inertia_of_star = self.moment_of_inertia(accretor) - - bs.semimajor_axis = a_new - bs.eccentricity = minimum_eccentricity - - #set to synchronization - corotating_frequency = corotating_spin_angular_frequency_binary(a_new, donor.mass, accretor.mass) - donor.spin_angular_frequency = corotating_frequency - accretor.spin_angular_frequency = corotating_frequency - - self.check_RLOF() - if self.has_donor(): - print(self.triple.child2.child1.mass, self.triple.child2.child2.mass, self.triple.child2.child1.radius, self.triple.child2.child2.radius,self.triple.child2.semimajor_axis, self.triple.child2.eccentricity, self.triple.child2.child1.is_donor, self.triple.child2.child2.is_donor) - print(self.triple.child2.child1.core_mass, self.triple.child2.child1.mass-self.triple.child2.child1.core_mass, self.triple.child2.child1.stellar_type) - print(self.triple.child1.mass, self.triple.semimajor_axis, self.triple.eccentricity, self.triple.child1.is_donor) - -# sys.exit("error in adjusting triple after gamma CE: RLOF") - stopping_condition = perform_inner_merger(bs, donor, accretor, self) - if not stopping_condition: #stellar interaction - return False - -# adjusting of stellar system -# in previous case of merger, the adjustment is done there as mass may be lost during the merger - adjust_system_after_ce_in_inner_binary(bs, self) - - - - donor.is_donor = False - bs.is_mt_stable = True - bs.bin_type = bin_type['detached'] - self.instantaneous_evolution = True #skip secular evolution - - return True - -#Following Webbink 1984 -def common_envelope_energy_balance(bs, donor, accretor, self): - if REPORT_FUNCTION_NAMES: - print('Common envelope energy balance') - - if REPORT_BINARY_EVOLUTION: - print('Before common envelope energy balance' ) - self.print_binary(bs) - - bs.bin_type = bin_type['common_envelope_energy_balance'] - self.save_snapshot() - - alpha = common_envelope_efficiency(donor, accretor) - lambda_donor = envelope_structure_parameter(donor) - - Rl_donor = roche_radius(bs, donor, self) - donor_radius = min(donor.radius, Rl_donor) - - #based on Glanz & Perets 2021 2021MNRAS.507.2659G - #eccentric CE -> end result depends on pericenter distance more than semi-major axis - pericenter_init = bs.semimajor_axis * (1-bs.eccentricity) - orb_energy_new = donor.mass * (donor.mass-donor.core_mass) / (alpha * lambda_donor * donor_radius) + donor.mass * accretor.mass/2/pericenter_init - a_new = donor.core_mass * accretor.mass / 2 / orb_energy_new -# a_new = bs.semimajor_axis * (donor.core_mass/donor.mass) / (1. + (2.*(donor.mass-donor.core_mass)*bs.semimajor_axis/(alpha_lambda*donor_radius*accretor.mass))) - - Rl_donor_new = roche_radius_dimensionless(donor.core_mass, accretor.mass)*a_new - Rl_accretor_new = roche_radius_dimensionless(accretor.mass, donor.core_mass)*a_new - if REPORT_BINARY_EVOLUTION: - print('donor:', donor.radius, donor.core_radius, Rl_donor_new) - print('accretor:', accretor.radius, accretor.core_radius, Rl_accretor_new) - - if (donor.core_radius > Rl_donor_new) or (accretor.radius > Rl_accretor_new): - stopping_condition = perform_inner_merger(bs, donor, accretor, self) - if not stopping_condition: #stellar interaction - return False - else: - donor_in_stellar_code = donor.as_set().get_intersecting_subset_in(self.stellar_code.particles)[0] - #reduce_mass not subtrac mass, want geen adjust_donor_radius - #check if star changes type - donor_in_stellar_code.change_mass(-1*(donor.mass-donor.core_mass+(small_numerical_error|units.MSun)), 0.|units.yr) - self.copy_from_stellar() - - donor.moment_of_inertia_of_star = self.moment_of_inertia(donor) - accretor.moment_of_inertia_of_star = self.moment_of_inertia(accretor) - - bs.semimajor_axis = a_new - bs.eccentricity = minimum_eccentricity - - #set to synchronization - corotating_frequency = corotating_spin_angular_frequency_binary(a_new, donor.mass, accretor.mass) - donor.spin_angular_frequency = corotating_frequency - accretor.spin_angular_frequency = corotating_frequency - - - self.check_RLOF() - if self.has_donor(): - print(self.triple.child2.child1.mass, self.triple.child2.child2.mass, self.triple.child2.semimajor_axis, self.triple.child2.eccentricity, self.triple.child2.child1.is_donor, self.triple.child2.child2.is_donor) - print(self.triple.child1.mass, self.triple.semimajor_axis, self.triple.eccentricity, self.triple.child1.is_donor) - - # sys.exit("error in adjusting triple after alpha CE: RLOF") - stopping_condition = perform_inner_merger(bs, donor, accretor, self) - if not stopping_condition: #stellar interaction - return False - -# adjusting of stellar system -# in previous case of merger, the adjustment is done there as mass may be lost during the merger - adjust_system_after_ce_in_inner_binary(bs, self) - - donor.is_donor = False - bs.is_mt_stable = True - bs.bin_type = bin_type['detached'] - self.instantaneous_evolution = True #skip secular evolution - return True - -# See appendix of Nelemans YPZV 2001, 365, 491 A&A -def double_common_envelope_energy_balance(bs, donor, accretor, self): - if REPORT_FUNCTION_NAMES: - print('Double common envelope energy balance') - - if REPORT_BINARY_EVOLUTION: - print('Before double common envelope energy balance' ) - self.print_binary(bs) - - bs.bin_type = bin_type['double_common_envelope'] - self.save_snapshot() - - alpha = common_envelope_efficiency(donor, accretor) - lambda_donor = envelope_structure_parameter(donor) - lambda_accretor = envelope_structure_parameter(accretor) - - Rl_donor = roche_radius(bs, donor, self) - donor_radius = min(donor.radius, Rl_donor) - accretor_radius = accretor.radius - - - #based on Glanz & Perets 2021 2021MNRAS.507.2659G - #eccentric CE -> end result depends on pericenter distance more than semi-major axis - pericenter_init = bs.semimajor_axis * (1-bs.eccentricity) - orb_energy_new = donor.mass * (donor.mass-donor.core_mass) / (alpha * lambda_donor * donor_radius) + accretor.mass * (accretor.mass-accretor.core_mass) / (alpha * lambda_accretor * accretor_radius) + donor.mass * accretor.mass/2/pericenter_init - a_new = donor.core_mass * accretor.core_mass / 2 / orb_energy_new - - Rl_donor_new = roche_radius_dimensionless(donor.core_mass, accretor.core_mass)*a_new - Rl_accretor_new = roche_radius_dimensionless(accretor.core_mass, donor.core_mass)*a_new - if REPORT_BINARY_EVOLUTION: - print('donor:', donor.radius, donor.core_radius, Rl_donor_new) - print('accretor:', accretor.radius, accretor.core_radius, Rl_accretor_new) - - if (donor.core_radius > Rl_donor_new) or (accretor.core_radius > Rl_accretor_new): - stopping_condition = perform_inner_merger(bs, donor, accretor, self) - if not stopping_condition: #stellar interaction - return False - else: - #reduce_mass not subtrac mass, want geen adjust_donor_radius - #check if star changes type - - donor_in_stellar_code = donor.as_set().get_intersecting_subset_in(self.stellar_code.particles)[0] - donor_in_stellar_code.change_mass(-1*(donor.mass-donor.core_mass+(small_numerical_error|units.MSun)), 0.|units.yr) - accretor_in_stellar_code = accretor.as_set().get_intersecting_subset_in(self.stellar_code.particles)[0] - accretor_in_stellar_code.change_mass(-1*(accretor.mass-accretor.core_mass), 0.|units.yr) - self.copy_from_stellar() - - - donor.moment_of_inertia_of_star = self.moment_of_inertia(donor) - accretor.moment_of_inertia_of_star = self.moment_of_inertia(accretor) - - bs.semimajor_axis = a_new - bs.eccentricity = minimum_eccentricity - - #set to synchronization - corotating_frequency = corotating_spin_angular_frequency_binary(a_new, donor.mass, accretor.mass) - donor.spin_angular_frequency = corotating_frequency - accretor.spin_angular_frequency = corotating_frequency - - self.check_RLOF() - if self.has_donor(): - print(self.triple.child2.child1.mass, self.triple.child2.child2.mass, self.triple.child2.semimajor_axis, self.triple.child2.eccentricity, self.triple.child2.child1.is_donor, self.triple.child2.child2.is_donor) - print(self.triple.child1.mass, self.triple.semimajor_axis, self.triple.eccentricity, self.triple.child1.is_donor) - - # sys.exit("error in adjusting triple after double CE: RLOF") - stopping_condition = perform_inner_merger(bs, donor, accretor, self) - if not stopping_condition: #stellar interaction - return False - -# adjusting of stellar system -# in previous case of merger, the adjustment is done there as mass may be lost during the merger - adjust_system_after_ce_in_inner_binary(bs, self) - - donor.is_donor = False - bs.is_mt_stable = True - bs.bin_type = bin_type['detached'] - self.instantaneous_evolution = True #skip secular evolution - return True - -def common_envelope_phase(bs, donor, accretor, self): - stopping_condition = True - - if REPORT_FUNCTION_NAMES: - print('Common envelope phase', self.which_common_envelope) - print('donor:', donor.stellar_type) - print('accretor:', accretor.stellar_type) - - if donor.stellar_type not in stellar_types_giants and accretor.stellar_type not in stellar_types_giants: -# possible options: MS+MS, MS+remnant, remnant+remnant, -# HeMS+HeMS, HeMS+MS, HeMS+remnant - bs.bin_type = bin_type['common_envelope'] - self.save_snapshot() - stopping_condition = perform_inner_merger(bs, donor, accretor, self) - if not stopping_condition: #stellar interaction - return False - - self.check_RLOF() - if self.has_donor(): - print(self.triple.child2.child1.mass, self.triple.child2.child2.mass, self.triple.child2.semimajor_axis, self.triple.child2.eccentricity, self.triple.child2.child1.is_donor, self.triple.child2.child2.is_donor) - print(self.triple.child1.mass, self.triple.semimajor_axis, self.triple.eccentricity, self.triple.child1.is_donor) - print(self.triple.child2.child1.radius, self.triple.child2.child2.radius,self.triple.child1.radius) - print(self.secular_code.give_roche_radii(self.triple)) - print('binary Roche lobe radii:', roche_radius(bs, bs.child1, self), roche_radius(bs, bs.child2, self)) - -# sys.exit("error in adjusting system after CE: RLOF") - stopping_condition = perform_inner_merger(bs, donor, accretor, self) - if not stopping_condition: #stellar interaction - return False - - donor.is_donor = False - bs.is_mt_stable = True - bs.bin_type = bin_type['detached'] - self.instantaneous_evolution = True #skip secular evolution - - return True - - - - if self.which_common_envelope == 0: - if donor.stellar_type in stellar_types_giants and accretor.stellar_type in stellar_types_giants: - stopping_condition = double_common_envelope_energy_balance(bs, donor, accretor, self) - else: - stopping_condition = common_envelope_energy_balance(bs, donor, accretor, self) - elif self.which_common_envelope == 1: - if donor.stellar_type in stellar_types_giants and accretor.stellar_type in stellar_types_giants: - stopping_condition = double_common_envelope_energy_balance(bs, donor, accretor, self) - else: - stopping_condition = common_envelope_angular_momentum_balance(bs, donor, accretor, self) - elif self.which_common_envelope == 2: - Js_d = self.spin_angular_momentum(donor) - Js_a = self.spin_angular_momentum(accretor) - Jb = self.orbital_angular_momentum(bs) - Js = max(Js_d, Js_a) -# print("Darwin Riemann instability? donor/accretor:", Js_d, Js_a, Jb, Jb/3.) - if donor.stellar_type in stellar_types_giants and accretor.stellar_type in stellar_types_giants: - #giant+giant - stopping_condition = double_common_envelope_energy_balance(bs, donor, accretor, self) - elif donor.stellar_type in stellar_types_compact_objects or accretor.stellar_type in stellar_types_compact_objects: - #giant+remnant - stopping_condition = common_envelope_energy_balance(bs, donor, accretor, self) - elif Js >= Jb/3. : - #darwin riemann instability - stopping_condition = common_envelope_energy_balance(bs, donor, accretor, self) - else: - #giant+normal(non-giant, non-remnant) - stopping_condition = common_envelope_angular_momentum_balance(bs, donor, accretor, self) - - return stopping_condition - - -def adiabatic_expansion_due_to_mass_loss(a_i, Md_f, Md_i, Ma_f, Ma_i): - - d_Md = Md_f - Md_i #negative mass loss rate - d_Ma = Ma_f - Ma_i #positive mass accretion rate - - Mt_f = Md_f + Ma_f - Mt_i = Md_i + Ma_i - - if d_Md < 0|units.MSun and d_Ma >= 0|units.MSun: - eta = d_Ma / d_Md - a_f = a_i * ((Md_f/Md_i)**eta * (Ma_f/Ma_i))**-2 * Mt_i/Mt_f - return a_f - return a_i - - -def adjust_system_after_ce_in_inner_binary(bs, self): - # Assumption: Unstable mass transfer (common-envelope phase) in the inner binary, affects the outer binary as a wind. - # Instanteneous effect - if REPORT_FUNCTION_NAMES: - print('Adjust system after ce in inner binary') - - if self.is_triple(): - M_com_after_ce = self.get_mass(bs) - M_com_before_ce = bs.previous_mass - - if self.triple.child1.is_star: - tertiary_star = self.triple.child1 - else: - tertiary_star = self.triple.child2 - # accretion_efficiency - M_accretor_before_ce = tertiary_star.mass - M_accretor_after_ce = tertiary_star.mass - - a_new = adiabatic_expansion_due_to_mass_loss(self.triple.semimajor_axis, M_com_after_ce, M_com_before_ce, M_accretor_after_ce, M_accretor_before_ce) - self.triple.semimajor_axis = a_new -# print('outer orbit', a_new) - - -# nice but difficult to update self.triple -# system = bs -# while True: -# try: -# system = system.parent -# if not system.child1.is_star and system.child2.is_star: -# system = adjust_triple_after_ce_in_inner_binary(system, system.child1, system.child2, self) -# elif not system.child2.is_star and system.child1.is_star: -# system = adjust_triple_after_ce_in_inner_binary(system, system.child2, system.child1, self) -# else: -# print('adjust_system_after_ce_in_inner_binary: type of system unknown') -# exit(2) -# -# except AttributeError: -# #when there is no parent -# break -# - - -def stable_mass_transfer(bs, donor, accretor, self): - # orbital evolution is being taken into account in secular_code - if REPORT_FUNCTION_NAMES: - print('Stable mass transfer') - - if bs.bin_type != bin_type['stable_mass_transfer']: - bs.bin_type = bin_type['stable_mass_transfer'] - self.save_snapshot() - else: - bs.bin_type = bin_type['stable_mass_transfer'] - - self.secular_code.parameters.check_for_inner_RLOF = False - self.secular_code.parameters.include_spin_radius_mass_coupling_terms_star1 = False - self.secular_code.parameters.include_spin_radius_mass_coupling_terms_star2 = False - - Md = donor.mass - Ma = accretor.mass - - dt = self.triple.time - self.previous_time - dm_desired = bs.mass_transfer_rate * dt - if REPORT_FUNCTION_NAMES: - print(bs.mass_transfer_rate, dt, dm_desired) - donor_in_stellar_code = donor.as_set().get_intersecting_subset_in(self.stellar_code.particles)[0] - donor_in_stellar_code.change_mass(dm_desired+(small_numerical_error|units.MSun), dt) - - # dm != dm_desired e.g. when the envelope of the star becomes empty - dm = donor_in_stellar_code.mass - Md - bs.part_dt_mt = 1. - if dm - dm_desired > numerical_error|units.MSun: -# print('WARNING:the envelope is empty, mass transfer rate should be lower or dt should be smaller... ') - bs.part_dt_mt = dm/dm_desired - - # there is an implicit assumption in change_mass that the accreted mass is of solar composition (hydrogen) - accretor_in_stellar_code = accretor.as_set().get_intersecting_subset_in(self.stellar_code.particles)[0] -# accretor_in_stellar_code.change_mass(dm, dt) - # for now, only conservative mass transfer - accretor_in_stellar_code.change_mass(-1.*dm, -1.*dt) - #if you want seba to determine the accretion efficiency, use - #accretor_in_stellar_code.change_mass(-1.*dm, dt) - #note doesnt work perfectly, as seba is oblivious to the roche lobe radius - - - #to adjust radius to mass loss and increase - self.stellar_code.evolve_model(self.triple.time) - self.copy_from_stellar() - - self.update_stellar_parameters() - - Md_new = donor.mass - Ma_new = accretor.mass - accretion_efficiency = (Ma_new-Ma)/(Md-Md_new) - if abs(accretion_efficiency - 1.0) > numerical_error and abs(Md-Md_new - -1.*(Ma-Ma_new)) > numerical_error |units.MSun: - self.save_snapshot() - print('stable_mass_transfer: non conservative mass transfer') - print(Md, Ma, donor.previous_mass, accretor.previous_mass) - print(Md_new, Ma_new, Md-Md_new, Ma-Ma_new, accretion_efficiency) - print(donor.stellar_type, accretor.stellar_type) - sys.exit('error in stable mass transfer') - - bs.accretion_efficiency_mass_transfer = accretion_efficiency - - corotation_spin = corotating_spin_angular_frequency_binary(bs.semimajor_axis, donor.mass, accretor.mass) - donor.spin_angular_frequency = corotation_spin - accretor.spin_angular_frequency = corotation_spin - - - -def semi_detached(bs, donor, accretor, self): -#only for binaries (consisting of two stars) - if REPORT_FUNCTION_NAMES: - print('Semi-detached') - print(bs.semimajor_axis, donor.mass, accretor.mass, donor.stellar_type, accretor.stellar_type, bs.is_mt_stable) - - - stopping_condition = True - if bs.is_mt_stable: - stable_mass_transfer(bs, donor, accretor, self) - #adjusting triple is done in secular evolution code - else: - stopping_condition = common_envelope_phase(bs, donor, accretor, self) - - return stopping_condition - - #possible problem if companion or tertiary accretes significantly from this -# self.update_previous_stellar_parameters() #previous_mass, previous_radius for safety check -#------------------------- -#functions for contact mass transfer in a multiple / triple - -#change parameters assuming fully conservative mass transfer -def perform_mass_equalisation_for_contact(bs, donor, accretor, self): - if REPORT_FUNCTION_NAMES: - print('perform_mass_equalisation_for_contact') - if REPORT_BINARY_EVOLUTION: - print('Start of stable mass transfer of contact systems' ) - - if donor.mass != accretor.mass: - # if abs(donor.mass - accretor.mass)> 1e-4|units.MSun: #could be better. see if problems arise - new_mass = 0.5*(donor.mass + accretor.mass) - bs.semimajor_axis = bs.semimajor_axis * (donor.mass * accretor.mass / new_mass ** 2) ** 2 - - delta_mass_donor = new_mass - donor.mass - delta_mass_accretor = new_mass - accretor.mass - donor_in_stellar_code = donor.as_set().get_intersecting_subset_in(self.stellar_code.particles)[0] - accretor_in_stellar_code = accretor.as_set().get_intersecting_subset_in(self.stellar_code.particles)[0] - - donor_in_stellar_code.change_mass(delta_mass_donor, -1.0|units.yr) - accretor_in_stellar_code.change_mass(delta_mass_accretor, -1.0|units.yr) - self.stellar_code.evolve_model(minimum_time_step) #to get updates radii, not just inflation of stars due to accretion - self.copy_from_stellar() - self.update_stellar_parameters() #makes secular code use update values: mass equalisation happens instantaneously - - #set to synchronization - if self.include_CHE: - corotating_frequency = corotating_spin_angular_frequency_binary(bs.semimajor_axis, donor.mass, accretor.mass) - donor.spin_angular_frequency = corotating_frequency - accretor.spin_angular_frequency = corotating_frequency - donor.rotation_period = (2*np.pi/donor.spin_angular_frequency) - accretor.rotation_period = (2*np.pi/accretor.spin_angular_frequency) - self.channel_to_stellar.copy_attributes(['rotation_period']) #only defined when include_CHE - - self.secular_code.parameters.include_inner_RLOF_terms = False - self.secular_code.parameters.include_outer_RLOF_terms = False - - - -def contact_system(bs, star1, star2, self): - #if this implementation changes, then also change the is_mt_stable - if REPORT_FUNCTION_NAMES: - print("Contact system") - - bs.bin_type = bin_type['contact'] - self.save_snapshot() - self.check_RLOF() #@andris: is this necessary? - - #for now no W Ursae Majoris evolution - #so for now contact binaries merge in common_envelope_phase, and MS-MS contact binaries will have mass equalisation - if bs.is_mt_stable: # happens when star1 & star2 are both on MS - perform_mass_equalisation_for_contact(bs, bs.child1, bs.child2, self) - stopping_condition = True - else: - if star1.mass >= star2.mass: - stopping_condition = common_envelope_phase(bs, star1, star2, self) - else: - stopping_condition = common_envelope_phase(bs, star2, star1, self) - - return stopping_condition - - -#------------------------- -#functions for mass transfer in a multiple / triple - -def triple_stable_mass_transfer(bs, donor, accretor, self): - # mass transfer of both inner and outer orbit is not yet considered here - - # orbital evolution is being taken into account in secular_code - if REPORT_FUNCTION_NAMES: - print('Triple stable mass transfer') - - if bs.bin_type != bin_type['stable_mass_transfer']: - bs.bin_type = bin_type['stable_mass_transfer'] - self.save_snapshot() - else: - bs.bin_type = bin_type['stable_mass_transfer'] - - #implementation is missing - -def triple_common_envelope_phase(bs, donor, accretor, self): - # mass transfer of both inner and outer orbit is not yet considered here - - # orbital evolution is being taken into account in secular_code - if REPORT_FUNCTION_NAMES: - print('Triple common envelope') - - bs.bin_type = bin_type['common_envelope'] - self.save_snapshot() +from amuse.units import units, constants, quantities +import numpy as np +import sys +import scipy.integrate as integrate + +from tres.TRES_options import REPORT_BINARY_EVOLUTION, REPORT_FUNCTION_NAMES, REPORT_MASS_TRANSFER_STABILITY + +#constants +numerical_error = 1.e-6 +small_numerical_error = 1.e-10 +minimum_eccentricity = 1.e-5 + +const_common_envelope_efficiency = 4.0 #1.0, 4 for now for easier testing with SeBa +const_envelope_structure_parameter = 0.5 +const_common_envelope_efficiency_gamma = 1.75 + +stellar_types_compact_objects = [10,11,12,13,14]|units.stellar_type +stellar_types_giants = [2,3,4,5,6,8,9]|units.stellar_type +stellar_types_planetary_objects = [18,19]|units.stellar_type # planets & brown dwarfs + +stellar_types_SN_remnants = [13,14,15]|units.stellar_type # remnant types created through a supernova +stellar_types_remnants = [7,8,9,10,11,12,13,14,15]|units.stellar_type +stellar_types_dr = [2,4,7,8,9,10,11,12,13,14,15]|units.stellar_type #stars which go through a instantaneous radius change at formation; hertzsprung gap stars (small envelope perturbation) + horizontal branch stars + remnants + + + +#q_crit = 3. +#q_crit_giants_conv_env = 0.9 +nucleair_efficiency = 0.007 # nuc. energy production eff, Delta E = 0.007 Mc^2 + + + + + +#dictionaries +bin_type = { + 'unknown': 'unknown', + 'merger': 'merger', + 'disintegrated': 'disintegrated', + 'dyn_inst': 'dynamical_instability', + + 'detached': 'detached', + 'contact': 'contact', + 'collision': 'collision', + 'semisecular': 'semisecular', + 'rlof': 'rlof', #only used for stopping conditions + 'olof' : 'olof', #only used for stopping conditions + + 'stable_mass_transfer': 'stable_mass_transfer', + 'common_envelope': 'common_envelope', + 'common_envelope_energy_balance': 'common_envelope_energy_balance', + 'common_envelope_angular_momentum_balance': 'common_envelope_angular_momentum_balance', + 'double_common_envelope': 'double_common_envelope', + + } + +#------------------------- +#general functions +def roche_radius_dimensionless(M, m): + # Assure that the q is calculated in identical units. + unit = M.unit + # and that q itself has no unit + q = M.value_in(unit)/m.value_in(unit) + q13 = q**(1./3.) + q23 = q13**2 + return 0.49*q23/(0.6*q23 + np.log(1 + q13)) + +def roche_radius(bin, primary, self): + if not bin.is_star and primary.is_star: + return bin.semimajor_axis * roche_radius_dimensionless(primary.mass, self.get_mass(bin)-primary.mass) + + sys.exit('error in roche radius: Roche radius can only be determined in a binary') + +def L2_radius_dimensionless(M,m): + # approximation for l2 overflow + # see Marchant+ 2016 equation 2 + q = M/m + rl1 = roche_radius_dimensionless(M, m) + rl2_div_rl1 = 0.299 * np.arctan(1.83*q**0.397) + 1 + return rl2_div_rl1 * rl1 + +def L2_radius(bin, primary, self): + # note: this prescription is based on the Eggleton approximation for how to adjust a circular RL to an eccentric one + # may not be consistent with Sepinsky's method for eccentric RL (L1) + if not bin.is_star and primary.is_star: + return bin.semimajor_axis * L2_radius_dimensionless(primary.mass, self.get_mass(bin)-primary.mass)*(1-bin.eccentricity) + sys.exit('Error: L2 radius can only be determined in a binary') + +#for comparison with kozai timescale +def stellar_evolution_timescale(star): + if REPORT_FUNCTION_NAMES: + print("Stellar evolution timescale") + + if star.stellar_type in [0,1,7]|units.stellar_type: + return (0.1 * star.mass * nucleair_efficiency * constants.c**2 / star.luminosity).in_(units.Gyr) + elif star.stellar_type in stellar_types_compact_objects: + return np.inf|units.Myr + elif star.stellar_type in stellar_types_planetary_objects: + return np.inf|units.Myr + else: + return 0.1*star.age + + +#for mass transfer rate +def nuclear_evolution_timescale(star): + if REPORT_FUNCTION_NAMES: + print("Nuclear evolution timescale:") + + if star.stellar_type in [0,1,7]|units.stellar_type: + return (0.1 * star.mass * nucleair_efficiency * constants.c**2 / star.luminosity).in_(units.Gyr) + elif star.stellar_type in stellar_types_planetary_objects: +# print('nuclear evolution timescale for planetary objects requested') +# return np.inf|units.Myr + return dynamic_timescale(star) + else: #t_nuc ~ delta t * R/ delta R, other prescription gave long timescales in SeBa which destables the mass transfer + if star.time_derivative_of_radius <= (quantities.zero+numerical_error**2)|units.RSun/units.yr: + #when star is shrinking +# t_nuc = 0.1*main_sequence_time() # in SeBa + t_nuc = 0.1*star.age + else: + t_nuc = star.radius / star.time_derivative_of_radius #does not include the effect of mass loss on R + + return t_nuc + +def kelvin_helmholds_timescale(star): + if star.stellar_type in stellar_types_planetary_objects: +# print('thermal evolution timescale for planetary objects requested') + return dynamic_timescale(star) + + if REPORT_FUNCTION_NAMES: + print("KH timescale:", (constants.G*star.mass**2/star.radius/star.luminosity).in_(units.Myr)) + return constants.G*star.mass**2/star.radius/star.luminosity + +def dynamic_timescale(star): + if REPORT_FUNCTION_NAMES: + print("Dynamic timescale:", (np.sqrt(star.radius**3/star.mass/constants.G)[0]).in_(units.yr)) + return np.sqrt(star.radius**3/star.mass/constants.G) + +def corotating_spin_angular_frequency_binary(semi, m1, m2): + return 1./np.sqrt(semi**3/constants.G / (m1+m2)) + +#Hurley, Pols en Tout 2000, eq 107-108 +def lang_spin_angular_frequency(star): + v_rot = 330*star.mass.value_in(units.MSun)**3.3/(15.0+star.mass.value_in(units.MSun)**3.45) + w = 45.35 * v_rot/star.radius.value_in(units.RSun) + return w|1./units.yr + +def break_up_angular_frequency(object): + return np.sqrt( constants.G * object.mass / object.radius ) / object.radius + + +def criticial_angular_frequency_CHE(m, Z): + #angular frequency of spin for CHE threshold + #Fitting formula for CHE from Riley+ 2021 + + a_coeff = np.array([5.7914 * 10 ** - 4, -1.9196 * 10 ** - 6, + -4.0602 * 10 ** - 7, 1.0150 * 10 ** - 8, + -9.1792 * 10 ** - 11, 2.9051 * 10 ** - 13]) + mass_power = np.linspace(0,5,6) + omega_at_z_0d004 = np.sum(a_coeff * m.value_in(units.MSun)** mass_power / m.value_in(units.MSun) ** 0.4) + omega_crit = omega_at_z_0d004/(0.09 * np.log(Z/0.004) + 1) |1./units.s + return omega_crit + + +def copy_outer_orbit_to_inner_orbit(bs, self): + if REPORT_FUNCTION_NAMES: + print('Copy_outer_orbit_to_inner_orbit') + + if self.is_triple(): + bs.semimajor_axis = self.triple.semimajor_axis + bs.eccentricity = self.triple.eccentricity + bs.argument_of_pericenter = self.triple.argument_of_pericenter + bs.longitude_of_ascending_node = self.triple.longitude_of_ascending_node + bs.mass_transfer_rate = self.triple.mass_transfer_rate + bs.accretion_efficiency_mass_transfer, = self.triple.accretion_efficiency_mass_transfer, + bs.accretion_efficiency_wind_child1_to_child2, = self.triple.accretion_efficiency_wind_child1_to_child2, + bs.accretion_efficiency_wind_child2_to_child1, = self.triple.accretion_efficiency_wind_child2_to_child1, + bs.specific_AM_loss_mass_transfer, = self.triple.specific_AM_loss_mass_transfer, + bs.is_mt_stable = self.triple.is_mt_stable + + self.triple.semimajor_axis = 1e100|units.RSun + self.triple.eccentricity = 0 + + + + +def copy_outer_star_to_accretor(self): + if REPORT_FUNCTION_NAMES: + print('Copy_outer_star_to_accretor') + + if self.is_triple(): + if self.triple.child1.is_star: + tertiary_star = self.triple.child1 + bs = self.triple.child2 + else: + tertiary_star = self.triple.child2 + bs = self.triple.child1 + + + if not bs.child1.is_donor: + bs.child1 = tertiary_star + else: + bs.child2 = tertiary_star + + +#------------------------- + +#------------------------- +# functions for mass transfer in a binary + +def perform_inner_collision(self): + if self.is_triple(): + if self.triple.child1.is_star: + self.triple.child2 + else: + self.triple.child1 + + # smaller star is added to big star + if bs.child1.radius >= bs.child2.radius: + donor = bs.child1 + accretor = bs.child2 + else: + donor = bs.child2 + accretor = bs.child1 + + donor_in_stellar_code = donor.as_set().get_intersecting_subset_in(self.stellar_code.particles)[0] + accretor_in_stellar_code = accretor.as_set().get_intersecting_subset_in(self.stellar_code.particles)[0] + + #no additional mass and Jspin loss from merged object for now + J_spin_donor_previous = self.spin_angular_momentum(donor) + J_spin_accretor_previous = self.spin_angular_momentum(accretor) + J_orbit = self.orbital_angular_momentum(bs) + J_spin_new = J_spin_donor_previous + J_spin_accretor_previous + J_orbit + + #merger + donor_in_stellar_code.merge_with_other_star(accretor_in_stellar_code) + self.copy_from_stellar() + + donor.moment_of_inertia_of_star = self.moment_of_inertia(donor) + + #assuming conservation of total angular momentum of the inner binary + spin_angular_frequency = J_spin_new / donor.moment_of_inertia_of_star + critical_spin_angular_frequency = np.sqrt(constants.G * donor.mass/donor.radius**3) + donor.spin_angular_frequency = min(donor.spin_angular_frequency, critical_spin_angular_frequency) + + self.stellar_code.particles.remove_particle(accretor) + accretor.mass = 0|units.MSun # necessary for adjust_system_after_ce_in_inner_binary + #adjust outer orbit, needs to be before the system becomes a binary + #and copy to inner orbit + # weird structure necessary for secular code -> outer orbit is redundant + adjust_system_after_ce_in_inner_binary(bs, self) + copy_outer_orbit_to_inner_orbit(bs, self) + copy_outer_star_to_accretor(self) + #functions are skipped in binaries, needs to be checked if this works well + + self.secular_code.parameters.ignore_tertiary = True + self.secular_code.parameters.check_for_dynamical_stability = False + self.secular_code.parameters.check_for_outer_collision = False + self.secular_code.parameters.check_for_outer_RLOF = False + + bs.bin_type = bin_type['collision'] + self.save_snapshot() # just to note that it the system has merged + +#use of stopping condition in this way (similar to perform inner merger) is not necessary. +#TRES.py takes care of it +# if self.check_stopping_conditions_stellar_interaction()==False: +# print('stopping conditions stellar interaction') +# return False + + self.check_RLOF() + if self.has_donor(): + print(self.triple.child2.child1.mass, self.triple.child2.child2.mass, self.triple.child2.semimajor_axis, self.triple.child2.eccentricity, self.triple.child2.child1.is_donor, self.triple.child2.child2.is_donor) + print(self.triple.child1.mass, self.triple.semimajor_axis, self.triple.eccentricity, self.triple.child1.is_donor) + sys.exit("error in adjusting triple after collision: RLOF") + + donor.is_donor = False + bs.is_mt_stable = True + bs.bin_type = bin_type['detached'] + + donor.spin_angular_frequency = corotating_spin_angular_frequency_binary(bs.semimajor_axis, bs.child1.mass, bs.child2.mass) + +#use of stopping condition in this way (similar to perform inner merger) is not necessary +#TRES.py takes care of it +# return True + +def perform_inner_merger(bs, donor, accretor, self): + if REPORT_BINARY_EVOLUTION: + print('Merger in inner binary through common envelope phase') + + donor_in_stellar_code = donor.as_set().get_intersecting_subset_in(self.stellar_code.particles)[0] + accretor_in_stellar_code = accretor.as_set().get_intersecting_subset_in(self.stellar_code.particles)[0] + + #no additional mass and Jspin loss from merged object for now + J_spin_donor_previous = self.spin_angular_momentum(donor) + J_spin_accretor_previous = self.spin_angular_momentum(accretor) + J_orbit = self.orbital_angular_momentum(bs) + J_spin_new = J_spin_donor_previous + J_spin_accretor_previous + J_orbit + + #merger + donor_in_stellar_code.merge_with_other_star(accretor_in_stellar_code) + self.copy_from_stellar() + + donor.moment_of_inertia_of_star = self.moment_of_inertia(donor) + + #assuming conservation of total angular momentum of the inner binary + spin_angular_momentum = J_spin_new / donor.moment_of_inertia_of_star + critical_spin_angular_frequency = np.sqrt(constants.G * donor.mass/donor.radius**3) + donor.spin_angular_frequency = min(donor.spin_angular_frequency, critical_spin_angular_frequency) + + self.stellar_code.particles.remove_particle(accretor) + accretor.mass = 0|units.MSun # necessary for adjust_system_after_ce_in_inner_binary + #adjust outer orbit, needs to be before the system becomes a binary + #and copy to inner orbit + # weird structure necessary for secular code -> outer orbit is redundant + adjust_system_after_ce_in_inner_binary(bs, self) + copy_outer_orbit_to_inner_orbit(bs, self) + copy_outer_star_to_accretor(self) + #functions are skipped in binaries, needs to be checked if this works well + + self.secular_code.parameters.ignore_tertiary = True + self.secular_code.parameters.check_for_dynamical_stability = False + self.secular_code.parameters.check_for_outer_collision = False + self.secular_code.parameters.check_for_outer_RLOF = False + bs.bin_type = bin_type['merger'] + self.save_snapshot() # just to note that the system has merged + + if self.check_stopping_conditions_stellar_interaction()==False: + print('stopping conditions stellar interaction') + return False + else: + return True + +# print(self.secular_code.give_roche_radii(self.triple),) +# print(roche_radius(self.triple.child2, self.triple.child2.child1, self), roche_radius(self.triple.child2, self.triple.child2.child2, self)) +# +# print(donor.spin_angular_frequency, corotating_spin_angular_frequency_binary(bs.semimajor_axis, bs.child1.mass, bs.child2.mass), critical_spin_angular_frequency) +# donor.spin_angular_frequency = corotating_spin_angular_frequency_binary(bs.semimajor_axis, bs.child1.mass, bs.child2.mass) + + + +def common_envelope_efficiency(donor, accretor): + return const_common_envelope_efficiency + +def envelope_structure_parameter(donor): + return const_envelope_structure_parameter + +def common_envelope_efficiency_gamma(donor, accretor): + return const_common_envelope_efficiency_gamma + + + +# ang.mom balance: \Delta J = \gamma * J * \Delta M / M +# See Eq. 5 of Nelemans VYPZ 2000, 360, 1011 A&A +def common_envelope_angular_momentum_balance(bs, donor, accretor, self): + if REPORT_FUNCTION_NAMES: + print('Common envelope angular momentum balance') + + if REPORT_BINARY_EVOLUTION: + if bs.eccentricity > 0.05: + print('gamma common envelope in eccentric binary') + print('Before common envelope angular momentum balance' ) + self.print_binary(bs) + + bs.bin_type = bin_type['common_envelope_angular_momentum_balance'] + self.save_snapshot() + + gamma = common_envelope_efficiency_gamma(donor, accretor) + J_init = np.sqrt(bs.semimajor_axis) * (donor.mass * accretor.mass) / np.sqrt(donor.mass + accretor.mass) * np.sqrt(1-bs.eccentricity**2) + J_f_over_sqrt_a_new = (donor.core_mass * accretor.mass) / np.sqrt(donor.core_mass + accretor.mass) + J_lost = gamma * (donor.mass-donor.core_mass) * J_init/(donor.mass + accretor.mass) + sqrt_a_new = max(0.|units.RSun**0.5, (J_init -J_lost)/J_f_over_sqrt_a_new) + a_new = pow(sqrt_a_new, 2) + + Rl_donor_new = roche_radius_dimensionless(donor.core_mass, accretor.mass)*a_new + Rl_accretor_new = roche_radius_dimensionless(accretor.mass, donor.core_mass)*a_new + if REPORT_BINARY_EVOLUTION: + print('donor:', donor.radius, donor.core_radius, Rl_donor_new) + print('accretor:', accretor.radius, accretor.core_radius, Rl_accretor_new) + + if (donor.core_radius > Rl_donor_new) or (accretor.radius > Rl_accretor_new): + stopping_condition = perform_inner_merger(bs, donor, accretor, self) + if not stopping_condition: #stellar interaction + return False + else: + donor_in_stellar_code = donor.as_set().get_intersecting_subset_in(self.stellar_code.particles)[0] + #reduce_mass not subtrac mass, want geen adjust_donor_radius + #check if star changes type + donor_in_stellar_code.change_mass(-1*(donor.mass-donor.core_mass+(small_numerical_error|units.MSun)), 0.|units.yr) + self.copy_from_stellar() + + donor.moment_of_inertia_of_star = self.moment_of_inertia(donor) + accretor.moment_of_inertia_of_star = self.moment_of_inertia(accretor) + + bs.semimajor_axis = a_new + bs.eccentricity = minimum_eccentricity + + #set to synchronization + corotating_frequency = corotating_spin_angular_frequency_binary(a_new, donor.mass, accretor.mass) + donor.spin_angular_frequency = corotating_frequency + accretor.spin_angular_frequency = corotating_frequency + + self.check_RLOF() + if self.has_donor(): + print(self.triple.child2.child1.mass, self.triple.child2.child2.mass, self.triple.child2.child1.radius, self.triple.child2.child2.radius,self.triple.child2.semimajor_axis, self.triple.child2.eccentricity, self.triple.child2.child1.is_donor, self.triple.child2.child2.is_donor) + print(self.triple.child2.child1.core_mass, self.triple.child2.child1.mass-self.triple.child2.child1.core_mass, self.triple.child2.child1.stellar_type) + print(self.triple.child1.mass, self.triple.semimajor_axis, self.triple.eccentricity, self.triple.child1.is_donor) + +# sys.exit("error in adjusting triple after gamma CE: RLOF") + stopping_condition = perform_inner_merger(bs, donor, accretor, self) + if not stopping_condition: #stellar interaction + return False + +# adjusting of stellar system +# in previous case of merger, the adjustment is done there as mass may be lost during the merger + adjust_system_after_ce_in_inner_binary(bs, self) + + + + donor.is_donor = False + bs.is_mt_stable = True + bs.bin_type = bin_type['detached'] + self.instantaneous_evolution = True #skip secular evolution + + return True + +#Following Webbink 1984 +def common_envelope_energy_balance(bs, donor, accretor, self): + if REPORT_FUNCTION_NAMES: + print('Common envelope energy balance') + + if REPORT_BINARY_EVOLUTION: + print('Before common envelope energy balance' ) + self.print_binary(bs) + + bs.bin_type = bin_type['common_envelope_energy_balance'] + self.save_snapshot() + + alpha = common_envelope_efficiency(donor, accretor) + lambda_donor = envelope_structure_parameter(donor) + + Rl_donor = roche_radius(bs, donor, self) + donor_radius = min(donor.radius, Rl_donor) + + #based on Glanz & Perets 2021 2021MNRAS.507.2659G + #eccentric CE -> end result depends on pericenter distance more than semi-major axis + pericenter_init = bs.semimajor_axis * (1-bs.eccentricity) + orb_energy_new = donor.mass * (donor.mass-donor.core_mass) / (alpha * lambda_donor * donor_radius) + donor.mass * accretor.mass/2/pericenter_init + a_new = donor.core_mass * accretor.mass / 2 / orb_energy_new +# a_new = bs.semimajor_axis * (donor.core_mass/donor.mass) / (1. + (2.*(donor.mass-donor.core_mass)*bs.semimajor_axis/(alpha_lambda*donor_radius*accretor.mass))) + + Rl_donor_new = roche_radius_dimensionless(donor.core_mass, accretor.mass)*a_new + Rl_accretor_new = roche_radius_dimensionless(accretor.mass, donor.core_mass)*a_new + if REPORT_BINARY_EVOLUTION: + print('donor:', donor.radius, donor.core_radius, Rl_donor_new) + print('accretor:', accretor.radius, accretor.core_radius, Rl_accretor_new) + + if (donor.core_radius > Rl_donor_new) or (accretor.radius > Rl_accretor_new): + stopping_condition = perform_inner_merger(bs, donor, accretor, self) + if not stopping_condition: #stellar interaction + return False + else: + donor_in_stellar_code = donor.as_set().get_intersecting_subset_in(self.stellar_code.particles)[0] + #reduce_mass not subtrac mass, want geen adjust_donor_radius + #check if star changes type + donor_in_stellar_code.change_mass(-1*(donor.mass-donor.core_mass+(small_numerical_error|units.MSun)), 0.|units.yr) + self.copy_from_stellar() + + donor.moment_of_inertia_of_star = self.moment_of_inertia(donor) + accretor.moment_of_inertia_of_star = self.moment_of_inertia(accretor) + + bs.semimajor_axis = a_new + bs.eccentricity = minimum_eccentricity + + #set to synchronization + corotating_frequency = corotating_spin_angular_frequency_binary(a_new, donor.mass, accretor.mass) + donor.spin_angular_frequency = corotating_frequency + accretor.spin_angular_frequency = corotating_frequency + + + self.check_RLOF() + if self.has_donor(): + print(self.triple.child2.child1.mass, self.triple.child2.child2.mass, self.triple.child2.semimajor_axis, self.triple.child2.eccentricity, self.triple.child2.child1.is_donor, self.triple.child2.child2.is_donor) + print(self.triple.child1.mass, self.triple.semimajor_axis, self.triple.eccentricity, self.triple.child1.is_donor) + + # sys.exit("error in adjusting triple after alpha CE: RLOF") + stopping_condition = perform_inner_merger(bs, donor, accretor, self) + if not stopping_condition: #stellar interaction + return False + +# adjusting of stellar system +# in previous case of merger, the adjustment is done there as mass may be lost during the merger + adjust_system_after_ce_in_inner_binary(bs, self) + + donor.is_donor = False + bs.is_mt_stable = True + bs.bin_type = bin_type['detached'] + self.instantaneous_evolution = True #skip secular evolution + return True + +# See appendix of Nelemans YPZV 2001, 365, 491 A&A +def double_common_envelope_energy_balance(bs, donor, accretor, self): + if REPORT_FUNCTION_NAMES: + print('Double common envelope energy balance') + + if REPORT_BINARY_EVOLUTION: + print('Before double common envelope energy balance' ) + self.print_binary(bs) + + bs.bin_type = bin_type['double_common_envelope'] + self.save_snapshot() + + alpha = common_envelope_efficiency(donor, accretor) + lambda_donor = envelope_structure_parameter(donor) + lambda_accretor = envelope_structure_parameter(accretor) + + Rl_donor = roche_radius(bs, donor, self) + donor_radius = min(donor.radius, Rl_donor) + accretor_radius = accretor.radius + + + #based on Glanz & Perets 2021 2021MNRAS.507.2659G + #eccentric CE -> end result depends on pericenter distance more than semi-major axis + pericenter_init = bs.semimajor_axis * (1-bs.eccentricity) + orb_energy_new = donor.mass * (donor.mass-donor.core_mass) / (alpha * lambda_donor * donor_radius) + accretor.mass * (accretor.mass-accretor.core_mass) / (alpha * lambda_accretor * accretor_radius) + donor.mass * accretor.mass/2/pericenter_init + a_new = donor.core_mass * accretor.core_mass / 2 / orb_energy_new + + Rl_donor_new = roche_radius_dimensionless(donor.core_mass, accretor.core_mass)*a_new + Rl_accretor_new = roche_radius_dimensionless(accretor.core_mass, donor.core_mass)*a_new + if REPORT_BINARY_EVOLUTION: + print('donor:', donor.radius, donor.core_radius, Rl_donor_new) + print('accretor:', accretor.radius, accretor.core_radius, Rl_accretor_new) + + if (donor.core_radius > Rl_donor_new) or (accretor.core_radius > Rl_accretor_new): + stopping_condition = perform_inner_merger(bs, donor, accretor, self) + if not stopping_condition: #stellar interaction + return False + else: + #reduce_mass not subtrac mass, want geen adjust_donor_radius + #check if star changes type + + donor_in_stellar_code = donor.as_set().get_intersecting_subset_in(self.stellar_code.particles)[0] + donor_in_stellar_code.change_mass(-1*(donor.mass-donor.core_mass+(small_numerical_error|units.MSun)), 0.|units.yr) + accretor_in_stellar_code = accretor.as_set().get_intersecting_subset_in(self.stellar_code.particles)[0] + accretor_in_stellar_code.change_mass(-1*(accretor.mass-accretor.core_mass), 0.|units.yr) + self.copy_from_stellar() + + + donor.moment_of_inertia_of_star = self.moment_of_inertia(donor) + accretor.moment_of_inertia_of_star = self.moment_of_inertia(accretor) + + bs.semimajor_axis = a_new + bs.eccentricity = minimum_eccentricity + + #set to synchronization + corotating_frequency = corotating_spin_angular_frequency_binary(a_new, donor.mass, accretor.mass) + donor.spin_angular_frequency = corotating_frequency + accretor.spin_angular_frequency = corotating_frequency + + self.check_RLOF() + if self.has_donor(): + print(self.triple.child2.child1.mass, self.triple.child2.child2.mass, self.triple.child2.semimajor_axis, self.triple.child2.eccentricity, self.triple.child2.child1.is_donor, self.triple.child2.child2.is_donor) + print(self.triple.child1.mass, self.triple.semimajor_axis, self.triple.eccentricity, self.triple.child1.is_donor) + + # sys.exit("error in adjusting triple after double CE: RLOF") + stopping_condition = perform_inner_merger(bs, donor, accretor, self) + if not stopping_condition: #stellar interaction + return False + +# adjusting of stellar system +# in previous case of merger, the adjustment is done there as mass may be lost during the merger + adjust_system_after_ce_in_inner_binary(bs, self) + + donor.is_donor = False + bs.is_mt_stable = True + bs.bin_type = bin_type['detached'] + self.instantaneous_evolution = True #skip secular evolution + return True + +def common_envelope_phase(bs, donor, accretor, self): + stopping_condition = True + + if REPORT_FUNCTION_NAMES: + print('Common envelope phase', self.which_common_envelope) + print('donor:', donor.stellar_type) + print('accretor:', accretor.stellar_type) + + if donor.stellar_type not in stellar_types_giants and accretor.stellar_type not in stellar_types_giants: +# possible options: MS+MS, MS+remnant, remnant+remnant, +# HeMS+HeMS, HeMS+MS, HeMS+remnant + bs.bin_type = bin_type['common_envelope'] + self.save_snapshot() + stopping_condition = perform_inner_merger(bs, donor, accretor, self) + if not stopping_condition: #stellar interaction + return False + + self.check_RLOF() + if self.has_donor(): + print(self.triple.child2.child1.mass, self.triple.child2.child2.mass, self.triple.child2.semimajor_axis, self.triple.child2.eccentricity, self.triple.child2.child1.is_donor, self.triple.child2.child2.is_donor) + print(self.triple.child1.mass, self.triple.semimajor_axis, self.triple.eccentricity, self.triple.child1.is_donor) + print(self.triple.child2.child1.radius, self.triple.child2.child2.radius,self.triple.child1.radius) + print(self.secular_code.give_roche_radii(self.triple)) + print('binary Roche lobe radii:', roche_radius(bs, bs.child1, self), roche_radius(bs, bs.child2, self)) + +# sys.exit("error in adjusting system after CE: RLOF") + stopping_condition = perform_inner_merger(bs, donor, accretor, self) + if not stopping_condition: #stellar interaction + return False + + donor.is_donor = False + bs.is_mt_stable = True + bs.bin_type = bin_type['detached'] + self.instantaneous_evolution = True #skip secular evolution + + return True + + + + if self.which_common_envelope == 0: + if donor.stellar_type in stellar_types_giants and accretor.stellar_type in stellar_types_giants: + stopping_condition = double_common_envelope_energy_balance(bs, donor, accretor, self) + else: + stopping_condition = common_envelope_energy_balance(bs, donor, accretor, self) + elif self.which_common_envelope == 1: + if donor.stellar_type in stellar_types_giants and accretor.stellar_type in stellar_types_giants: + stopping_condition = double_common_envelope_energy_balance(bs, donor, accretor, self) + else: + stopping_condition = common_envelope_angular_momentum_balance(bs, donor, accretor, self) + elif self.which_common_envelope == 2: + Js_d = self.spin_angular_momentum(donor) + Js_a = self.spin_angular_momentum(accretor) + Jb = self.orbital_angular_momentum(bs) + Js = max(Js_d, Js_a) +# print("Darwin Riemann instability? donor/accretor:", Js_d, Js_a, Jb, Jb/3.) + if donor.stellar_type in stellar_types_giants and accretor.stellar_type in stellar_types_giants: + #giant+giant + stopping_condition = double_common_envelope_energy_balance(bs, donor, accretor, self) + elif donor.stellar_type in stellar_types_compact_objects or accretor.stellar_type in stellar_types_compact_objects: + #giant+remnant + stopping_condition = common_envelope_energy_balance(bs, donor, accretor, self) + elif Js >= Jb/3. : + #darwin riemann instability + stopping_condition = common_envelope_energy_balance(bs, donor, accretor, self) + else: + #giant+normal(non-giant, non-remnant) + stopping_condition = common_envelope_angular_momentum_balance(bs, donor, accretor, self) + + return stopping_condition + + +def adiabatic_expansion_due_to_mass_loss(a_i, Md_f, Md_i, Ma_f, Ma_i): + + d_Md = Md_f - Md_i #negative mass loss rate + d_Ma = Ma_f - Ma_i #positive mass accretion rate + + Mt_f = Md_f + Ma_f + Mt_i = Md_i + Ma_i + + if d_Md < 0|units.MSun and d_Ma >= 0|units.MSun: + eta = d_Ma / d_Md + a_f = a_i * ((Md_f/Md_i)**eta * (Ma_f/Ma_i))**-2 * Mt_i/Mt_f + return a_f + return a_i + + +def adjust_system_after_ce_in_inner_binary(bs, self): + # Assumption: Unstable mass transfer (common-envelope phase) in the inner binary, affects the outer binary as a wind. + # Instanteneous effect + if REPORT_FUNCTION_NAMES: + print('Adjust system after ce in inner binary') + + if self.is_triple(): + M_com_after_ce = self.get_mass(bs) + M_com_before_ce = bs.previous_mass + + if self.triple.child1.is_star: + tertiary_star = self.triple.child1 + else: + tertiary_star = self.triple.child2 + # accretion_efficiency + M_accretor_before_ce = tertiary_star.mass + M_accretor_after_ce = tertiary_star.mass + + a_new = adiabatic_expansion_due_to_mass_loss(self.triple.semimajor_axis, M_com_after_ce, M_com_before_ce, M_accretor_after_ce, M_accretor_before_ce) + self.triple.semimajor_axis = a_new +# print('outer orbit', a_new) + + +# nice but difficult to update self.triple +# system = bs +# while True: +# try: +# system = system.parent +# if not system.child1.is_star and system.child2.is_star: +# system = adjust_triple_after_ce_in_inner_binary(system, system.child1, system.child2, self) +# elif not system.child2.is_star and system.child1.is_star: +# system = adjust_triple_after_ce_in_inner_binary(system, system.child2, system.child1, self) +# else: +# print('adjust_system_after_ce_in_inner_binary: type of system unknown') +# exit(2) +# +# except AttributeError: +# #when there is no parent +# break +# + + +def stable_mass_transfer(bs, donor, accretor, self): + # orbital evolution is being taken into account in secular_code + if REPORT_FUNCTION_NAMES: + print('Stable mass transfer') + + if bs.bin_type != bin_type['stable_mass_transfer']: + bs.bin_type = bin_type['stable_mass_transfer'] + self.save_snapshot() + else: + bs.bin_type = bin_type['stable_mass_transfer'] + + self.secular_code.parameters.check_for_inner_RLOF = False + self.secular_code.parameters.include_spin_radius_mass_coupling_terms_star1 = False + self.secular_code.parameters.include_spin_radius_mass_coupling_terms_star2 = False + + Md = donor.mass + Ma = accretor.mass + + dt = self.triple.time - self.previous_time + dm_desired = bs.mass_transfer_rate * dt + if REPORT_FUNCTION_NAMES: + print(bs.mass_transfer_rate, dt, dm_desired) + donor_in_stellar_code = donor.as_set().get_intersecting_subset_in(self.stellar_code.particles)[0] + donor_in_stellar_code.change_mass(dm_desired+(small_numerical_error|units.MSun), dt) + + # dm != dm_desired e.g. when the envelope of the star becomes empty + dm = donor_in_stellar_code.mass - Md + bs.part_dt_mt = 1. + if dm - dm_desired > numerical_error|units.MSun: +# print('WARNING:the envelope is empty, mass transfer rate should be lower or dt should be smaller... ') + bs.part_dt_mt = dm/dm_desired + + # there is an implicit assumption in change_mass that the accreted mass is of solar composition (hydrogen) + accretor_in_stellar_code = accretor.as_set().get_intersecting_subset_in(self.stellar_code.particles)[0] +# accretor_in_stellar_code.change_mass(dm, dt) + # for now, only conservative mass transfer + accretor_in_stellar_code.change_mass(-1.*dm, -1.*dt) + #if you want seba to determine the accretion efficiency, use + #accretor_in_stellar_code.change_mass(-1.*dm, dt) + #note doesnt work perfectly, as seba is oblivious to the roche lobe radius + + + #to adjust radius to mass loss and increase + self.stellar_code.evolve_model(self.triple.time) + self.copy_from_stellar() + + self.update_stellar_parameters() + + Md_new = donor.mass + Ma_new = accretor.mass + accretion_efficiency = (Ma_new-Ma)/(Md-Md_new) + if abs(accretion_efficiency - 1.0) > numerical_error and abs(Md-Md_new - -1.*(Ma-Ma_new)) > numerical_error |units.MSun: + self.save_snapshot() + print('stable_mass_transfer: non conservative mass transfer') + print(Md, Ma, donor.previous_mass, accretor.previous_mass) + print(Md_new, Ma_new, Md-Md_new, Ma-Ma_new, accretion_efficiency) + print(donor.stellar_type, accretor.stellar_type) + sys.exit('error in stable mass transfer') + + bs.accretion_efficiency_mass_transfer = accretion_efficiency + + corotation_spin = corotating_spin_angular_frequency_binary(bs.semimajor_axis, donor.mass, accretor.mass) + donor.spin_angular_frequency = corotation_spin + accretor.spin_angular_frequency = corotation_spin + + + +def semi_detached(bs, donor, accretor, self): +#only for binaries (consisting of two stars) + if REPORT_FUNCTION_NAMES: + print('Semi-detached') + print(bs.semimajor_axis, donor.mass, accretor.mass, donor.stellar_type, accretor.stellar_type, bs.is_mt_stable) + + + stopping_condition = True + if bs.is_mt_stable: + stable_mass_transfer(bs, donor, accretor, self) + #adjusting triple is done in secular evolution code + else: + stopping_condition = common_envelope_phase(bs, donor, accretor, self) + + return stopping_condition + + #possible problem if companion or tertiary accretes significantly from this +# self.update_previous_stellar_parameters() #previous_mass, previous_radius for safety check +#------------------------- +#functions for contact mass transfer in a multiple / triple + +#change parameters assuming fully conservative mass transfer +def perform_mass_equalisation_for_contact(bs, donor, accretor, self): + if REPORT_FUNCTION_NAMES: + print('perform_mass_equalisation_for_contact') + if REPORT_BINARY_EVOLUTION: + print('Start of stable mass transfer of contact systems' ) + + if donor.mass != accretor.mass: + # if abs(donor.mass - accretor.mass)> 1e-4|units.MSun: #could be better. see if problems arise + new_mass = 0.5*(donor.mass + accretor.mass) + bs.semimajor_axis = bs.semimajor_axis * (donor.mass * accretor.mass / new_mass ** 2) ** 2 + + delta_mass_donor = new_mass - donor.mass + delta_mass_accretor = new_mass - accretor.mass + donor_in_stellar_code = donor.as_set().get_intersecting_subset_in(self.stellar_code.particles)[0] + accretor_in_stellar_code = accretor.as_set().get_intersecting_subset_in(self.stellar_code.particles)[0] + + donor_in_stellar_code.change_mass(delta_mass_donor, -1.0|units.yr) + accretor_in_stellar_code.change_mass(delta_mass_accretor, -1.0|units.yr) + self.stellar_code.evolve_model(minimum_time_step) #to get updates radii, not just inflation of stars due to accretion + self.copy_from_stellar() + self.update_stellar_parameters() #makes secular code use update values: mass equalisation happens instantaneously + + #set to synchronization + if self.include_CHE: + corotating_frequency = corotating_spin_angular_frequency_binary(bs.semimajor_axis, donor.mass, accretor.mass) + donor.spin_angular_frequency = corotating_frequency + accretor.spin_angular_frequency = corotating_frequency + donor.rotation_period = (2*np.pi/donor.spin_angular_frequency) + accretor.rotation_period = (2*np.pi/accretor.spin_angular_frequency) + self.channel_to_stellar.copy_attributes(['rotation_period']) #only defined when include_CHE + + self.secular_code.parameters.include_inner_RLOF_terms = False + self.secular_code.parameters.include_outer_RLOF_terms = False + + + +def contact_system(bs, star1, star2, self): + #if this implementation changes, then also change the is_mt_stable + if REPORT_FUNCTION_NAMES: + print("Contact system") + + bs.bin_type = bin_type['contact'] + self.save_snapshot() + self.check_RLOF() #@andris: is this necessary? + + #for now no W Ursae Majoris evolution + #so for now contact binaries merge in common_envelope_phase, and MS-MS contact binaries will have mass equalisation + if bs.is_mt_stable: # happens when star1 & star2 are both on MS + perform_mass_equalisation_for_contact(bs, bs.child1, bs.child2, self) + stopping_condition = True + else: + if star1.mass >= star2.mass: + stopping_condition = common_envelope_phase(bs, star1, star2, self) + else: + stopping_condition = common_envelope_phase(bs, star2, star1, self) + + return stopping_condition + + +#------------------------- +#functions for mass transfer in a multiple / triple + +def triple_stable_mass_transfer(bs, donor, accretor, self): + # mass transfer of both inner and outer orbit is not yet considered here + + # orbital evolution is being taken into account in secular_code + if REPORT_FUNCTION_NAMES: + print('Triple stable mass transfer') + + if bs.bin_type != bin_type['stable_mass_transfer']: + bs.bin_type = bin_type['stable_mass_transfer'] + self.save_snapshot() + else: + bs.bin_type = bin_type['stable_mass_transfer'] + + #implementation is missing + +def triple_common_envelope_phase(bs, donor, accretor, self): + # mass transfer of both inner and outer orbit is not yet considered here + + # orbital evolution is being taken into account in secular_code + if REPORT_FUNCTION_NAMES: + print('Triple common envelope') + + bs.bin_type = bin_type['common_envelope'] + self.save_snapshot() - #implementation is missing - -#when the tertiary star transfers mass to the inner binary -def outer_mass_transfer(bs, donor, accretor, self): -#only for stellar systems consisting of a star and a binary - if REPORT_FUNCTION_NAMES: - print('Triple mass transfer') - bs.semimajor_axis, donor.mass, self.get_mass(accretor), donor.stellar_type - - - if bs.is_mt_stable: - triple_stable_mass_transfer(bs, donor, accretor, self) - - # possible the outer binary needs part_dt_mt as well. - #adjusting triple is done in secular evolution code - else: - triple_common_envelope_phase(bs, donor, accretor, self) + #implementation is missing + +#when the tertiary star transfers mass to the inner binary +def outer_mass_transfer(bs, donor, accretor, self): +#only for stellar systems consisting of a star and a binary + if REPORT_FUNCTION_NAMES: + print('Triple mass transfer') + bs.semimajor_axis, donor.mass, self.get_mass(accretor), donor.stellar_type + + + if bs.is_mt_stable: + triple_stable_mass_transfer(bs, donor, accretor, self) + + # possible the outer binary needs part_dt_mt as well. + #adjusting triple is done in secular evolution code + else: + triple_common_envelope_phase(bs, donor, accretor, self) #stopping condition 0:False, 1:True, -1: calculate through outer mass transfer - effect on inner & outer orbit is taken care off here. return -1 - -#------------------------- - -#------------------------- -#Functions for detached evolution -## Calculates stellar wind velocoty. -## Steller wind velocity is 2.5 times stellar escape velocity -#def wind_velocity(star): -# v_esc2 = constants.G * star.mass / star.radius -# return 2.5*np.sqrt(v_esc2) -#} -# -# -## Bondi, H., and Hoyle, F., 1944, MNRAS 104, 273 (wind accretion. -## Livio, M., Warner, B., 1984, The Observatory 104, 152. -#def accretion_efficiency_from_stellar_wind(accretor, donor): -#velocity needs to be determined -> velocity average? -# why is BH dependent on ecc as 1/np.sqrt(1-e**2) - -# alpha_wind = 0.5 -# v_wind = wind_velocity(donor) -# acc_radius = (constants.G*accretor.mass)**2/v_wind**4 -# -# wind_acc = alpha_wind/np.sqrt(1-bs.eccentricity**2) / bs.semimajor_axis**2 -# v_factor = 1/((1+(velocity/v_wind)**2)**3./2.) -# mass_fraction = acc_radius*wind_acc*v_factor -# -# print('mass_fraction:', mass_fraction) -## mass_fraction = min(0.9, mass_fraction) -# - - - -def detached(bs, self): - # orbital evolution is being taken into account in secular_code - if REPORT_FUNCTION_NAMES: - print('Detached') - - if bs.bin_type == bin_type['detached'] or bs.bin_type == bin_type['unknown']: - bs.bin_type = bin_type['detached'] - else: - bs.bin_type = bin_type['detached'] - self.save_snapshot() - - # wind mass loss is done by stellar_code - # wind accretion here: - # update accretion efficiency of wind mass loss - if self.is_binary(bs): - - bs.accretion_efficiency_wind_child1_to_child2 = 0.0 - bs.accretion_efficiency_wind_child2_to_child1 = 0.0 - -# child1_in_stellar_code = bs.child1.as_set().get_intersecting_subset_in(self.stellar_code.particles)[0] -# child2_in_stellar_code = bs.child2.as_set().get_intersecting_subset_in(self.stellar_code.particles)[0] -# -# dt = self.triple.time - self.previous_time -# dm_child1_to_child2 = -1 * child1.wind_mass_loss_rate * bs.accretion_efficiency_wind_child1_to_child2 * dt -# child2_in_stellar_code.change_mass(dm_child1_to_child2, -1*dt) -# dm_child12to_child1 = -1 * child2.wind_mass_loss_rate * bs.accretion_efficiency_wind_child2_to_child1 * dt -# child1_in_stellar_code.change_mass(dm_child2_to_child1, -1*dt) -# check if this indeed is accreted conservatively - - - elif bs.child1.is_star and self.is_binary(bs.child2): - #Assumption: an inner binary is not effected by wind from an outer star - bs.accretion_efficiency_wind_child1_to_child2 = 0.0 - - bs.accretion_efficiency_wind_child2_to_child1 = 0.0 - -# child1_in_stellar_code = bs.child1.as_set().get_intersecting_subset_in(self.stellar_code.particles)[0] -# dt = self.triple.time - self.previous_time - - #effect of wind from bs.child2.child1 onto bs.child1 -# mtr_w_in1_1 = bs.child2.child1.wind_mass_loss_rate * (1-bs.child2.accretion_efficiency_wind_child1_to_child2) -# beta_w_in1_1 = 0.0 -# dm_in1_1 = -1 * mtr_w_in1_1 * beta_w_in1_1 * dt -# - #effect of wind from bs.child2.child2 onto bs.child1 -# mtr_w_in2_1 = bs.child2.child2.wind_mass_loss_rate * (1-bs.child2.accretion_efficiency_wind_child2_to_child1) -# beta_w_in2_1 = 0.0 -# dm_in2_1 = -1 * mtr_w_in2_1 * beta_w_in2_1 * dt -# -# dm = dm_in1_1 + dm_in2_1 -# mtr = mtr_w_in1_1 + mtr_w_in2_1) - - - #effect of mass transfer in the binary bs.child2 onto bs.child1 -# if bs.child2.child1.is_donor and bs.child2.child2.is_donor: -# print('contact binary in detached...') -# exit(1) -# elif bs.child2.child1.is_donor or bs.child2.child2.is_donor: -# #Assumption: -# #Stable mass transfer in the inner binary, affects the outer binary as a wind. -# mtr_rlof_in_1 = bs.child2.mass_transfer_rate * (1-bs.child2.accretion_efficiency_mass_transfer) -# beta_rlof_in_1 = 0.0 -# dm_rlof_in_1 = -1 * mtr_rlof_in_1 * beta_rlof_in_1 * dt -# dm += dm_rlof_in_1 -# mtr += mtr_rlof_in_1 - -# bs.accretion_efficiency_wind_child2_to_child1 = dm / ( mtr* -1 * dt) - -# child1_in_stellar_code.change_mass(dm, dt) -# check if this indeed is accreted conservatively - - else: - self.save_snapshot() - print('detached: type of system unknown') - print( bs.child1.is_star, bs.child2.is_star) - sys.exit('error in detached') - - #reset parameters after mass transfer -# bs.mass_transfer_rate = 0.0 | units.MSun/units.yr - -# return bs -#------------------------- - -#------------------------- -def perform_stellar_interaction(bs, self): - if REPORT_FUNCTION_NAMES: - print('Perform stellar interaction') - - stopping_condition = True - if not bs.is_star and bs.child1.is_star: - if REPORT_BINARY_EVOLUTION: - Rl1 = roche_radius(bs, bs.child1, self) - print("Check for RLOF:", bs.child1.mass, bs.child1.previous_mass) - print("Check for RLOF:", Rl1, bs.child1.radius) - - if bs.child2.is_star: - if REPORT_BINARY_EVOLUTION: - Rl2 = roche_radius(bs, bs.child2, self) - print("Check for RLOF:", bs.child2.mass, bs.child2.previous_mass) - print("Check for RLOF:", Rl2, bs.child2.radius) - -# if bs.child1.is_donor or bs.child2.is_donor: -# print("start mt") -# exit(0) - - if bs.child1.is_donor and bs.child2.is_donor: - stopping_condition = contact_system(bs, bs.child1, bs.child2, self) - elif bs.child1.is_donor and not bs.child2.is_donor: - stopping_condition = semi_detached(bs, bs.child1, bs.child2, self) - elif not bs.child1.is_donor and bs.child2.is_donor: - stopping_condition = semi_detached(bs, bs.child2, bs.child1, self) - else: - detached(bs, self) - - elif not bs.child2.is_star: - if REPORT_BINARY_EVOLUTION: - print(self.get_mass(bs), bs.child1.mass, self.get_mass(bs.child2)) - - if bs.child1.is_donor: - if bs.child2.child1.is_donor or bs.child2.child2.is_donor: - stopping_condition = outer_mass_transfer(bs, bs.child1, bs.child2, self) - else: - detached(bs, self) - - else: - print(bs.is_star, bs.child1.is_star, bs.child2.is_star) - sys.exit('error in perform stellar interaction, system type unknown') - - else: - print(bs.is_star, bs.child1.is_star, bs.child1.is_donor) - sys.exit('error in perform stellar interaction, system type unknown') - - return stopping_condition - -#------------------------- - -#------------------------- -#functions for the stability of mass transfer -def q_crit(self, donor, companion): - #following Hurley, Tout, Pols 2002 - if donor.stellar_type in [9]|units.stellar_type: -# if donor.stellar_type in [8,9]|units.stellar_type: - return 0.784 - elif donor.stellar_type in [3,4,5,6]|units.stellar_type: - x=0.3 - return (1.67-x+2*(donor.core_mass/donor.mass)**5)/2.13 - elif donor.stellar_type == 0|units.stellar_type: - return 0.695 - elif donor.stellar_type == 1|units.stellar_type: - return 1./0.625 #following claeys et al. 2014 based on de mink et al 2007 - elif donor.stellar_type in stellar_types_compact_objects:#eventhough ns & bh shouldn't be donors... - return 0.25 #0.628 - elif donor.stellar_type in [18,19]|units.stellar_type:#planet or brown dwarf. - #metzger et al 2012,425,2778, - return 1. * (donor.radius/self.get_size(companion))**3 - else: #stellar type 2, and 8 - return 3 # high for hg? - - - -def mass_transfer_stability(binary, self): - if REPORT_FUNCTION_NAMES: - print('Mass transfer stability') - - if self.is_binary(binary): - Js_1 = self.spin_angular_momentum(binary.child1) - Js_2 = self.spin_angular_momentum(binary.child2) - Jb = self.orbital_angular_momentum(binary) - if REPORT_MASS_TRANSFER_STABILITY: - print("Mass transfer stability: Binary ") - print(binary.semimajor_axis, binary.child1.mass, binary.child2.mass, binary.child1.stellar_type, binary.child2.stellar_type) - print(binary.child1.spin_angular_frequency, binary.child2.spin_angular_frequency) - print(Js_1, Js_2, Jb, Jb/3. ) - - Js = max(Js_1, Js_2) - if Js >= Jb/3. : - if REPORT_MASS_TRANSFER_STABILITY: - print("Mass transfer stability: Darwin Riemann instability", Js_1, Js_2, Jb, Jb/3.) - mt1 = -1.* binary.child1.mass / dynamic_timescale(binary.child1) - mt2 = -1.* binary.child2.mass / dynamic_timescale(binary.child2) - binary.mass_transfer_rate = min(mt1, mt2) # minimum because mt<0 - binary.is_mt_stable = False - - elif binary.child1.is_donor and binary.child2.is_donor: - if binary.child1.is_OLOF_donor and binary.child2.is_OLOF_donor: - if REPORT_MASS_TRANSFER_STABILITY: - print("Mass transfer stability: Unstable OLOF contact") - mt1 = -1.* binary.child1.mass / dynamic_timescale(binary.child1) - mt2 = -1.* binary.child2.mass / dynamic_timescale(binary.child2) - binary.mass_transfer_rate = min(mt1, mt2) # minimum because mt<0 - binary.is_mt_stable = False - #already included in next elif + mass transfer rate doesn't matter for olof - # elif binary.child1.is_OLOF_donor and binary.child1.stellar_type <= 1|units.stellar_type: - # if REPORT_MASS_TRANSFER_STABILITY: - # print("Mass transfer stability: Stable OLOF") - # binary.mass_transfer_rate = -1.* binary.child1.mass / nuclear_evolution_timescale(binary.child1) - # binary.is_mt_stable = True - # elif binary.child2.is_OLOF_donor and binary.child2.stellar_type <= 1|units.stellar_type: - # if REPORT_MASS_TRANSFER_STABILITY: - # print("Mass transfer stability: Stable OLOF") - # binary.mass_transfer_rate = -1.* binary.child2.mass / nuclear_evolution_timescale(binary.child2) - # binary.is_mt_stable = True - elif binary.child1.stellar_type <= 1|units.stellar_type and binary.child2.stellar_type <= 1|units.stellar_type: - if REPORT_MASS_TRANSFER_STABILITY: - print("Mass transfer stability: stable case A contact") - mt1 = -1.* binary.child1.mass / nuclear_evolution_timescale(binary.child1) - mt2 = -1.* binary.child2.mass / nuclear_evolution_timescale(binary.child2) - binary.mass_transfer_rate = min(mt1, mt2) # minimum because mt<0 - binary.is_mt_stable = False - else: - if REPORT_MASS_TRANSFER_STABILITY: - print("Mass transfer stability: Unstable contact") - mt1 = -1.* binary.child1.mass / dynamic_timescale(binary.child1) - mt2 = -1.* binary.child2.mass / dynamic_timescale(binary.child2) - binary.mass_transfer_rate = min(mt1, mt2) # minimum because mt<0 - binary.is_mt_stable = False - elif binary.child1.is_donor and binary.child1.mass > binary.child2.mass*q_crit(self, binary.child1, binary.child2): - if REPORT_MASS_TRANSFER_STABILITY: - print("Mass transfer stability: Mdonor1>Macc*q_crit ") - binary.mass_transfer_rate = -1.* binary.child1.mass / dynamic_timescale(binary.child1) - binary.is_mt_stable = False - elif binary.child2.is_donor and binary.child2.mass > binary.child1.mass*q_crit(self, binary.child2, binary.child1): - if REPORT_MASS_TRANSFER_STABILITY: - print("Mass transfer stability: Mdonor2>Macc*q_crit ") - binary.mass_transfer_rate= -1.* binary.child2.mass / dynamic_timescale(binary.child2) - binary.is_mt_stable = False - - elif binary.child1.is_donor: - if REPORT_MASS_TRANSFER_STABILITY: - print("Mass transfer stability: Donor1 stable ") - binary.mass_transfer_rate = -1.* binary.child1.mass / mass_transfer_timescale(binary, binary.child1) - binary.is_mt_stable = True - elif binary.child2.is_donor: - if REPORT_MASS_TRANSFER_STABILITY: - print("Mass transfer stability: Donor2 stable") - binary.mass_transfer_rate = -1.* binary.child2.mass / mass_transfer_timescale(binary, binary.child2) - binary.is_mt_stable = True - - else: - if REPORT_MASS_TRANSFER_STABILITY: - print("Mass transfer stability: Detached") - #detached system - mt1 = -1.* binary.child1.mass / mass_transfer_timescale(binary, binary.child1) - mt2 = -1.* binary.child2.mass / mass_transfer_timescale(binary, binary.child2) - binary.mass_transfer_rate = min(mt1, mt2) # minimum because mt<0 - binary.is_mt_stable = True - - else: - if binary.child1.is_star and not binary.child2.is_star: - star = binary.child1 - companion = binary.child2 - elif binary.child2.is_star and not binary.child1.is_star: - star = binary.child2 - companion = binary.child1 - else: - print(binary.is_star, binary.child1.is_star, binary.child2.is_star) - sys.exit('error in Mass transfer stability: type of system unknown') - - - if REPORT_MASS_TRANSFER_STABILITY: - print("Mass transfer stability: Binary ") - print(binary.semimajor_axis, self.get_mass(companion), star.mass, star.stellar_type) - - Js = self.spin_angular_momentum(star) - Jb = self.orbital_angular_momentum(binary) - - if Js >= Jb/3. : - if REPORT_MASS_TRANSFER_STABILITY: - print("Mass transfer stability: Darwin Riemann instability: ", Js, Jb, Jb/3.) - binary.mass_transfer_rate = -1.* star.mass / dynamic_timescale(star) - binary.is_mt_stable = False - - elif star.is_donor and star.mass > self.get_mass(companion)*q_crit(self, star, companion): - if REPORT_MASS_TRANSFER_STABILITY: - print("Mass transfer stability: Mdonor1>Macc*q_crit") - binary.mass_transfer_rate = -1.* star.mass / dynamic_timescale(star) - binary.is_mt_stable = False - - - elif star.is_donor: - if REPORT_MASS_TRANSFER_STABILITY: - print("Mass transfer stability: Donor1 stable ") - binary.mass_transfer_rate = -1.* star.mass / mass_transfer_timescale(binary, star) - binary.is_mt_stable = True - - else: - if REPORT_MASS_TRANSFER_STABILITY: - print("Mass transfer stability: Detached") - #detached system - binary.mass_transfer_rate = -1.* star.mass / mass_transfer_timescale(binary, star) - binary.is_mt_stable = True - - - - -def mass_transfer_timescale(binary, star): - if REPORT_FUNCTION_NAMES: - print('Mass transfer timescale') - - if not star.is_star: - sys.exit('error in mass transfer timescale: type of system unknown, donor star is not a star') - - #For now thermal timescale donor - mtt = kelvin_helmholds_timescale(star) -# mtt = nuclear_evolution_timescale(star) - return mtt -#------------------------- - -# Mass loss recipes for the energy limited photoevaporation of planets. - -# X-ray luminosity fraction as prescripted by Wright 2011, based on the Rossby number. -def Rx_wright11(mass, p_rot): - Rx_sat = 10**(-3.13) - Ro_sat = 0.16 - tau_conv = 10**(1.16 - 1.49* np.log(mass.value_in(units.MSun)) - 0.54*(np.log(mass.value_in(units.MSun)))**2) - Ro = p_rot/tau_conv - if Ro > Ro_sat: - B = -2.70 - R_X = Rx_sat * (Ro / Ro_sat)**B - else: - R_X = Rx_sat - return R_X - -# compute the specific flux of a BB, in erg/s /m3 (/sterad) -def blackbody(wavel, T): - h = constants.h.value_in( units.erg * units.s ) - c = constants.c.value_in( units.m / units.s ) - KB = constants.kB.value_in( units.erg / units.K ) - B_l = (2* h * c**2 / wavel**5) / (np.exp( h*c/(wavel*KB*T), dtype=np.float128) - 1) - return B_l - - -# Compute the high energy luminosity from the bolometric one. -def xuv_luminosity(star): - L_bol = star.luminosity.value_in(units.erg/units.s) - - #silvia: right now WDs+NS, should it just be wds? include bhs? - if star.stellar_type.value in [10,11,12]: # we have a WD, we integrate a Black Body from 1 nm to 91.2 nm - F_xuv = integrate.quad(blackbody, 1e-09, 9.12e-08, args=(star.temperature.value_in(units.K)))[0] - L_XUV = 4*np.pi**2 * star.radius.value_in(units.m)**2 * F_xuv - # print('M WD:', star.mass, '\t T WD:', star.temperature) - return L_XUV # erg/s - elif star.stellar_type in stellar_types_planetary_objects: - return 0; - elif star.stellar_type in stellar_types_SN_remnants: #NS, BH or massless SN - return 0; - else: - if (star.mass <= 2|units.MSun): - p_rot_star = 2*np.pi / star.spin_angular_frequency.value_in(1/units.s) - L_X = L_bol * Rx_wright11(star.mass, p_rot_star) # Rossby number approach, Wright 2011 - L_EUV = 10**4.8 * L_X**0.86 # Sanz-Forcada 2011 - elif 2|units.MSun < star.mass <= 3|units.MSun: - if star.stellar_type.value in [1,2,7,8]: #ms & hg : radiative envelope - L_X = 10**(-3.5) * L_bol # Flaccomio 2003 - elif star.stellar_type.value in [3,4,5,6,9]: # during giant phases, rossby approach again, having convective envelopes - p_rot_star = 2*np.pi / star.spin_angular_frequency.value_in(1/units.s) - L_X = L_bol * Rx_wright11(star.mass, p_rot_star) - else: - sys.exit('stellar type unknown in xuv_luminosity') - L_EUV = 10**4.8 * L_X**0.86 # Sanz-Forcada 2011 - - elif 3|units.MSun < star.mass < 10|units.MSun: - L_X = 1e-06 * L_bol # 10**31 # erg/s #Flaccomio 2003 - L_EUV = L_X # actually EUV should be stronger than X emission in this mass range - else: - # Star mass out of implemented range for evaporation: default factor employed - L_X = 1e-06 * L_bol - L_EUV = 1e-06 * L_bol - - return (L_X + L_EUV ) #|units.erg/units.s # erg/s - - -# Compute instantaneous flux at time t from given star, for a planet in circular orbit. -# lum input has to be erg/s -def flux_inst(t, r_plan, a_st_i, P_plan, P_binary, lum, star_number, i_orb ): - phi = 2*np.pi * t / P_plan # planet's phase angle (inclined) - st_ang = 2*np.pi* t / P_binary + star_number * np.pi # star phase angle (on plane) - d_z2 = ( r_plan * np.sin(phi) * np.sin(i_orb) )**2 - d_p2 = ( r_plan *np.cos(phi) - a_st_i *np.cos(st_ang) )**2 + ( r_plan *np.sin(phi)*np.cos(i_orb) - a_st_i *np.sin(st_ang) )**2 - distance_sq = d_p2 + d_z2 - return lum/distance_sq - - -def mass_lost_due_to_evaporation_tertiary(stellar_system, dt, outer_planet, inner_binary, self): - if REPORT_FUNCTION_NAMES: - print("Mass lost due to evaporation tertiary") - - e_pl = stellar_system.eccentricity - a_pl = stellar_system.semimajor_axis - P_pl = self.orbital_period(stellar_system) - i_orbits = stellar_system.relative_inclination - # time-averaged circular radius of elliptical orbits - r_pl = a_pl * ( 1 + 0.5* e_pl**2 ) - - a_bin = inner_binary.semimajor_axis - P_bin = self.orbital_period(inner_binary) - M_bin = self.get_mass(inner_binary) - xi = roche_radius_dimensionless(outer_planet.mass, M_bin) * a_pl / outer_planet.radius - #Erkaev (2007) escape factor - K_Erk = 1 - 1.5/xi + 0.5* xi**(-3) - - # compute the high-energy flux average from the two stars - t_start = 0. - #average on one orbital period of the outer planet (~ 5 P_binary) - t_end = P_pl.value_in(units.Myr) - - L_xuv1_erg_s = xuv_luminosity(inner_binary.child1) - a_st_1 = a_bin/(1+inner_binary.child1.mass/inner_binary.child2.mass) - F1 = integrate.quad(flux_inst, t_start, t_end, args=(r_pl.value_in(units.RSun), a_st_1.value_in(units.RSun), P_pl.value_in(units.Myr), P_bin.value_in(units.Myr), L_xuv1_erg_s, 0, i_orbits), limit=100, full_output=1)[0] - - L_xuv2_erg_s = xuv_luminosity(inner_binary.child2) - a_st_2 = a_bin/(1+inner_binary.child2.mass/inner_binary.child1.mass) - F2 = integrate.quad(flux_inst, t_start, t_end, args=(r_pl.value_in(units.RSun), a_st_2.value_in(units.RSun), P_pl.value_in(units.Myr), P_bin.value_in(units.Myr), L_xuv2_erg_s, 1, i_orbits), limit=100, full_output=1)[0] - - Flux_XUV = (F1+F2)/(4*np.pi* (t_end-t_start) ) | (units.erg/units.s / units.RSun**2) - eta = 0.2 # evaporation efficiency parameter - M_dot = eta * np.pi * (outer_planet.radius)**3 * Flux_XUV / ( constants.G * outer_planet.mass * K_Erk ) - mass_lost = M_dot * dt - return mass_lost - - -def mass_lost_due_to_evaporation_in_binary(stellar_system, dt, planet, star, self): - if REPORT_FUNCTION_NAMES: - print("Mass lost due to evaporation binary") - - e_pl = stellar_system.eccentricity - a_pl = stellar_system.semimajor_axis - P_pl = self.orbital_period(stellar_system) - i_orbits = stellar_system.relative_inclination - # time-averaged circular radius of elliptical orbits - r_pl = a_pl * ( 1 + 0.5* e_pl**2 ) - - xi = roche_radius_dimensionless(planet.mass, star.mass) * a_pl / planet.radius - #Erkaev (2007) escape factor - K_Erk = 1 - 1.5/xi + 0.5* xi**(-3) - Flux_XUV = star.luminosity / r_pl**2 - - eta = 0.2 # evaporation efficiency parameter - M_dot = eta * np.pi * (planet.radius)**3 * Flux_XUV / ( constants.G * planet.mass * K_Erk ) - mass_lost = M_dot * dt - return mass_lost - + +#------------------------- + +#------------------------- +#Functions for detached evolution +## Calculates stellar wind velocoty. +## Steller wind velocity is 2.5 times stellar escape velocity +#def wind_velocity(star): +# v_esc2 = constants.G * star.mass / star.radius +# return 2.5*np.sqrt(v_esc2) +#} +# +# +## Bondi, H., and Hoyle, F., 1944, MNRAS 104, 273 (wind accretion. +## Livio, M., Warner, B., 1984, The Observatory 104, 152. +#def accretion_efficiency_from_stellar_wind(accretor, donor): +#velocity needs to be determined -> velocity average? +# why is BH dependent on ecc as 1/np.sqrt(1-e**2) + +# alpha_wind = 0.5 +# v_wind = wind_velocity(donor) +# acc_radius = (constants.G*accretor.mass)**2/v_wind**4 +# +# wind_acc = alpha_wind/np.sqrt(1-bs.eccentricity**2) / bs.semimajor_axis**2 +# v_factor = 1/((1+(velocity/v_wind)**2)**3./2.) +# mass_fraction = acc_radius*wind_acc*v_factor +# +# print('mass_fraction:', mass_fraction) +## mass_fraction = min(0.9, mass_fraction) +# + + + +def detached(bs, self): + # orbital evolution is being taken into account in secular_code + if REPORT_FUNCTION_NAMES: + print('Detached') + + if bs.bin_type == bin_type['detached'] or bs.bin_type == bin_type['unknown']: + bs.bin_type = bin_type['detached'] + else: + bs.bin_type = bin_type['detached'] + self.save_snapshot() + + # wind mass loss is done by stellar_code + # wind accretion here: + # update accretion efficiency of wind mass loss + if self.is_binary(bs): + + bs.accretion_efficiency_wind_child1_to_child2 = 0.0 + bs.accretion_efficiency_wind_child2_to_child1 = 0.0 + +# child1_in_stellar_code = bs.child1.as_set().get_intersecting_subset_in(self.stellar_code.particles)[0] +# child2_in_stellar_code = bs.child2.as_set().get_intersecting_subset_in(self.stellar_code.particles)[0] +# +# dt = self.triple.time - self.previous_time +# dm_child1_to_child2 = -1 * child1.wind_mass_loss_rate * bs.accretion_efficiency_wind_child1_to_child2 * dt +# child2_in_stellar_code.change_mass(dm_child1_to_child2, -1*dt) +# dm_child12to_child1 = -1 * child2.wind_mass_loss_rate * bs.accretion_efficiency_wind_child2_to_child1 * dt +# child1_in_stellar_code.change_mass(dm_child2_to_child1, -1*dt) +# check if this indeed is accreted conservatively + + + elif bs.child1.is_star and self.is_binary(bs.child2): + #Assumption: an inner binary is not effected by wind from an outer star + bs.accretion_efficiency_wind_child1_to_child2 = 0.0 + + bs.accretion_efficiency_wind_child2_to_child1 = 0.0 + +# child1_in_stellar_code = bs.child1.as_set().get_intersecting_subset_in(self.stellar_code.particles)[0] +# dt = self.triple.time - self.previous_time + + #effect of wind from bs.child2.child1 onto bs.child1 +# mtr_w_in1_1 = bs.child2.child1.wind_mass_loss_rate * (1-bs.child2.accretion_efficiency_wind_child1_to_child2) +# beta_w_in1_1 = 0.0 +# dm_in1_1 = -1 * mtr_w_in1_1 * beta_w_in1_1 * dt +# + #effect of wind from bs.child2.child2 onto bs.child1 +# mtr_w_in2_1 = bs.child2.child2.wind_mass_loss_rate * (1-bs.child2.accretion_efficiency_wind_child2_to_child1) +# beta_w_in2_1 = 0.0 +# dm_in2_1 = -1 * mtr_w_in2_1 * beta_w_in2_1 * dt +# +# dm = dm_in1_1 + dm_in2_1 +# mtr = mtr_w_in1_1 + mtr_w_in2_1) + + + #effect of mass transfer in the binary bs.child2 onto bs.child1 +# if bs.child2.child1.is_donor and bs.child2.child2.is_donor: +# print('contact binary in detached...') +# exit(1) +# elif bs.child2.child1.is_donor or bs.child2.child2.is_donor: +# #Assumption: +# #Stable mass transfer in the inner binary, affects the outer binary as a wind. +# mtr_rlof_in_1 = bs.child2.mass_transfer_rate * (1-bs.child2.accretion_efficiency_mass_transfer) +# beta_rlof_in_1 = 0.0 +# dm_rlof_in_1 = -1 * mtr_rlof_in_1 * beta_rlof_in_1 * dt +# dm += dm_rlof_in_1 +# mtr += mtr_rlof_in_1 + +# bs.accretion_efficiency_wind_child2_to_child1 = dm / ( mtr* -1 * dt) + +# child1_in_stellar_code.change_mass(dm, dt) +# check if this indeed is accreted conservatively + + else: + self.save_snapshot() + print('detached: type of system unknown') + print( bs.child1.is_star, bs.child2.is_star) + sys.exit('error in detached') + + #reset parameters after mass transfer +# bs.mass_transfer_rate = 0.0 | units.MSun/units.yr + +# return bs +#------------------------- + +#------------------------- +def perform_stellar_interaction(bs, self): + if REPORT_FUNCTION_NAMES: + print('Perform stellar interaction') + + stopping_condition = True + if not bs.is_star and bs.child1.is_star: + if REPORT_BINARY_EVOLUTION: + Rl1 = roche_radius(bs, bs.child1, self) + print("Check for RLOF:", bs.child1.mass, bs.child1.previous_mass) + print("Check for RLOF:", Rl1, bs.child1.radius) + + if bs.child2.is_star: + if REPORT_BINARY_EVOLUTION: + Rl2 = roche_radius(bs, bs.child2, self) + print("Check for RLOF:", bs.child2.mass, bs.child2.previous_mass) + print("Check for RLOF:", Rl2, bs.child2.radius) + +# if bs.child1.is_donor or bs.child2.is_donor: +# print("start mt") +# exit(0) + + if bs.child1.is_donor and bs.child2.is_donor: + stopping_condition = contact_system(bs, bs.child1, bs.child2, self) + elif bs.child1.is_donor and not bs.child2.is_donor: + stopping_condition = semi_detached(bs, bs.child1, bs.child2, self) + elif not bs.child1.is_donor and bs.child2.is_donor: + stopping_condition = semi_detached(bs, bs.child2, bs.child1, self) + else: + detached(bs, self) + + elif not bs.child2.is_star: + if REPORT_BINARY_EVOLUTION: + print(self.get_mass(bs), bs.child1.mass, self.get_mass(bs.child2)) + + if bs.child1.is_donor: + if bs.child2.child1.is_donor or bs.child2.child2.is_donor: + stopping_condition = outer_mass_transfer(bs, bs.child1, bs.child2, self) + else: + detached(bs, self) + + else: + print(bs.is_star, bs.child1.is_star, bs.child2.is_star) + sys.exit('error in perform stellar interaction, system type unknown') + + else: + print(bs.is_star, bs.child1.is_star, bs.child1.is_donor) + sys.exit('error in perform stellar interaction, system type unknown') + + return stopping_condition + +#------------------------- + +#------------------------- +#functions for the stability of mass transfer +def q_crit(self, donor, companion): + #following Hurley, Tout, Pols 2002 + if donor.stellar_type in [9]|units.stellar_type: +# if donor.stellar_type in [8,9]|units.stellar_type: + return 0.784 + elif donor.stellar_type in [3,4,5,6]|units.stellar_type: + x=0.3 + return (1.67-x+2*(donor.core_mass/donor.mass)**5)/2.13 + elif donor.stellar_type == 0|units.stellar_type: + return 0.695 + elif donor.stellar_type == 1|units.stellar_type: + return 1./0.625 #following claeys et al. 2014 based on de mink et al 2007 + elif donor.stellar_type in stellar_types_compact_objects:#eventhough ns & bh shouldn't be donors... + return 0.25 #0.628 + elif donor.stellar_type in [18,19]|units.stellar_type:#planet or brown dwarf. + #metzger et al 2012,425,2778, + return 1. * (donor.radius/self.get_size(companion))**3 + else: #stellar type 2, and 8 + return 3 # high for hg? + + + +def mass_transfer_stability(binary, self): + if REPORT_FUNCTION_NAMES: + print('Mass transfer stability') + + if self.is_binary(binary): + Js_1 = self.spin_angular_momentum(binary.child1) + Js_2 = self.spin_angular_momentum(binary.child2) + Jb = self.orbital_angular_momentum(binary) + if REPORT_MASS_TRANSFER_STABILITY: + print("Mass transfer stability: Binary ") + print(binary.semimajor_axis, binary.child1.mass, binary.child2.mass, binary.child1.stellar_type, binary.child2.stellar_type) + print(binary.child1.spin_angular_frequency, binary.child2.spin_angular_frequency) + print(Js_1, Js_2, Jb, Jb/3. ) + + Js = max(Js_1, Js_2) + if Js >= Jb/3. : + if REPORT_MASS_TRANSFER_STABILITY: + print("Mass transfer stability: Darwin Riemann instability", Js_1, Js_2, Jb, Jb/3.) + mt1 = -1.* binary.child1.mass / dynamic_timescale(binary.child1) + mt2 = -1.* binary.child2.mass / dynamic_timescale(binary.child2) + binary.mass_transfer_rate = min(mt1, mt2) # minimum because mt<0 + binary.is_mt_stable = False + + elif binary.child1.is_donor and binary.child2.is_donor: + if binary.child1.is_OLOF_donor and binary.child2.is_OLOF_donor: + if REPORT_MASS_TRANSFER_STABILITY: + print("Mass transfer stability: Unstable OLOF contact") + mt1 = -1.* binary.child1.mass / dynamic_timescale(binary.child1) + mt2 = -1.* binary.child2.mass / dynamic_timescale(binary.child2) + binary.mass_transfer_rate = min(mt1, mt2) # minimum because mt<0 + binary.is_mt_stable = False + #already included in next elif + mass transfer rate doesn't matter for olof + # elif binary.child1.is_OLOF_donor and binary.child1.stellar_type <= 1|units.stellar_type: + # if REPORT_MASS_TRANSFER_STABILITY: + # print("Mass transfer stability: Stable OLOF") + # binary.mass_transfer_rate = -1.* binary.child1.mass / nuclear_evolution_timescale(binary.child1) + # binary.is_mt_stable = True + # elif binary.child2.is_OLOF_donor and binary.child2.stellar_type <= 1|units.stellar_type: + # if REPORT_MASS_TRANSFER_STABILITY: + # print("Mass transfer stability: Stable OLOF") + # binary.mass_transfer_rate = -1.* binary.child2.mass / nuclear_evolution_timescale(binary.child2) + # binary.is_mt_stable = True + elif binary.child1.stellar_type <= 1|units.stellar_type and binary.child2.stellar_type <= 1|units.stellar_type: + if REPORT_MASS_TRANSFER_STABILITY: + print("Mass transfer stability: stable case A contact") + mt1 = -1.* binary.child1.mass / nuclear_evolution_timescale(binary.child1) + mt2 = -1.* binary.child2.mass / nuclear_evolution_timescale(binary.child2) + binary.mass_transfer_rate = min(mt1, mt2) # minimum because mt<0 + binary.is_mt_stable = False + else: + if REPORT_MASS_TRANSFER_STABILITY: + print("Mass transfer stability: Unstable contact") + mt1 = -1.* binary.child1.mass / dynamic_timescale(binary.child1) + mt2 = -1.* binary.child2.mass / dynamic_timescale(binary.child2) + binary.mass_transfer_rate = min(mt1, mt2) # minimum because mt<0 + binary.is_mt_stable = False + elif binary.child1.is_donor and binary.child1.mass > binary.child2.mass*q_crit(self, binary.child1, binary.child2): + if REPORT_MASS_TRANSFER_STABILITY: + print("Mass transfer stability: Mdonor1>Macc*q_crit ") + binary.mass_transfer_rate = -1.* binary.child1.mass / dynamic_timescale(binary.child1) + binary.is_mt_stable = False + elif binary.child2.is_donor and binary.child2.mass > binary.child1.mass*q_crit(self, binary.child2, binary.child1): + if REPORT_MASS_TRANSFER_STABILITY: + print("Mass transfer stability: Mdonor2>Macc*q_crit ") + binary.mass_transfer_rate= -1.* binary.child2.mass / dynamic_timescale(binary.child2) + binary.is_mt_stable = False + + elif binary.child1.is_donor: + if REPORT_MASS_TRANSFER_STABILITY: + print("Mass transfer stability: Donor1 stable ") + binary.mass_transfer_rate = -1.* binary.child1.mass / mass_transfer_timescale(binary, binary.child1) + binary.is_mt_stable = True + elif binary.child2.is_donor: + if REPORT_MASS_TRANSFER_STABILITY: + print("Mass transfer stability: Donor2 stable") + binary.mass_transfer_rate = -1.* binary.child2.mass / mass_transfer_timescale(binary, binary.child2) + binary.is_mt_stable = True + + else: + if REPORT_MASS_TRANSFER_STABILITY: + print("Mass transfer stability: Detached") + #detached system + mt1 = -1.* binary.child1.mass / mass_transfer_timescale(binary, binary.child1) + mt2 = -1.* binary.child2.mass / mass_transfer_timescale(binary, binary.child2) + binary.mass_transfer_rate = min(mt1, mt2) # minimum because mt<0 + binary.is_mt_stable = True + + else: + if binary.child1.is_star and not binary.child2.is_star: + star = binary.child1 + companion = binary.child2 + elif binary.child2.is_star and not binary.child1.is_star: + star = binary.child2 + companion = binary.child1 + else: + print(binary.is_star, binary.child1.is_star, binary.child2.is_star) + sys.exit('error in Mass transfer stability: type of system unknown') + + + if REPORT_MASS_TRANSFER_STABILITY: + print("Mass transfer stability: Binary ") + print(binary.semimajor_axis, self.get_mass(companion), star.mass, star.stellar_type) + + Js = self.spin_angular_momentum(star) + Jb = self.orbital_angular_momentum(binary) + + if Js >= Jb/3. : + if REPORT_MASS_TRANSFER_STABILITY: + print("Mass transfer stability: Darwin Riemann instability: ", Js, Jb, Jb/3.) + binary.mass_transfer_rate = -1.* star.mass / dynamic_timescale(star) + binary.is_mt_stable = False + + elif star.is_donor and star.mass > self.get_mass(companion)*q_crit(self, star, companion): + if REPORT_MASS_TRANSFER_STABILITY: + print("Mass transfer stability: Mdonor1>Macc*q_crit") + binary.mass_transfer_rate = -1.* star.mass / dynamic_timescale(star) + binary.is_mt_stable = False + + + elif star.is_donor: + if REPORT_MASS_TRANSFER_STABILITY: + print("Mass transfer stability: Donor1 stable ") + binary.mass_transfer_rate = -1.* star.mass / mass_transfer_timescale(binary, star) + binary.is_mt_stable = True + + else: + if REPORT_MASS_TRANSFER_STABILITY: + print("Mass transfer stability: Detached") + #detached system + binary.mass_transfer_rate = -1.* star.mass / mass_transfer_timescale(binary, star) + binary.is_mt_stable = True + + + + +def mass_transfer_timescale(binary, star): + if REPORT_FUNCTION_NAMES: + print('Mass transfer timescale') + + if not star.is_star: + sys.exit('error in mass transfer timescale: type of system unknown, donor star is not a star') + + #For now thermal timescale donor + mtt = kelvin_helmholds_timescale(star) +# mtt = nuclear_evolution_timescale(star) + return mtt +#------------------------- + +# Mass loss recipes for the energy limited photoevaporation of planets. + +# X-ray luminosity fraction as prescripted by Wright 2011, based on the Rossby number. +def Rx_wright11(mass, p_rot): + Rx_sat = 10**(-3.13) + Ro_sat = 0.16 + tau_conv = 10**(1.16 - 1.49* np.log(mass.value_in(units.MSun)) - 0.54*(np.log(mass.value_in(units.MSun)))**2) + Ro = p_rot/tau_conv + if Ro > Ro_sat: + B = -2.70 + R_X = Rx_sat * (Ro / Ro_sat)**B + else: + R_X = Rx_sat + return R_X + +# compute the specific flux of a BB, in erg/s /m3 (/sterad) +def blackbody(wavel, T): + h = constants.h.value_in( units.erg * units.s ) + c = constants.c.value_in( units.m / units.s ) + KB = constants.kB.value_in( units.erg / units.K ) + B_l = (2* h * c**2 / wavel**5) / (np.exp( h*c/(wavel*KB*T), dtype=np.float128) - 1) + return B_l + + +# Compute the high energy luminosity from the bolometric one. +def xuv_luminosity(star): + L_bol = star.luminosity.value_in(units.erg/units.s) + + #silvia: right now WDs+NS, should it just be wds? include bhs? + if star.stellar_type.value in [10,11,12]: # we have a WD, we integrate a Black Body from 1 nm to 91.2 nm + F_xuv = integrate.quad(blackbody, 1e-09, 9.12e-08, args=(star.temperature.value_in(units.K)))[0] + L_XUV = 4*np.pi**2 * star.radius.value_in(units.m)**2 * F_xuv + # print('M WD:', star.mass, '\t T WD:', star.temperature) + return L_XUV # erg/s + elif star.stellar_type in stellar_types_planetary_objects: + return 0; + elif star.stellar_type in stellar_types_SN_remnants: #NS, BH or massless SN + return 0; + else: + if (star.mass <= 2|units.MSun): + p_rot_star = 2*np.pi / star.spin_angular_frequency.value_in(1/units.s) + L_X = L_bol * Rx_wright11(star.mass, p_rot_star) # Rossby number approach, Wright 2011 + L_EUV = 10**4.8 * L_X**0.86 # Sanz-Forcada 2011 + elif 2|units.MSun < star.mass <= 3|units.MSun: + if star.stellar_type.value in [1,2,7,8]: #ms & hg : radiative envelope + L_X = 10**(-3.5) * L_bol # Flaccomio 2003 + elif star.stellar_type.value in [3,4,5,6,9]: # during giant phases, rossby approach again, having convective envelopes + p_rot_star = 2*np.pi / star.spin_angular_frequency.value_in(1/units.s) + L_X = L_bol * Rx_wright11(star.mass, p_rot_star) + else: + sys.exit('stellar type unknown in xuv_luminosity') + L_EUV = 10**4.8 * L_X**0.86 # Sanz-Forcada 2011 + + elif 3|units.MSun < star.mass < 10|units.MSun: + L_X = 1e-06 * L_bol # 10**31 # erg/s #Flaccomio 2003 + L_EUV = L_X # actually EUV should be stronger than X emission in this mass range + else: + # Star mass out of implemented range for evaporation: default factor employed + L_X = 1e-06 * L_bol + L_EUV = 1e-06 * L_bol + + return (L_X + L_EUV ) #|units.erg/units.s # erg/s + + +# Compute instantaneous flux at time t from given star, for a planet in circular orbit. +# lum input has to be erg/s +def flux_inst(t, r_plan, a_st_i, P_plan, P_binary, lum, star_number, i_orb ): + phi = 2*np.pi * t / P_plan # planet's phase angle (inclined) + st_ang = 2*np.pi* t / P_binary + star_number * np.pi # star phase angle (on plane) + d_z2 = ( r_plan * np.sin(phi) * np.sin(i_orb) )**2 + d_p2 = ( r_plan *np.cos(phi) - a_st_i *np.cos(st_ang) )**2 + ( r_plan *np.sin(phi)*np.cos(i_orb) - a_st_i *np.sin(st_ang) )**2 + distance_sq = d_p2 + d_z2 + return lum/distance_sq + + +def mass_lost_due_to_evaporation_tertiary(stellar_system, dt, outer_planet, inner_binary, self): + if REPORT_FUNCTION_NAMES: + print("Mass lost due to evaporation tertiary") + + e_pl = stellar_system.eccentricity + a_pl = stellar_system.semimajor_axis + P_pl = self.orbital_period(stellar_system) + i_orbits = stellar_system.relative_inclination + # time-averaged circular radius of elliptical orbits + r_pl = a_pl * ( 1 + 0.5* e_pl**2 ) + + a_bin = inner_binary.semimajor_axis + P_bin = self.orbital_period(inner_binary) + M_bin = self.get_mass(inner_binary) + xi = roche_radius_dimensionless(outer_planet.mass, M_bin) * a_pl / outer_planet.radius + #Erkaev (2007) escape factor + K_Erk = 1 - 1.5/xi + 0.5* xi**(-3) + + # compute the high-energy flux average from the two stars + t_start = 0. + #average on one orbital period of the outer planet (~ 5 P_binary) + t_end = P_pl.value_in(units.Myr) + + L_xuv1_erg_s = xuv_luminosity(inner_binary.child1) + a_st_1 = a_bin/(1+inner_binary.child1.mass/inner_binary.child2.mass) + F1 = integrate.quad(flux_inst, t_start, t_end, args=(r_pl.value_in(units.RSun), a_st_1.value_in(units.RSun), P_pl.value_in(units.Myr), P_bin.value_in(units.Myr), L_xuv1_erg_s, 0, i_orbits), limit=100, full_output=1)[0] + + L_xuv2_erg_s = xuv_luminosity(inner_binary.child2) + a_st_2 = a_bin/(1+inner_binary.child2.mass/inner_binary.child1.mass) + F2 = integrate.quad(flux_inst, t_start, t_end, args=(r_pl.value_in(units.RSun), a_st_2.value_in(units.RSun), P_pl.value_in(units.Myr), P_bin.value_in(units.Myr), L_xuv2_erg_s, 1, i_orbits), limit=100, full_output=1)[0] + + Flux_XUV = (F1+F2)/(4*np.pi* (t_end-t_start) ) | (units.erg/units.s / units.RSun**2) + eta = 0.2 # evaporation efficiency parameter + M_dot = eta * np.pi * (outer_planet.radius)**3 * Flux_XUV / ( constants.G * outer_planet.mass * K_Erk ) + mass_lost = M_dot * dt + return mass_lost + + +def mass_lost_due_to_evaporation_in_binary(stellar_system, dt, planet, star, self): + if REPORT_FUNCTION_NAMES: + print("Mass lost due to evaporation binary") + + e_pl = stellar_system.eccentricity + a_pl = stellar_system.semimajor_axis + P_pl = self.orbital_period(stellar_system) + i_orbits = stellar_system.relative_inclination + # time-averaged circular radius of elliptical orbits + r_pl = a_pl * ( 1 + 0.5* e_pl**2 ) + + xi = roche_radius_dimensionless(planet.mass, star.mass) * a_pl / planet.radius + #Erkaev (2007) escape factor + K_Erk = 1 - 1.5/xi + 0.5* xi**(-3) + Flux_XUV = star.luminosity / r_pl**2 + + eta = 0.2 # evaporation efficiency parameter + M_dot = eta * np.pi * (planet.radius)**3 * Flux_XUV / ( constants.G * planet.mass * K_Erk ) + mass_lost = M_dot * dt + return mass_lost + diff --git a/src/tres/setup.py b/src/tres/setup.py index f564221..3f267cd 100644 --- a/src/tres/setup.py +++ b/src/tres/setup.py @@ -1,12 +1,12 @@ from amuse.community.seba.interface import SeBa from amuse.datamodel import Particles from amuse.units import units -from seculartriple_TPS.interface import SecularTriple +from tres.seculartriple_TPS.interface import SecularTriple -from TRES_options import max_mass, absolute_min_mass +from tres.TRES_options import max_mass, absolute_min_mass -from interactions import * -from tidal_friction_constant import * +from tres.interactions import * +from tres.tidal_friction_constant import * import numpy as np @@ -240,4 +240,4 @@ def setup_secular_code(triple, secular_code, stop_at_semisecular_regime): return secular_code -#------- \ No newline at end of file +#------- diff --git a/src/tres/tps.py b/src/tres/tps.py index b0e483a..8e3548d 100644 --- a/src/tres/tps.py +++ b/src/tres/tps.py @@ -165,10 +165,10 @@ from amuse.ic.flatimf import new_flat_mass_distribution from amuse.community.seba import Seba -import TRES -from seculartriple_TPS.interface import SecularTriple +import tres +from tres.seculartriple_TPS.interface import SecularTriple -from TRES_options import ( +from tres.options import ( REPORT_TPS, REPORT_USER_WARNINGS_TPS, EXCLUDE_SSO, @@ -1344,7 +1344,7 @@ def evolve_model( # do not use main_developer in TPS.py # memory of SeBa needs to be cleaned, in particular SeBa time # otherwise use evolve_for for particles indivicually -> many calls - tr = TRES.main( + tr = tres.main( inner_primary_mass=triple_system.inner_primary_mass, inner_secondary_mass=triple_system.inner_secondary_mass, outer_mass=triple_system.outer_mass, @@ -1423,7 +1423,7 @@ def evolve_model( i_n += 1 nr_imt -= 1 - tr = TRES.main( + tr = tres.main( inner_primary_mass=triple_system.inner_primary_mass, inner_secondary_mass=triple_system.inner_secondary_mass, outer_mass=triple_system.outer_mass, @@ -1717,26 +1717,26 @@ def test_initial_parameters( inner_primary_mass_max > absolute_max_mass ): sys.exit( - "'error: inner primary mass not in allowed range [', min_mass, ',', absolute_max_mass, ']'. min_mass and absolute_max_mass settable in TRES_options.py" + "'error: inner primary mass not in allowed range [', min_mass, ',', absolute_max_mass, ']'. min_mass and absolute_max_mass settable in tres.options" ) if inner_secondary_mass_max > absolute_max_mass: sys.exit( - "'error: inner secondary mass not in allowed range [ < ', absolute_max_mass, ']'. absolute_max_mass settable in TRES_options.py" + "'error: inner secondary mass not in allowed range [ < ', absolute_max_mass, ']'. absolute_max_mass settable in tres.options" ) if outer_mass_max > absolute_max_mass: sys.exit( - "'error: outer mass not in allowed range [ < ', absolute_max_mass, ']'. absolute_max_mass settable in TRES_options.py" + "'error: outer mass not in allowed range [ < ', absolute_max_mass, ']'. absolute_max_mass settable in tres.options" ) if inner_secondary_mass_min < absolute_min_mass: sys.exit( - "'error: inner secondary mass not in allowed range [ >', absolute_min_mass, ']'. absolute_min_mass settable in TRES_options.py" + "'error: inner secondary mass not in allowed range [ >', absolute_min_mass, ']'. absolute_min_mass settable in tres.options" ) if outer_mass_min < absolute_min_mass: sys.exit( - "'error: outer mass not in allowed range [>', absolute_min_mass, ']'. absolute_min_mass settable in TRES_options.py" + "'error: outer mass not in allowed range [>', absolute_min_mass, ']'. absolute_min_mass settable in tres.options" ) if inner_primary_mass_max < inner_primary_mass_min: diff --git a/src/tres/tres.py b/src/tres/tres.py index 9e5bcec..f17ff09 100644 --- a/src/tres/tres.py +++ b/src/tres/tres.py @@ -6,33 +6,31 @@ given any initial conditions (M, m, l, A, a, E, e, i, G, g, O, o, T, z). """ import sys - +import argparse import numpy as np -# from interactions import * -# from tidal_friction_constant import * from amuse.units import units from amuse.support.console import set_printing_strategy - from amuse.community.seba.interface import SeBa -from .seculartriple_TPS.interface import SecularTriple - -from .triple_class import Triple_Class -from .TRES_plotting import plot_data_container, plot_function -from .TRES_setup import make_particle_sets, setup_stellar_code -from .TRES_options import ( +from tres.seculartriple_TPS.interface import SecularTriple +from tres.triple_class import Triple_Class +from tres.plotting import plot_data_container, plot_function +from tres.setup import make_particle_sets, setup_stellar_code +from tres.options import ( REPORT_DEBUG, REPORT_TRIPLE_EVOLUTION, MAKE_PLOTS, REPORT_USER_WARNINGS, ) -from .interactions import ( +from tres.interactions import ( corotating_spin_angular_frequency_binary, lang_spin_angular_frequency, break_up_angular_frequency, criticial_angular_frequency_CHE, ) +# from interactions import * +# from tidal_friction_constant import * def initialize_triple_class( @@ -435,279 +433,273 @@ def main_developer( # ----- # for running triple.py from the commandline def parse_arguments(): - from amuse.units.optparse import OptionParser - parser = OptionParser() - parser.add_option( + parser = argparse.ArgumentParser( + formatter_class=argparse.ArgumentDefaultsHelpFormatter, + ) + parser.add_argument( "-M", "--M1", - unit=units.MSun, + type=units.MSun, dest="inner_primary_mass", - type="float", default=1.3 | units.MSun, - help="inner primary mass [%default]", + help="inner primary mass", ) - parser.add_option( + parser.add_argument( "-m", "--M2", - unit=units.MSun, + type=units.MSun, dest="inner_secondary_mass", - type="float", default=0.5 | units.MSun, - help="inner secondary mass [%default]", + help="inner secondary mass", ) - parser.add_option( + parser.add_argument( "-l", "--M3", - unit=units.MSun, + type=units.MSun, dest="outer_mass", - type="float", default=0.5 | units.MSun, - help="outer mass [%default]", + help="outer mass", ) - parser.add_option( + parser.add_argument( "-A", "--Ain", - unit=units.RSun, + type=units.RSun, dest="inner_semimajor_axis", - type="float", default=200.0 | units.RSun, - help="inner semi major axis [%default]", + help="inner semi major axis", ) - parser.add_option( + parser.add_argument( "-a", "--Aout", - unit=units.RSun, + type=units.RSun, dest="outer_semimajor_axis", - type="float", default=20000.0 | units.RSun, - help="outer semi major axis [%default]", + help="outer semi major axis", ) - parser.add_option( + parser.add_argument( "-E", "--Ein", dest="inner_eccentricity", - type="float", + type=float, default=0.1, - help="inner eccentricity [%default]", + help="inner eccentricity", ) - parser.add_option( + parser.add_argument( "-e", "--Eout", dest="outer_eccentricity", - type="float", + type=float, default=0.5, - help="outer eccentricity [%default]", + help="outer eccentricity", ) - parser.add_option( + parser.add_argument( "-i", "-I", dest="relative_inclination", - type="float", - default=80.0 * np.pi / 180.0, - help="relative inclination [rad] [%default]", + type=units.rad, + default=(80.0 * np.pi / 180.0) | units.rad, + help="relative inclination", ) - parser.add_option( + parser.add_argument( "-G", "--Gin", dest="inner_argument_of_pericenter", - type="float", - default=0.1, - help="inner argument of pericenter [rad] [%default]", + type=units.rad, + default=0.1 | units.rad, + help="inner argument of pericenter", ) - parser.add_option( + parser.add_argument( "-g", "--Gout", dest="outer_argument_of_pericenter", - type="float", - default=0.5, - help="outer argument of pericenter [rad] [%default]", + type=units.rad, + default=0.5 | units.rad, + help="outer argument of pericenter", ) - parser.add_option( + parser.add_argument( "-O", "--Oin", dest="inner_longitude_of_ascending_node", - type="float", - default=0.0, - help="inner longitude of ascending node [rad] [%default]", + type=units.rad, + default=0.0 | units.rad, + help="inner longitude of ascending node [rad]", ) ## outer longitude of ascending nodes = inner - pi - # parser.add_option("-o", - # dest="outer_longitude_of_ascending_node", type="float", default = 0.0, - # help="outer longitude of ascending node [rad] [%default]") + # parser.add_argument("-o", + # dest="outer_longitude_of_ascending_node", type=float, default = 0.0, + # help="outer longitude of ascending node [rad]") - parser.add_option( + parser.add_argument( "-z", "-Z", dest="metallicity", - type="float", + type=float, default=0.02, - help="metallicity [%default] %unit", + help="metallicity", ) - parser.add_option( + parser.add_argument( "-t", "-T", - unit=units.Myr, + type=units.Myr, dest="tend", - type="float", default=5.0 | units.Myr, - help="end time [%default] %unit", + help="end time", ) - parser.add_option( + parser.add_argument( "--initial_time", - unit=units.Myr, + type=units.Myr, dest="tinit", - type="float", default=0.0 | units.Myr, - help="initial time [%default] %unit", + help="initial time", ) - parser.add_option( + parser.add_argument( "-N", dest="number", - type="int", + type=int, default=0, - help="number ID of system [%default]", + help="number ID of system", ) - parser.add_option( + parser.add_argument( "-r", dest="maximum_radius_change_factor", - type="float", + type=float, default=0.01, - help="maximum_radius_change_factor [%default] %unit", + help="maximum_radius_change_factor", ) - # parser.add_option("--tidal", dest="tidal_terms", action="store_false", default = True, - # help="tidal terms included [%default] %unit") + # parser.add_argument("--tidal", dest="tidal_terms", action="store_false", default = True, + # help="tidal terms included %unit") - parser.add_option( + parser.add_argument( "--no_stop_at_mass_transfer", dest="stop_at_mass_transfer", action="store_false", default=True, - help="stop at mass transfer [%default] %unit", + help="stop at mass transfer", ) - parser.add_option( + parser.add_argument( "--no_stop_at_init_mass_transfer", dest="stop_at_init_mass_transfer", action="store_false", default=True, - help="stop if initially mass transfer[%default] %unit", + help="stop if initially mass transfer", ) - parser.add_option( + parser.add_argument( "--no_stop_at_outer_mass_transfer", dest="stop_at_outer_mass_transfer", action="store_false", default=True, - help="stop at triple mass transfer [%default] %unit", + help="stop at triple mass transfer", ) # if stop_at_mass_transfer is False, the following 4 stopping conditions can be used to further specify. # if stop_at_mass_transfer is True, the following 4 are ignored. - parser.add_option( + parser.add_argument( "--stop_at_stable_mass_transfer", dest="stop_at_stable_mass_transfer", action="store_true", default=False, - help="stop at stable mass transfer [%default] %unit", + help="stop at stable mass transfer", ) - parser.add_option( + parser.add_argument( "--stop_at_eccentric_stable_mass_transfer", dest="stop_at_eccentric_stable_mass_transfer", action="store_true", default=False, - help="stop at eccentric stable mass transfer [%default] %unit", + help="stop at eccentric stable mass transfer", ) # unstable mass transfer leads to common-envelope evolution - parser.add_option( + parser.add_argument( "--stop_at_unstable_mass_transfer", dest="stop_at_unstable_mass_transfer", action="store_true", default=False, - help="stop at unstable mass transfer [%default] %unit", + help="stop at unstable mass transfer", ) - parser.add_option( + parser.add_argument( "--stop_at_eccentric_unstable_mass_transfer", dest="stop_at_eccentric_unstable_mass_transfer", action="store_true", default=False, - help="stop at eccentric unstable mass transfer [%default] %unit", + help="stop at eccentric unstable mass transfer", ) # 0 alpha-ce + alpha-dce # 1 gamma-ce + alpha-dce # 2 seba style; combination of gamma-ce, alpha-ce & alpha-dce - parser.add_option( + parser.add_argument( "--CE", dest="which_common_envelope", - type="int", + type=int, default=2, - help="which common envelope modeling [%default]", + help="which common envelope modeling", ) - parser.add_option( + parser.add_argument( "--stop_at_no_CHE", dest="stop_at_no_CHE", action="store_true", default=False, - help="stop if no chemically homogeneous evolution [%default] %unit", + help="stop if no chemically homogeneous evolution", ) - parser.add_option( + parser.add_argument( "--include_CHE", dest="include_CHE", action="store_true", default=False, - help="include chemically homogeneous evolution in the stellar evolution [%default] %unit", + help="include chemically homogeneous evolution in the stellar evolution", ) - parser.add_option( + parser.add_argument( "--no_stop_at_merger", dest="stop_at_merger", action="store_false", default=True, - help="stop at merger [%default] %unit", + help="stop at merger", ) - parser.add_option( + parser.add_argument( "--no_stop_at_disintegrated", dest="stop_at_disintegrated", action="store_false", default=True, - help="stop at disintegrated [%default] %unit", + help="stop at disintegrated", ) - parser.add_option( + parser.add_argument( "--no_stop_at_inner_collision", dest="stop_at_inner_collision", action="store_false", default=True, - help="stop at collision in inner binary[%default] %unit", + help="stop at collision in inner binary", ) - parser.add_option( + parser.add_argument( "--no_stop_at_outer_collision", dest="stop_at_outer_collision", action="store_false", default=True, - help="stop at collision in outer binary[%default] %unit", + help="stop at collision in outer binary", ) - parser.add_option( + parser.add_argument( "--no_stop_at_dynamical_instability", dest="stop_at_dynamical_instability", action="store_false", default=True, - help="stop at dynamical instability [%default] %unit", + help="stop at dynamical instability", ) - parser.add_option( + parser.add_argument( "--stop_at_semisecular_regime", dest="stop_at_semisecular_regime", action="store_true", default=False, - help="stop at semisecular regime [%default] %unit", + help="stop at semisecular regime", ) - parser.add_option( + parser.add_argument( "--stop_at_SN", dest="stop_at_SN", action="store_true", default=False, - help="stop at supernova [%default] %unit", + help="stop at supernova", ) # 0 No kick # 1 Hobbs, Lorimer, Lyne & Kramer 2005, 360, 974 @@ -715,71 +707,71 @@ def parse_arguments(): # 3 Hansen & Phinney 1997, 291, 569 # 4 Paczynski 1990, 348, 485 # 5 Verbunt, Igoshev & Cator, 2017, 608, 57 - parser.add_option( + parser.add_argument( "--SN_kick_distr", dest="SN_kick_distr", - type="int", + type=int, default=5, - help="which supernova kick distribution [%default]", + help="which supernova kick distribution", ) - parser.add_option( + parser.add_argument( "--no_impulse_kick_for_black_holes", dest="impulse_kick_for_black_holes", action="store_false", default=True, - help="do not rescale the BH SN kick by mass -> impulse kick [%default]", + help="do not rescale the BH SN kick by mass -> impulse kick", ) - parser.add_option( + parser.add_argument( "--no_fallback_kick_for_black_holes", dest="fallback_kick_for_black_holes", action="store_false", default=True, - help="do not rescale the BH SN kick with fallback [%default]", + help="do not rescale the BH SN kick with fallback ", ) - parser.add_option( + parser.add_argument( "--stop_at_CPU_time", dest="stop_at_CPU_time", action="store_true", default=False, - help="stop at CPU time [%default] %unit", + help="stop at CPU time", ) - parser.add_option( + parser.add_argument( "--max_CPU_time", dest="max_CPU_time", - type="float", + type=float, default=3600.0, - help="max CPU time [%default] %unit", + help="max CPU time", ) - parser.add_option( + parser.add_argument( "-f", dest="file_name", - type="string", + type=str, default="TRES.hdf", # "TRES.txt" - help="file name[%default]", + help="file name", ) - parser.add_option( + parser.add_argument( "-F", dest="file_type", - type="string", + type=str, default="hdf5", # "txt" - help="file type[%default]", + help="file type", ) - parser.add_option( + parser.add_argument( "--dir_plots", dest="dir_plots", - type="string", + type=str, default="", # "txt" - help="directory for plots for debugging mode [%default]", + help="directory for plots for debugging mode", ) - options, args = parser.parse_args() - return options.__dict__ + args = parser.parse_args() + return args.__dict__ if __name__ == "__main__": - opt = parse_arguments() + arg = parse_arguments() set_printing_strategy( "custom", @@ -791,17 +783,17 @@ def parse_arguments(): ) stars, bins, correct_params = make_particle_sets( - opt["inner_primary_mass"], - opt["inner_secondary_mass"], - opt["outer_mass"], - opt["inner_semimajor_axis"], - opt["outer_semimajor_axis"], - opt["inner_eccentricity"], - opt["outer_eccentricity"], - opt["relative_inclination"], - opt["inner_argument_of_pericenter"], - opt["outer_argument_of_pericenter"], - opt["inner_longitude_of_ascending_node"], + arg["inner_primary_mass"], + arg["inner_secondary_mass"], + arg["outer_mass"], + arg["inner_semimajor_axis"], + arg["outer_semimajor_axis"], + arg["inner_eccentricity"], + arg["outer_eccentricity"], + arg["relative_inclination"], + arg["inner_argument_of_pericenter"], + arg["outer_argument_of_pericenter"], + arg["inner_longitude_of_ascending_node"], ) stellar_code = SeBa() @@ -818,36 +810,36 @@ def parse_arguments(): correct_params, stellar_code, secular_code, - opt["relative_inclination"], - opt["tend"], - opt["tinit"], - opt["number"], - opt["maximum_radius_change_factor"], - opt["stop_at_mass_transfer"], - opt["stop_at_init_mass_transfer"], - opt["stop_at_outer_mass_transfer"], - opt["stop_at_stable_mass_transfer"], - opt["stop_at_eccentric_stable_mass_transfer"], - opt["stop_at_unstable_mass_transfer"], - opt["stop_at_eccentric_unstable_mass_transfer"], - opt["which_common_envelope"], - opt["stop_at_no_CHE"], - opt["include_CHE"], - opt["stop_at_merger"], - opt["stop_at_disintegrated"], - opt["stop_at_inner_collision"], - opt["stop_at_outer_collision"], - opt["stop_at_dynamical_instability"], - opt["stop_at_semisecular_regime"], - opt["stop_at_SN"], - opt["SN_kick_distr"], - opt["impulse_kick_for_black_holes"], - opt["fallback_kick_for_black_holes"], - opt["stop_at_CPU_time"], - opt["max_CPU_time"], - opt["file_name"], - opt["file_type"], - opt["dir_plots"], + arg["relative_inclination"], + arg["tend"], + arg["tinit"], + arg["number"], + arg["maximum_radius_change_factor"], + arg["stop_at_mass_transfer"], + arg["stop_at_init_mass_transfer"], + arg["stop_at_outer_mass_transfer"], + arg["stop_at_stable_mass_transfer"], + arg["stop_at_eccentric_stable_mass_transfer"], + arg["stop_at_unstable_mass_transfer"], + arg["stop_at_eccentric_unstable_mass_transfer"], + arg["which_common_envelope"], + arg["stop_at_no_CHE"], + arg["include_CHE"], + arg["stop_at_merger"], + arg["stop_at_disintegrated"], + arg["stop_at_inner_collision"], + arg["stop_at_outer_collision"], + arg["stop_at_dynamical_instability"], + arg["stop_at_semisecular_regime"], + arg["stop_at_SN"], + arg["SN_kick_distr"], + arg["impulse_kick_for_black_holes"], + arg["fallback_kick_for_black_holes"], + arg["stop_at_CPU_time"], + arg["max_CPU_time"], + arg["file_name"], + arg["file_type"], + arg["dir_plots"], ) if triple_class_object.correct_params is False: @@ -860,7 +852,7 @@ def parse_arguments(): "Choose a different system. The parameters of the given triple are incorrect." ) elif ( - opt["stop_at_semisecular_regime"] is True + arg["stop_at_semisecular_regime"] is True and triple_class_object.semisecular_regime_at_initialisation is True ): if REPORT_USER_WARNINGS: @@ -878,7 +870,7 @@ def parse_arguments(): "Choose a different system. There is mass transfer in the given triple at initialization." ) elif ( - opt["stop_at_no_CHE"] is True + arg["stop_at_no_CHE"] is True and triple_class_object.CHE_at_initialisation is False ): if REPORT_USER_WARNINGS: @@ -886,9 +878,9 @@ def parse_arguments(): "Choose a different system. No chemically homogeneous evolution at initialization" ) else: - triple_class_object.evolve_model(opt["tend"]) + triple_class_object.evolve_model(arg["tend"]) if REPORT_DEBUG or MAKE_PLOTS: - plot_function(triple_class_object, opt["dir_plots"]) + plot_function(triple_class_object, arg["dir_plots"]) triple_class_object.print_stellar_system() if REPORT_TRIPLE_EVOLUTION: diff --git a/src/tres/triple_class.py b/src/tres/triple_class.py index 6bec791..7a96cc7 100644 --- a/src/tres/triple_class.py +++ b/src/tres/triple_class.py @@ -1,7 +1,3 @@ - -from interactions import * -from tidal_friction_constant import * - import sys import time from amuse.units import units, constants @@ -10,9 +6,13 @@ from amuse.units import quantities from scipy.stats import maxwell from scipy import optimize + # from math import isnan import numpy as np +from tres.interactions import * +from tres.tidal_friction_constant import * + # from tres_options import REPORT_USER_WARNINGS, \ # GET_GYRATION_RADIUS_FROM_STELLAR_CODE, \ # GET_AMC_FROM_STELLAR_CODE, \ @@ -24,115 +24,165 @@ # maximum_time_step_factor, \ # minimum_time_step -from TRES_options import * -from TRES_setup import setup_secular_code, setup_stellar_code -from TRES_plotting import plot_data_container +from tres.TRES_options import * +from tres.TRES_setup import setup_secular_code, setup_stellar_code +from tres.TRES_plotting import plot_data_container class Triple_Class: - #------- - #setup stellar system - def __init__(self, stars, bins, correct_params, - stellar_code, secular_code, relative_inclination, - tend, tinit, number, maximum_radius_change_factor, - stop_at_mass_transfer, stop_at_init_mass_transfer, stop_at_outer_mass_transfer, - stop_at_stable_mass_transfer, stop_at_eccentric_stable_mass_transfer, - stop_at_unstable_mass_transfer, stop_at_eccentric_unstable_mass_transfer, which_common_envelope, - stop_at_no_CHE, include_CHE, - stop_at_merger, stop_at_disintegrated, stop_at_inner_collision, stop_at_outer_collision, - stop_at_dynamical_instability, stop_at_semisecular_regime, - stop_at_SN, SN_kick_distr, impulse_kick_for_black_holes,fallback_kick_for_black_holes, - stop_at_CPU_time, max_CPU_time, - file_name, file_type, dir_plots): - + # ------- + # setup stellar system + def __init__( + self, + stars, + bins, + correct_params, + stellar_code, + secular_code, + relative_inclination, + tend, + tinit, + number, + maximum_radius_change_factor, + stop_at_mass_transfer, + stop_at_init_mass_transfer, + stop_at_outer_mass_transfer, + stop_at_stable_mass_transfer, + stop_at_eccentric_stable_mass_transfer, + stop_at_unstable_mass_transfer, + stop_at_eccentric_unstable_mass_transfer, + which_common_envelope, + stop_at_no_CHE, + include_CHE, + stop_at_merger, + stop_at_disintegrated, + stop_at_inner_collision, + stop_at_outer_collision, + stop_at_dynamical_instability, + stop_at_semisecular_regime, + stop_at_SN, + SN_kick_distr, + impulse_kick_for_black_holes, + fallback_kick_for_black_holes, + stop_at_CPU_time, + max_CPU_time, + file_name, + file_type, + dir_plots, + ): + self.correct_params = correct_params if correct_params == False: - self.triple = Particles(1) + self.triple = Particles(1) return - - self.tend = tend + + self.tend = tend self.tinit = tinit - self.previous_time = 0.0|units.yr - self.previous_dt = 0.0|units.yr - self.instantaneous_evolution = False - if tinit > 0|units.Myr: - self.instantaneous_evolution = True # no secular - + self.previous_time = 0.0 | units.yr + self.previous_dt = 0.0 | units.yr + self.instantaneous_evolution = False + if tinit > 0 | units.Myr: + self.instantaneous_evolution = True # no secular + self.maximum_radius_change_factor = maximum_radius_change_factor - self.fixed_timestep = -1|units.Myr + self.fixed_timestep = -1 | units.Myr self.file_name = file_name self.file_type = file_type self.which_common_envelope = which_common_envelope - self.include_CHE = include_CHE - if REPORT_USER_WARNINGS and self.include_CHE: - print("Note: For CHE evolution to be included, it also needs to be switched on manually in SeBa.") - print("\t This can be done by setting include_CHE=True in SeBa's sstar/starclass/constants.C.") + self.include_CHE = include_CHE + if REPORT_USER_WARNINGS and self.include_CHE: + print( + "Note: For CHE evolution to be included, it also needs to be switched on manually in SeBa." + ) + print( + "\t This can be done by setting include_CHE=True in SeBa's sstar/starclass/constants.C." + ) print("\t AMUSE developer mode is required to access SeBa files.") self.SN_kick_distr = SN_kick_distr self.impulse_kick_for_black_holes = impulse_kick_for_black_holes self.fallback_kick_for_black_holes = fallback_kick_for_black_holes self.max_CPU_time = max_CPU_time - self.triple = bins[1] - self.triple.time = 0.0|units.yr - self.triple.relative_inclination = relative_inclination - self.triple.is_star = False #maybe not necessary? - self.triple.dynamical_instability = False - self.triple.number = number + self.triple = bins[1] + self.triple.time = 0.0 | units.yr + self.triple.relative_inclination = relative_inclination + self.triple.is_star = False # maybe not necessary? + self.triple.dynamical_instability = False + self.triple.number = number self.triple.error_flag_secular = 0 self.triple.CPU_time = 0.0 self.triple.child2.delta_e_in = 0.0 self.triple.child2.max_delta_e_in = 0.0 - + self.dynamical_instability_at_initialisation = False self.semisecular_regime_at_initialisation = False self.mass_transfer_at_initialisation = False self.CHE_at_initialisation = False - self.set_stopping_conditions(stop_at_mass_transfer, stop_at_init_mass_transfer,stop_at_outer_mass_transfer, - stop_at_stable_mass_transfer, stop_at_eccentric_stable_mass_transfer, - stop_at_unstable_mass_transfer, stop_at_eccentric_unstable_mass_transfer, stop_at_no_CHE, - stop_at_merger, stop_at_disintegrated, stop_at_inner_collision, stop_at_outer_collision, - stop_at_dynamical_instability, stop_at_semisecular_regime, stop_at_SN, stop_at_CPU_time) + self.set_stopping_conditions( + stop_at_mass_transfer, + stop_at_init_mass_transfer, + stop_at_outer_mass_transfer, + stop_at_stable_mass_transfer, + stop_at_eccentric_stable_mass_transfer, + stop_at_unstable_mass_transfer, + stop_at_eccentric_unstable_mass_transfer, + stop_at_no_CHE, + stop_at_merger, + stop_at_disintegrated, + stop_at_inner_collision, + stop_at_outer_collision, + stop_at_dynamical_instability, + stop_at_semisecular_regime, + stop_at_SN, + stop_at_CPU_time, + ) self.initialize_stellar(stellar_code, stars) - self.initialize_secular(secular_code, stop_at_semisecular_regime, - stop_at_dynamical_instability) - - self.check_RLOF() - if self.has_tertiary_donor() and (self.stop_at_outer_mass_transfer or self.stop_at_mass_transfer or self.stop_at_init_mass_transfer): + self.initialize_secular( + secular_code, stop_at_semisecular_regime, stop_at_dynamical_instability + ) + + self.check_RLOF() + if self.has_tertiary_donor() and ( + self.stop_at_outer_mass_transfer + or self.stop_at_mass_transfer + or self.stop_at_init_mass_transfer + ): self.mass_transfer_at_initialisation = True - self.triple.bin_type = bin_type['rlof'] + self.triple.bin_type = bin_type["rlof"] return - + self.check_OLOF() if self.stop_at_no_CHE and (not self.check_CHE()): self.CHE_at_initialization = False return - - if (self.has_donor() or self.has_OLOF_donor()) and (self.stop_at_mass_transfer or self.stop_at_init_mass_transfer): + + if (self.has_donor() or self.has_OLOF_donor()) and ( + self.stop_at_mass_transfer or self.stop_at_init_mass_transfer + ): self.mass_transfer_at_initialisation = True - #assuming object is triple as is triple constructor + # assuming object is triple as is triple constructor if self.is_binary(self.triple.child1): bin = self.triple.child1 else: bin = self.triple.child2 - if bin.child1.is_OLOF_donor or bin.child2.is_OLOF_donor: - bin.bin_type = bin_type['olof'] - return + if bin.child1.is_OLOF_donor or bin.child2.is_OLOF_donor: + bin.bin_type = bin_type["olof"] + return elif bin.child1.is_donor and bin.child2.is_donor: - bin.bin_type = bin_type['contact'] + bin.bin_type = bin_type["contact"] return else: - bin.bin_type = bin_type['rlof'] + bin.bin_type = bin_type["rlof"] return return self.triple.kozai_type = self.get_kozai_type() - self.update_stellar_parameters() + self.update_stellar_parameters() self.update_time_derivative_of_radius() self.update_previous_stellar_parameters() @@ -140,200 +190,287 @@ def initialize_stellar(self, stellar_code, stars): self.stellar_code = setup_stellar_code(stellar_code, stars) self.channel_from_stellar = stellar_code.particles.new_channel_to(stars) self.channel_to_stellar = stars.new_channel_to(stellar_code.particles) - self.copy_from_stellar() - self.initial_angular_frequency() + self.copy_from_stellar() + self.initial_angular_frequency() - def initialize_secular(self, secular_code, - stop_at_semisecular_regime, - stop_at_dynamical_instability): + def initialize_secular( + self, secular_code, stop_at_semisecular_regime, stop_at_dynamical_instability + ): triple_set = self.triple.as_set() - self.secular_code = setup_secular_code(self.triple, secular_code, stop_at_semisecular_regime) + self.secular_code = setup_secular_code( + self.triple, secular_code, stop_at_semisecular_regime + ) self.channel_from_secular = self.secular_code.triples.new_channel_to(triple_set) self.channel_to_secular = triple_set.new_channel_to(self.secular_code.triples) self.channel_to_secular.copy() self.secular_code.check_for_dynamical_stability() - if stop_at_dynamical_instability == True and self.secular_code.triples[0].dynamical_instability == True: + if ( + stop_at_dynamical_instability == True + and self.secular_code.triples[0].dynamical_instability == True + ): self.dynamical_instability_at_initialisation = True self.triple.dynamical_instability = True self.set_bintype_to_dynamical_instability() - return + return self.secular_code.check_for_semisecular_regime() - if stop_at_semisecular_regime == True and self.secular_code.triples[0].semisecular_regime == True: + if ( + stop_at_semisecular_regime == True + and self.secular_code.triples[0].semisecular_regime == True + ): self.semisecular_regime_at_initialisation = True - self.triple.semisecular_regime = True + self.triple.semisecular_regime = True return - - - def set_stopping_conditions(self, stop_at_mass_transfer,stop_at_init_mass_transfer,stop_at_outer_mass_transfer, - stop_at_stable_mass_transfer, stop_at_eccentric_stable_mass_transfer, - stop_at_unstable_mass_transfer, stop_at_eccentric_unstable_mass_transfer, stop_at_no_CHE, - stop_at_merger, stop_at_disintegrated, stop_at_inner_collision, stop_at_outer_collision, - stop_at_dynamical_instability, stop_at_semisecular_regime, stop_at_SN, stop_at_CPU_time): + + def set_stopping_conditions( + self, + stop_at_mass_transfer, + stop_at_init_mass_transfer, + stop_at_outer_mass_transfer, + stop_at_stable_mass_transfer, + stop_at_eccentric_stable_mass_transfer, + stop_at_unstable_mass_transfer, + stop_at_eccentric_unstable_mass_transfer, + stop_at_no_CHE, + stop_at_merger, + stop_at_disintegrated, + stop_at_inner_collision, + stop_at_outer_collision, + stop_at_dynamical_instability, + stop_at_semisecular_regime, + stop_at_SN, + stop_at_CPU_time, + ): if stop_at_disintegrated == False: - sys.exit('stop_at_disintegrated = False not possible yet. After the disintegration of the triple, further evolution can be done with stellar code directly. ') + sys.exit( + "stop_at_disintegrated = False not possible yet. After the disintegration of the triple, further evolution can be done with stellar code directly. " + ) if stop_at_outer_mass_transfer == False: - sys.exit('stop_at_outer_mass_transfer = False not possible yet. Methodology is as of yet non-existent.' ) + sys.exit( + "stop_at_outer_mass_transfer = False not possible yet. Methodology is as of yet non-existent." + ) if stop_at_outer_collision == False: - sys.exit('stop_at_outer_collision = False not possible. Non-hierarchical triples can not be simulated using the secular equations as used in TRES. Further evolution should be done by other means, e.g. one of the N-body codes implemented in AMUSE.' ) + sys.exit( + "stop_at_outer_collision = False not possible. Non-hierarchical triples can not be simulated using the secular equations as used in TRES. Further evolution should be done by other means, e.g. one of the N-body codes implemented in AMUSE." + ) if stop_at_dynamical_instability == False: - sys.exit('stop_at_dynamical_instability = False not possible. Unstable triples can not be simulated using the secular equations as used in TRES. Further evolution should be done by other means, e.g. one of the N-body codes implemented in AMUSE.') + sys.exit( + "stop_at_dynamical_instability = False not possible. Unstable triples can not be simulated using the secular equations as used in TRES. Further evolution should be done by other means, e.g. one of the N-body codes implemented in AMUSE." + ) - - self.stop_at_mass_transfer = stop_at_mass_transfer + self.stop_at_mass_transfer = stop_at_mass_transfer self.stop_at_init_mass_transfer = stop_at_init_mass_transfer - self.stop_at_outer_mass_transfer = stop_at_outer_mass_transfer + self.stop_at_outer_mass_transfer = stop_at_outer_mass_transfer - self.stop_at_stable_mass_transfer = stop_at_stable_mass_transfer - self.stop_at_eccentric_stable_mass_transfer = stop_at_eccentric_stable_mass_transfer + self.stop_at_stable_mass_transfer = stop_at_stable_mass_transfer + self.stop_at_eccentric_stable_mass_transfer = ( + stop_at_eccentric_stable_mass_transfer + ) self.stop_at_unstable_mass_transfer = stop_at_unstable_mass_transfer - self.stop_at_eccentric_unstable_mass_transfer = stop_at_eccentric_unstable_mass_transfer + self.stop_at_eccentric_unstable_mass_transfer = ( + stop_at_eccentric_unstable_mass_transfer + ) self.stop_at_no_CHE = stop_at_no_CHE - - self.stop_at_merger = stop_at_merger - self.stop_at_disintegrated = stop_at_disintegrated - self.stop_at_inner_collision = stop_at_inner_collision - self.stop_at_outer_collision = stop_at_outer_collision - self.stop_at_dynamical_instability = stop_at_dynamical_instability + self.stop_at_merger = stop_at_merger + self.stop_at_disintegrated = stop_at_disintegrated + self.stop_at_inner_collision = stop_at_inner_collision + self.stop_at_outer_collision = stop_at_outer_collision + + self.stop_at_dynamical_instability = stop_at_dynamical_instability self.stop_at_semisecular_regime = stop_at_semisecular_regime self.stop_at_SN = stop_at_SN self.stop_at_CPU_time = stop_at_CPU_time - - - #------- + + # ------- def copy_from_stellar(self): -# self.channel_from_stellar.copy() - self.channel_from_stellar.copy_attributes(["age", "mass", "core_mass", "radius", "core_radius", "convective_envelope_radius", "convective_envelope_mass", "stellar_type", "luminosity", "wind_mass_loss_rate", "temperature"]) + # self.channel_from_stellar.copy() + self.channel_from_stellar.copy_attributes( + [ + "age", + "mass", + "core_mass", + "radius", + "core_radius", + "convective_envelope_radius", + "convective_envelope_mass", + "stellar_type", + "luminosity", + "wind_mass_loss_rate", + "temperature", + ] + ) if GET_GYRATION_RADIUS_FROM_STELLAR_CODE: - self.channel_from_stellar.copy_attributes(["gyration_radius"]) + self.channel_from_stellar.copy_attributes(["gyration_radius"]) if GET_AMC_FROM_STELLAR_CODE: - self.channel_from_stellar.copy_attributes(["apsidal_motion_constant"]) - + self.channel_from_stellar.copy_attributes(["apsidal_motion_constant"]) - #------- - - def initial_angular_frequency(self, stellar_system = None): + # ------- + + def initial_angular_frequency(self, stellar_system=None): if stellar_system == None: stellar_system = self.triple self.previous_time = self.triple.time if stellar_system.is_star: - if stellar_system.stellar_type in stellar_types_planetary_objects: - stellar_system.spin_angular_frequency = 0.125 * break_up_angular_frequency(stellar_system) + if stellar_system.stellar_type in stellar_types_planetary_objects: + stellar_system.spin_angular_frequency = ( + 0.125 * break_up_angular_frequency(stellar_system) + ) else: - stellar_system.spin_angular_frequency = lang_spin_angular_frequency(stellar_system) - if self.include_CHE: #sets initial spin to corotation - stellar_system.spin_angular_frequency = corotating_spin_angular_frequency_binary(stellar_system.parent.semimajor_axis, self.get_mass(stellar_system.parent.child1), self.get_mass(stellar_system.parent.child2)) - stellar_system.rotation_period = (2*np.pi/stellar_system.spin_angular_frequency) + stellar_system.spin_angular_frequency = lang_spin_angular_frequency( + stellar_system + ) + if self.include_CHE: # sets initial spin to corotation + stellar_system.spin_angular_frequency = ( + corotating_spin_angular_frequency_binary( + stellar_system.parent.semimajor_axis, + self.get_mass(stellar_system.parent.child1), + self.get_mass(stellar_system.parent.child2), + ) + ) + stellar_system.rotation_period = ( + 2 * np.pi / stellar_system.spin_angular_frequency + ) else: - self.initial_angular_frequency(stellar_system.child1) + self.initial_angular_frequency(stellar_system.child1) self.initial_angular_frequency(stellar_system.child2) - if self.include_CHE: #only needed when including CHE - self.channel_to_stellar.copy_attributes(['rotation_period']) - - #------- + if self.include_CHE: # only needed when including CHE + self.channel_to_stellar.copy_attributes(["rotation_period"]) + + # ------- - #------- - def refresh_memory(self, stellar_system = None): + # ------- + def refresh_memory(self, stellar_system=None): if stellar_system == None: stellar_system = self.triple self.triple.time = self.previous_time if stellar_system.is_star: - stellar_system.mass = stellar_system.previous_mass - stellar_system.radius = stellar_system.previous_radius + stellar_system.mass = stellar_system.previous_mass + stellar_system.radius = stellar_system.previous_radius stellar_system.stellar_type = stellar_system.previous_stellar_type - stellar_system.moment_of_inertia_of_star = stellar_system.previous_moment_of_inertia_of_star - stellar_system.time_derivative_of_radius = stellar_system.previous_time_derivative_of_radius - stellar_system.spin_angular_frequency = stellar_system.previous_spin_angular_frequency - + stellar_system.moment_of_inertia_of_star = ( + stellar_system.previous_moment_of_inertia_of_star + ) + stellar_system.time_derivative_of_radius = ( + stellar_system.previous_time_derivative_of_radius + ) + stellar_system.spin_angular_frequency = ( + stellar_system.previous_spin_angular_frequency + ) + else: - self.refresh_memory(stellar_system.child1) + self.refresh_memory(stellar_system.child1) self.refresh_memory(stellar_system.child2) stellar_system.mass = stellar_system.previous_mass stellar_system.bin_type = stellar_system.previous_bin_type - + if self.is_triple(stellar_system): stellar_system.kozai_type = stellar_system.previous_kozai_type - def update_previous_stellar_parameters(self, stellar_system = None): + def update_previous_stellar_parameters(self, stellar_system=None): if stellar_system == None: stellar_system = self.triple self.previous_time = self.triple.time if stellar_system.is_star: - stellar_system.previous_mass = self.get_mass(stellar_system) + stellar_system.previous_mass = self.get_mass(stellar_system) stellar_system.previous_radius = stellar_system.radius stellar_system.previous_stellar_type = stellar_system.stellar_type - stellar_system.previous_moment_of_inertia_of_star = stellar_system.moment_of_inertia_of_star - stellar_system.previous_spin_angular_frequency = stellar_system.spin_angular_frequency - if self.triple.time == quantities.zero: #initialization - stellar_system.previous_time_derivative_of_radius = 0.0 | units.RSun/units.yr + stellar_system.previous_moment_of_inertia_of_star = ( + stellar_system.moment_of_inertia_of_star + ) + stellar_system.previous_spin_angular_frequency = ( + stellar_system.spin_angular_frequency + ) + if self.triple.time == quantities.zero: # initialization + stellar_system.previous_time_derivative_of_radius = ( + 0.0 | units.RSun / units.yr + ) else: - stellar_system.previous_time_derivative_of_radius = stellar_system.time_derivative_of_radius + stellar_system.previous_time_derivative_of_radius = ( + stellar_system.time_derivative_of_radius + ) else: - self.update_previous_stellar_parameters(stellar_system.child1) + self.update_previous_stellar_parameters(stellar_system.child1) self.update_previous_stellar_parameters(stellar_system.child2) - stellar_system.previous_mass = self.get_mass(stellar_system) + stellar_system.previous_mass = self.get_mass(stellar_system) stellar_system.previous_bin_type = stellar_system.bin_type - + if self.is_triple(stellar_system): stellar_system.previous_kozai_type = stellar_system.kozai_type - - #------- - #------- - def update_time_derivative_of_radius(self, stellar_system = None): - #update time_derivative_of_radius for effect of wind on spin - #radius change due to stellar evolution, not mass transfer + # ------- + + # ------- + def update_time_derivative_of_radius(self, stellar_system=None): + # update time_derivative_of_radius for effect of wind on spin + # radius change due to stellar evolution, not mass transfer if stellar_system == None: stellar_system = self.triple - + time_step = self.triple.time - self.previous_time if self.triple.time == quantities.zero: - #initialization - self.triple.child2.child1.time_derivative_of_radius = 0.0 | units.RSun/units.yr - self.triple.child2.child2.time_derivative_of_radius = 0.0 | units.RSun/units.yr - self.triple.child1.time_derivative_of_radius = 0.0 | units.RSun/units.yr - else: + # initialization + self.triple.child2.child1.time_derivative_of_radius = ( + 0.0 | units.RSun / units.yr + ) + self.triple.child2.child2.time_derivative_of_radius = ( + 0.0 | units.RSun / units.yr + ) + self.triple.child1.time_derivative_of_radius = 0.0 | units.RSun / units.yr + else: if stellar_system.is_star: - stellar_system.time_derivative_of_radius = (stellar_system.radius - stellar_system.previous_radius)/time_step + stellar_system.time_derivative_of_radius = ( + stellar_system.radius - stellar_system.previous_radius + ) / time_step else: - self.update_time_derivative_of_radius(stellar_system.child1) + self.update_time_derivative_of_radius(stellar_system.child1) self.update_time_derivative_of_radius(stellar_system.child2) - #------- - - #------- - def update_time_derivative_of_moment_of_inertia(self, stellar_system = None): - #update time_derivative_of_radius for effect of changing Jspin + + # ------- + + # ------- + def update_time_derivative_of_moment_of_inertia(self, stellar_system=None): + # update time_derivative_of_radius for effect of changing Jspin if stellar_system == None: stellar_system = self.triple - + time_step = self.triple.time - self.previous_time if self.triple.time == quantities.zero: - #initialization - self.triple.child2.child1.time_derivative_of_moment_of_inertia = 0.0 | units.MSun*units.RSun**2/units.yr - self.triple.child2.child2.time_derivative_of_moment_of_inertia = 0.0 | units.MSun*units.RSun**2/units.yr - self.triple.child1.time_derivative_of_moment_of_inertia = 0.0 | units.RSun/units.yr - else: + # initialization + self.triple.child2.child1.time_derivative_of_moment_of_inertia = ( + 0.0 | units.MSun * units.RSun**2 / units.yr + ) + self.triple.child2.child2.time_derivative_of_moment_of_inertia = ( + 0.0 | units.MSun * units.RSun**2 / units.yr + ) + self.triple.child1.time_derivative_of_moment_of_inertia = ( + 0.0 | units.RSun / units.yr + ) + else: if stellar_system.is_star: - stellar_system.time_derivative_of_moment_of_inertia = (stellar_system.moment_of_inertia_of_star - stellar_system.previous_moment_of_inertia_of_star)/time_step + stellar_system.time_derivative_of_moment_of_inertia = ( + stellar_system.moment_of_inertia_of_star + - stellar_system.previous_moment_of_inertia_of_star + ) / time_step else: - self.update_time_derivative_of_moment_of_inertia(stellar_system.child1) + self.update_time_derivative_of_moment_of_inertia(stellar_system.child1) self.update_time_derivative_of_moment_of_inertia(stellar_system.child2) - #------- - #------- - def update_stellar_parameters(self, stellar_system = None): + # ------- + + # ------- + def update_stellar_parameters(self, stellar_system=None): # for the convective envelope mass: # the prescription of Hurley, Pols & Tout 2000 is implemented in SeBa, however note that the prescription in BSE is different # for the convective envelope radius: @@ -342,110 +479,126 @@ def update_stellar_parameters(self, stellar_system = None): stellar_system = self.triple if stellar_system.is_star: - + if not GET_GYRATION_RADIUS_FROM_STELLAR_CODE: - stellar_system.gyration_radius = set_gyration_radius(stellar_system.stellar_type, stellar_system.mass) + stellar_system.gyration_radius = set_gyration_radius( + stellar_system.stellar_type, stellar_system.mass + ) if not GET_AMC_FROM_STELLAR_CODE: - stellar_system.apsidal_motion_constant = self.apsidal_motion_constant(stellar_system) + stellar_system.apsidal_motion_constant = self.apsidal_motion_constant( + stellar_system + ) if stellar_system.core_radius > stellar_system.radius: - #can happen very late on the agb before WD formation - stellar_system.core_radius = stellar_system.radius - stellar_system.moment_of_inertia_of_star = self.moment_of_inertia(stellar_system) - - if stellar_system.convective_envelope_radius < 0|units.RSun: - sys.exit('convective_envelope_radius < 0') - if stellar_system.convective_envelope_radius == 0|units.RSun: - stellar_system.convective_envelope_mass = 1.e-10 |units.MSun - stellar_system.convective_envelope_radius = 1.e-10 |units.RSun - - #When the GW inspiral time is shorter than the inner orbit, the numerical solver crashes - #This is only possible for BH & NS as other stars would fill their RL earlier - #To avoid this articially increase stellar radii of BH/NS in secular code - #Does not affect any other processes + # can happen very late on the agb before WD formation + stellar_system.core_radius = stellar_system.radius + stellar_system.moment_of_inertia_of_star = self.moment_of_inertia( + stellar_system + ) + + if stellar_system.convective_envelope_radius < 0 | units.RSun: + sys.exit("convective_envelope_radius < 0") + if stellar_system.convective_envelope_radius == 0 | units.RSun: + stellar_system.convective_envelope_mass = 1.0e-10 | units.MSun + stellar_system.convective_envelope_radius = 1.0e-10 | units.RSun + + # When the GW inspiral time is shorter than the inner orbit, the numerical solver crashes + # This is only possible for BH & NS as other stars would fill their RL earlier + # To avoid this articially increase stellar radii of BH/NS in secular code + # Does not affect any other processes if stellar_system.stellar_type in stellar_types_SN_remnants: - stellar_system.radius = stellar_system.radius*10 - + stellar_system.radius = stellar_system.radius * 10 + else: - self.update_stellar_parameters(stellar_system.child1) + self.update_stellar_parameters(stellar_system.child1) self.update_stellar_parameters(stellar_system.child2) if self.is_triple(stellar_system): - stellar_system.kozai_type = self.get_kozai_type() - #------- + stellar_system.kozai_type = self.get_kozai_type() - #------- + # ------- + + # ------- # useful functions general - - #whether or not a stellar system consists of just two stars + + # whether or not a stellar system consists of just two stars def is_binary(self, stellar_system=None): if stellar_system == None: - stellar_system = self.triple - - if not stellar_system.is_star and stellar_system.child1.is_star and stellar_system.child2.is_star: + stellar_system = self.triple + + if ( + not stellar_system.is_star + and stellar_system.child1.is_star + and stellar_system.child2.is_star + ): return True else: return False - def is_triple(self, stellar_system = None): + def is_triple(self, stellar_system=None): if stellar_system == None: stellar_system = self.triple if not stellar_system.is_star: if stellar_system.child1.is_star and self.is_binary(stellar_system.child2): return True - elif stellar_system.child2.is_star and self.is_binary(stellar_system.child1): + elif stellar_system.child2.is_star and self.is_binary( + stellar_system.child1 + ): return True return False - def has_donor(self, stellar_system = None): + def has_donor(self, stellar_system=None): if stellar_system == None: stellar_system = self.triple - + if stellar_system.is_star: if stellar_system.is_donor: return True else: - if self.has_donor(stellar_system.child1) or self.has_donor(stellar_system.child2): - return True - - return False + if self.has_donor(stellar_system.child1) or self.has_donor( + stellar_system.child2 + ): + return True + return False - def has_OLOF_donor(self, stellar_system = None): + def has_OLOF_donor(self, stellar_system=None): if stellar_system == None: stellar_system = self.triple - + if stellar_system.is_star: if stellar_system.is_OLOF_donor: return True else: - if self.has_OLOF_donor(stellar_system.child1) or self.has_OLOF_donor(stellar_system.child2): - return True - - return False - - def has_contact_system(self, stellar_system = None): - if stellar_system == None: - stellar_system = self.triple - - if stellar_system.is_star: - return False - elif self.is_binary(stellar_system): - if stellar_system.child1.is_donor and stellar_system.child2.is_donor: - return True - else: - if self.has_contact_system(stellar_system.child1): - return True - if self.has_contact_system(stellar_system.child2): - return True - - return False - -# if a merger is currently taking place, not if a merger has happened in the past - def has_merger(self, stellar_system = None): + if self.has_OLOF_donor(stellar_system.child1) or self.has_OLOF_donor( + stellar_system.child2 + ): + return True + + return False + + def has_contact_system(self, stellar_system=None): if stellar_system == None: stellar_system = self.triple - + + if stellar_system.is_star: + return False + elif self.is_binary(stellar_system): + if stellar_system.child1.is_donor and stellar_system.child2.is_donor: + return True + else: + if self.has_contact_system(stellar_system.child1): + return True + if self.has_contact_system(stellar_system.child2): + return True + + return False + + # if a merger is currently taking place, not if a merger has happened in the past + def has_merger(self, stellar_system=None): + if stellar_system == None: + stellar_system = self.triple + if stellar_system.is_star: return False else: @@ -453,16 +606,16 @@ def has_merger(self, stellar_system = None): return True if self.has_merger(stellar_system.child2): return True - if stellar_system.bin_type == bin_type['merger']: - return True + if stellar_system.bin_type == bin_type["merger"]: + return True - return False + return False -# if a disruption is currently taking place, not if a disruption has happened in the past - def has_disintegrated(self, stellar_system = None): + # if a disruption is currently taking place, not if a disruption has happened in the past + def has_disintegrated(self, stellar_system=None): if stellar_system == None: stellar_system = self.triple - + if stellar_system.is_star: return False else: @@ -470,18 +623,16 @@ def has_disintegrated(self, stellar_system = None): return True if self.has_disintegrated(stellar_system.child2): return True - if stellar_system.bin_type == bin_type['disintegrated']: - return True - - return False - + if stellar_system.bin_type == bin_type["disintegrated"]: + return True + return False -# if a dynamical instability is currently taking place, not if an instability has happened in the past - def has_dynamical_instability(self, stellar_system = None): + # if a dynamical instability is currently taking place, not if an instability has happened in the past + def has_dynamical_instability(self, stellar_system=None): if stellar_system == None: stellar_system = self.triple - + if stellar_system.is_star: return False else: @@ -489,64 +640,70 @@ def has_dynamical_instability(self, stellar_system = None): return True if self.has_dynamical_instability(stellar_system.child2): return True - if stellar_system.bin_type == bin_type['dyn_inst']: - return True - - return False + if stellar_system.bin_type == bin_type["dyn_inst"]: + return True - def set_bintype_to_dynamical_instability(self, stellar_system = None): - if self.triple.dynamical_instability: + return False + + def set_bintype_to_dynamical_instability(self, stellar_system=None): + if self.triple.dynamical_instability: if stellar_system == None: stellar_system = self.triple - + if stellar_system.is_star == False: - stellar_system.bin_type = bin_type['dyn_inst'] + stellar_system.bin_type = bin_type["dyn_inst"] self.set_bintype_to_dynamical_instability(stellar_system.child1) - self.set_bintype_to_dynamical_instability(stellar_system.child2) - - -#doesn't work well, as it uses bin_types that are set later -> use has_tertiary_donor -# if a mass transfer in the outer binary of the triple is currently taking place, not if a mass transfer has happened in the past -# def has_outer_mass_transfer(self, stellar_system = None): -# if stellar_system == None: -# stellar_system = self.triple -# -# if stellar_system.is_star: -# return False -# elif self.is_binary(stellar_system): -# return False -# else: -# if self.has_outer_mass_transfer(stellar_system.child1): -# return True -# if self.has_outer_mass_transfer(stellar_system.child2): -# return True -# if stellar_system.bin_type != bin_type['unknown'] and stellar_system.bin_type != bin_type['detached']: -# return True -# -# return False - - -# if a mass transfer in the outer binary of the triple is currently taking place, not if a mass transfer has happened in the past - def has_tertiary_donor(self, stellar_system = None): + self.set_bintype_to_dynamical_instability(stellar_system.child2) + + # doesn't work well, as it uses bin_types that are set later -> use has_tertiary_donor + # if a mass transfer in the outer binary of the triple is currently taking place, not if a mass transfer has happened in the past + # def has_outer_mass_transfer(self, stellar_system = None): + # if stellar_system == None: + # stellar_system = self.triple + # + # if stellar_system.is_star: + # return False + # elif self.is_binary(stellar_system): + # return False + # else: + # if self.has_outer_mass_transfer(stellar_system.child1): + # return True + # if self.has_outer_mass_transfer(stellar_system.child2): + # return True + # if stellar_system.bin_type != bin_type['unknown'] and stellar_system.bin_type != bin_type['detached']: + # return True + # + # return False + + # if a mass transfer in the outer binary of the triple is currently taking place, not if a mass transfer has happened in the past + def has_tertiary_donor(self, stellar_system=None): if stellar_system == None: stellar_system = self.triple - + if stellar_system.is_star: return False elif self.is_binary(stellar_system): return False else: - if self.has_tertiary_donor(stellar_system.child1): + if self.has_tertiary_donor(stellar_system.child1): + return True + if self.has_tertiary_donor(stellar_system.child2): return True - if self.has_tertiary_donor(stellar_system.child2): + if ( + stellar_system.child1.is_star + and stellar_system.child1.is_donor + and not stellar_system.child2.is_star + ): return True - if stellar_system.child1.is_star and stellar_system.child1.is_donor and not stellar_system.child2.is_star: - return True - if stellar_system.child2.is_star and stellar_system.child2.is_donor and not stellar_system.child1.is_star: - return True - return False - - def contains_SN_remnant(self, stellar_system = None): + if ( + stellar_system.child2.is_star + and stellar_system.child2.is_donor + and not stellar_system.child1.is_star + ): + return True + return False + + def contains_SN_remnant(self, stellar_system=None): if stellar_system == None: stellar_system = self.triple @@ -554,27 +711,32 @@ def contains_SN_remnant(self, stellar_system = None): if stellar_system.stellar_type in stellar_types_SN_remnants: return True else: - if self.contains_SN_remnant(stellar_system.child1) or self.contains_SN_remnant(stellar_system.child2): - return True - - return False - + if self.contains_SN_remnant( + stellar_system.child1 + ) or self.contains_SN_remnant(stellar_system.child2): + return True - def has_stellar_type_changed_into_SN_remnant(self, stellar_system = None): + return False + + def has_stellar_type_changed_into_SN_remnant(self, stellar_system=None): if stellar_system == None: stellar_system = self.triple if stellar_system.is_star: - if stellar_system.stellar_type != stellar_system.previous_stellar_type and stellar_system.stellar_type in stellar_types_SN_remnants: + if ( + stellar_system.stellar_type != stellar_system.previous_stellar_type + and stellar_system.stellar_type in stellar_types_SN_remnants + ): return True else: - if self.has_stellar_type_changed_into_SN_remnant(stellar_system.child1) or self.has_stellar_type_changed_into_SN_remnant(stellar_system.child2): - return True - - return False + if self.has_stellar_type_changed_into_SN_remnant( + stellar_system.child1 + ) or self.has_stellar_type_changed_into_SN_remnant(stellar_system.child2): + return True + return False - def has_stellar_type_changed(self, stellar_system = None): + def has_stellar_type_changed(self, stellar_system=None): if stellar_system == None: stellar_system = self.triple @@ -582,50 +744,50 @@ def has_stellar_type_changed(self, stellar_system = None): if stellar_system.stellar_type != stellar_system.previous_stellar_type: return True else: - if self.has_stellar_type_changed(stellar_system.child1) or self.has_stellar_type_changed(stellar_system.child2): - return True - - return False - - - - def has_kozai_type_changed(self, stellar_system = None): + if self.has_stellar_type_changed( + stellar_system.child1 + ) or self.has_stellar_type_changed(stellar_system.child2): + return True + + return False + + def has_kozai_type_changed(self, stellar_system=None): if stellar_system == None: stellar_system = self.triple if self.is_triple(stellar_system): if stellar_system.kozai_type != stellar_system.previous_kozai_type: return True - else: #binaries and single stars do not have a kozai timescale - return False - -#obsolete? -# def is_system_stable(self, stellar_system = None): -# if stellar_system == None: -# stellar_system = self.triple -# -# if stellar_system.is_star: -# return True -# elif self.is_binary(stellar_system): -# return stellar_system.is_mt_stable -# else: -# if stellar_system.is_mt_stable and self.is_system_stable(stellar_system.child1) and self.is_system_stable(stellar_system.child2): -# return True -# -# return False - - def get_mass(self, stellar_system = None): + else: # binaries and single stars do not have a kozai timescale + return False + + # obsolete? + # def is_system_stable(self, stellar_system = None): + # if stellar_system == None: + # stellar_system = self.triple + # + # if stellar_system.is_star: + # return True + # elif self.is_binary(stellar_system): + # return stellar_system.is_mt_stable + # else: + # if stellar_system.is_mt_stable and self.is_system_stable(stellar_system.child1) and self.is_system_stable(stellar_system.child2): + # return True + # + # return False + + def get_mass(self, stellar_system=None): if stellar_system == None: stellar_system = self.triple if stellar_system.is_star: return stellar_system.mass else: - M1 = self.get_mass(stellar_system.child1) + M1 = self.get_mass(stellar_system.child1) M2 = self.get_mass(stellar_system.child2) - return M1 + M2 + return M1 + M2 - def get_size(self, stellar_system = None): + def get_size(self, stellar_system=None): if stellar_system == None: stellar_system = self.triple @@ -633,19 +795,22 @@ def get_size(self, stellar_system = None): return stellar_system.radius else: return stellar_system.semimajor_axis - - #------- + # ------- - #------- + # ------- # useful functions general - + def orbital_period(self, bs): if not bs.is_star: - Porb = 2*np.pi * np.sqrt(bs.semimajor_axis**3/constants.G / self.get_mass(bs)) + Porb = ( + 2 + * np.pi + * np.sqrt(bs.semimajor_axis**3 / constants.G / self.get_mass(bs)) + ) return Porb else: - sys.exit('orbital_period: single star does not have a period') + sys.exit("orbital_period: single star does not have a period") def orbital_angular_momentum(self, bs): if not bs.is_star: @@ -653,141 +818,152 @@ def orbital_angular_momentum(self, bs): m = self.get_mass(bs.child2) a = bs.semimajor_axis e = bs.eccentricity - J = M*m * np.sqrt(constants.G*a*(1-e**2)/(M+m)) - + J = M * m * np.sqrt(constants.G * a * (1 - e**2) / (M + m)) + if REPORT_BINARY_EVOLUTION: - print('Jorb:', M, m, a, e, J) - + print("Jorb:", M, m, a, e, J) + return J else: - sys.exit('orbital_angular_momentum: single star does not have an orbit') - + sys.exit("orbital_angular_momentum: single star does not have an orbit") + def spin_angular_momentum(self, ss): if ss.is_star: return ss.moment_of_inertia_of_star * ss.spin_angular_frequency else: - sys.exit('spin_angular_momentum: structure stellar system unknown') + sys.exit("spin_angular_momentum: structure stellar system unknown") - - def apsidal_motion_constant(self, star): - - if star.stellar_type in [13]|units.stellar_type: #ns - #based on Brooke & Olle 1955, for n=1 polytrope + + if star.stellar_type in [13] | units.stellar_type: # ns + # based on Brooke & Olle 1955, for n=1 polytrope return 0.260 - - elif star.stellar_type in [13, 14]|units.stellar_type: #bh + + elif star.stellar_type in [13, 14] | units.stellar_type: # bh # Hamers et al. 2013 - return 0. - elif star.stellar_type in [1,7,10,11,12]|units.stellar_type:#ms, he-ms, wd - #based on Brooke & Olle 1955, for n=3 polytrope - return 0.0144 - - elif star.stellar_type in [0,2,3,4,5,6,8,9,17]|units.stellar_type:#low-mass ms, hg, gb, cheb, agb, he-g, pre-ms - #based on Brooke & Olle 1955, for n=3 polytrope -# return 0.143 - #based on Claret & Gimenez 1992, 96, 225 the value should be smaller, try: + return 0.0 + elif ( + star.stellar_type in [1, 7, 10, 11, 12] | units.stellar_type + ): # ms, he-ms, wd + # based on Brooke & Olle 1955, for n=3 polytrope + return 0.0144 + + elif ( + star.stellar_type in [0, 2, 3, 4, 5, 6, 8, 9, 17] | units.stellar_type + ): # low-mass ms, hg, gb, cheb, agb, he-g, pre-ms + # based on Brooke & Olle 1955, for n=3 polytrope + # return 0.143 + # based on Claret & Gimenez 1992, 96, 225 the value should be smaller, try: return 0.05 - elif star.stellar_type in [18]|units.stellar_type:#planet - #based on Brooke & Olle 1955, for n=3 polytrope - return 0.0144 - elif star.stellar_type in [19]|units.stellar_type:#bd - #based on Brooke & Olle 1955, for n=3 polytrope + elif star.stellar_type in [18] | units.stellar_type: # planet + # based on Brooke & Olle 1955, for n=3 polytrope + return 0.0144 + elif star.stellar_type in [19] | units.stellar_type: # bd + # based on Brooke & Olle 1955, for n=3 polytrope return 0.0144 else: print(star.stellar_type) - sys.exit('apsidal motion constant: stellar_type unknown') - + sys.exit("apsidal motion constant: stellar_type unknown") def moment_of_inertia(self, star): if star.is_star: if GET_GYRATION_RADIUS_FROM_STELLAR_CODE: - I = star.gyration_radius**2 * (star.mass)*star.radius**2 - else: + I = star.gyration_radius**2 * (star.mass) * star.radius**2 + else: k2 = 0.1 k3 = 0.21 - - if star.stellar_type in stellar_types_remnants: - I = k3*(star.mass)*star.radius**2 - else: - I = k2*(star.mass - star.core_mass)*star.radius**2 + k3*star.core_mass*star.core_radius**2 - - return I - else: - sys.exit('moment_of_inertia: structure stellar system unknown') - - + if star.stellar_type in stellar_types_remnants: + I = k3 * (star.mass) * star.radius**2 + else: + I = ( + k2 * (star.mass - star.core_mass) * star.radius**2 + + k3 * star.core_mass * star.core_radius**2 + ) + return I + else: + sys.exit("moment_of_inertia: structure stellar system unknown") def octupole_parameter(self): if self.is_triple(): - if self.triple.child1.is_star: + if self.triple.child1.is_star: star = self.triple.child1 bin = self.triple.child2 - else: + else: star = self.triple.child2 bin = self.triple.child1 - return (self.get_mass(bin.child1)-self.get_mass(bin.child2))/self.get_mass(bin) * bin.semimajor_axis/self.triple.semimajor_axis * self.triple.eccentricity/(1-self.triple.eccentricity**2) + return ( + (self.get_mass(bin.child1) - self.get_mass(bin.child2)) + / self.get_mass(bin) + * bin.semimajor_axis + / self.triple.semimajor_axis + * self.triple.eccentricity + / (1 - self.triple.eccentricity**2) + ) else: - print('Octupole parameter needs triple system') - return np.nan - - - + print("Octupole parameter needs triple system") + return np.nan def kozai_timescale(self): if self.is_triple(): - alpha_kozai = 1. - if self.triple.child1.is_star: + alpha_kozai = 1.0 + if self.triple.child1.is_star: star = self.triple.child1 bin = self.triple.child2 - else: + else: star = self.triple.child2 bin = self.triple.child1 - - P_in = self.orbital_period(bin) #period inner binary - P_out = self.orbital_period(self.triple)#period outer binary - return alpha_kozai * P_out**2 / P_in * (self.get_mass(self.triple) / self.get_mass(star)) * (1-self.triple.eccentricity**2)**1.5 + P_in = self.orbital_period(bin) # period inner binary + P_out = self.orbital_period(self.triple) # period outer binary + return ( + alpha_kozai + * P_out**2 + / P_in + * (self.get_mass(self.triple) / self.get_mass(star)) + * (1 - self.triple.eccentricity**2) ** 1.5 + ) else: - print('Kozai timescale needs triple system') - return np.nan - + print("Kozai timescale needs triple system") + return np.nan + def get_kozai_type(self): if self.is_triple(): if self.secular_code.parameters.ignore_tertiary == True: return False t_kozai = self.kozai_timescale() - if t_kozai >kozai_type_factor * self.tend: + if t_kozai > kozai_type_factor * self.tend: return False - + t_ev = self.get_min_stellar_evolution_timescale_of_system() if t_kozai < kozai_type_factor * t_ev: return True else: return False else: - sys.exit('Kozai type needs triple system') - + sys.exit("Kozai type needs triple system") - def get_min_stellar_evolution_timescale_of_system(self, stellar_system = None): + def get_min_stellar_evolution_timescale_of_system(self, stellar_system=None): if stellar_system == None: stellar_system = self.triple if stellar_system.is_star: return stellar_evolution_timescale(stellar_system) else: - t1 = self.get_min_stellar_evolution_timescale_of_system(stellar_system.child1) - t2 = self.get_min_stellar_evolution_timescale_of_system(stellar_system.child2) + t1 = self.get_min_stellar_evolution_timescale_of_system( + stellar_system.child1 + ) + t2 = self.get_min_stellar_evolution_timescale_of_system( + stellar_system.child2 + ) return max(t1, t2) - def check_RLOF(self): if self.triple.is_star: return @@ -795,39 +971,46 @@ def check_RLOF(self): Rl1 = roche_radius(self, self.child1) Rl2 = roche_radius(self, self.child2) if REPORT_TRIPLE_EVOLUTION: - print('Roche lobe radii:', Rl1, Rl2) - print('Stellar radii:', self.triple.child1.radius, self.triple.child2.radius) - + print("Roche lobe radii:", Rl1, Rl2) + print( + "Stellar radii:", + self.triple.child1.radius, + self.triple.child2.radius, + ) + self.triple.child1.is_donor = False self.triple.child2.is_donor = False - - if self.triple.child1.radius >= Rl1 - (1.0 * small_numerical_error|units.RSun): - self.triple.child1.is_donor = True - if self.triple.child2.radius >= Rl2 - (1.0 * small_numerical_error|units.RSun): - self.triple.child2.is_donor = True - + + if self.triple.child1.radius >= Rl1 - ( + 1.0 * small_numerical_error | units.RSun + ): + self.triple.child1.is_donor = True + if self.triple.child2.radius >= Rl2 - ( + 1.0 * small_numerical_error | units.RSun + ): + self.triple.child2.is_donor = True + elif self.is_triple() and self.secular_code.parameters.ignore_tertiary == True: # for disrupted binary if self.triple.child1.is_star: bin = self.triple.child2 else: bin = self.triple.child1 - + Rl1 = roche_radius(bin, bin.child1, self) Rl2 = roche_radius(bin, bin.child2, self) if REPORT_TRIPLE_EVOLUTION: - print('Roche lobe radii:', Rl1, Rl2) - print('Stellar radii:', bin.child1.radius, bin.child2.radius) - + print("Roche lobe radii:", Rl1, Rl2) + print("Stellar radii:", bin.child1.radius, bin.child2.radius) + bin.child1.is_donor = False bin.child2.is_donor = False - - if bin.child1.radius >= Rl1 - (1.0 * small_numerical_error|units.RSun): - bin.child1.is_donor = True - if bin.child2.radius >= Rl2 - (1.0 * small_numerical_error|units.RSun): - bin.child2.is_donor = True - - + + if bin.child1.radius >= Rl1 - (1.0 * small_numerical_error | units.RSun): + bin.child1.is_donor = True + if bin.child2.radius >= Rl2 - (1.0 * small_numerical_error | units.RSun): + bin.child2.is_donor = True + elif self.is_triple(): if self.triple.child1.is_star: star = self.triple.child1 @@ -836,36 +1019,56 @@ def check_RLOF(self): star = self.triple.child2 bin = self.triple.child1 - #assumping secular code always returns inner binary first + # assumping secular code always returns inner binary first Rl1, Rl2, Rl3 = self.secular_code.give_roche_radii(self.triple) - + if REPORT_TRIPLE_EVOLUTION: - print('Roche lobe radii:', Rl1, Rl2, Rl3) - print('Stellar radii:', bin.child1.radius, bin.child2.radius, star.radius) - print('binary Roche lobe radii:', roche_radius(bin, bin.child1, self), roche_radius(bin, bin.child2, self), roche_radius(self.triple, star, self)) - print('eccentric binary Roche lobe radii:', roche_radius(bin, bin.child1, self)* (1-bin.eccentricity), roche_radius(bin, bin.child2, self)* (1-bin.eccentricity), roche_radius(self.triple, star, self)*(1-self.triple.eccentricity)) - print('Masses:', bin.child1.mass, bin.child2.mass, star.mass) - print('Semi:', bin.semimajor_axis, self.triple.semimajor_axis) - print('Ecc:', bin.eccentricity, self.triple.eccentricity) - print('Stellar type:', bin.child1.stellar_type, bin.child2.stellar_type, star.stellar_type) - print('Spin:', bin.child1.spin_angular_frequency, bin.child2.spin_angular_frequency, star.spin_angular_frequency) - + print("Roche lobe radii:", Rl1, Rl2, Rl3) + print( + "Stellar radii:", bin.child1.radius, bin.child2.radius, star.radius + ) + print( + "binary Roche lobe radii:", + roche_radius(bin, bin.child1, self), + roche_radius(bin, bin.child2, self), + roche_radius(self.triple, star, self), + ) + print( + "eccentric binary Roche lobe radii:", + roche_radius(bin, bin.child1, self) * (1 - bin.eccentricity), + roche_radius(bin, bin.child2, self) * (1 - bin.eccentricity), + roche_radius(self.triple, star, self) + * (1 - self.triple.eccentricity), + ) + print("Masses:", bin.child1.mass, bin.child2.mass, star.mass) + print("Semi:", bin.semimajor_axis, self.triple.semimajor_axis) + print("Ecc:", bin.eccentricity, self.triple.eccentricity) + print( + "Stellar type:", + bin.child1.stellar_type, + bin.child2.stellar_type, + star.stellar_type, + ) + print( + "Spin:", + bin.child1.spin_angular_frequency, + bin.child2.spin_angular_frequency, + star.spin_angular_frequency, + ) bin.child1.is_donor = False bin.child2.is_donor = False star.is_donor = False - - if bin.child1.radius >= Rl1 - (1.0 * small_numerical_error|units.RSun): + + if bin.child1.radius >= Rl1 - (1.0 * small_numerical_error | units.RSun): bin.child1.is_donor = True - if bin.child2.radius >= Rl2 - (1.0 * small_numerical_error|units.RSun): + if bin.child2.radius >= Rl2 - (1.0 * small_numerical_error | units.RSun): bin.child2.is_donor = True - if star.radius >= Rl3 - (1.0 * small_numerical_error|units.RSun): + if star.radius >= Rl3 - (1.0 * small_numerical_error | units.RSun): star.is_donor = True - else: - sys.exit('check_RLOF: structure stellar system unknown') - + sys.exit("check_RLOF: structure stellar system unknown") def check_OLOF(self): if self.triple.is_star: @@ -874,17 +1077,25 @@ def check_OLOF(self): Rl2_1 = L2_radius(self, self.child1) Rl2_2 = L2_radius(self, self.child2) if REPORT_TRIPLE_EVOLUTION: - print('L2 lobe radii:', Rl2_1, Rl2_2) - print('Stellar radii:', self.triple.child1.radius, self.triple.child2.radius) - + print("L2 lobe radii:", Rl2_1, Rl2_2) + print( + "Stellar radii:", + self.triple.child1.radius, + self.triple.child2.radius, + ) + self.triple.child1.is_OLOF_donor = False self.triple.child2.is_OLOF_donor = False - - if self.triple.child1.radius >= Rl2_1 - (1.0 * small_numerical_error|units.RSun): - self.triple.child1.is_OLOF_donor = True - if self.triple.child2.radius >= Rl2_2 - (1.0 * small_numerical_error|units.RSun): - self.triple.child2.is_OLOF_donor = True - + + if self.triple.child1.radius >= Rl2_1 - ( + 1.0 * small_numerical_error | units.RSun + ): + self.triple.child1.is_OLOF_donor = True + if self.triple.child2.radius >= Rl2_2 - ( + 1.0 * small_numerical_error | units.RSun + ): + self.triple.child2.is_OLOF_donor = True + elif self.is_triple(): # for disrupted binary if self.triple.child1.is_star: @@ -893,143 +1104,212 @@ def check_OLOF(self): else: star = self.triple.child2 bin = self.triple.child1 - + Rl2_1 = L2_radius(bin, bin.child1, self) Rl2_2 = L2_radius(bin, bin.child2, self) - + bin.child1.is_OLOF_donor = False bin.child2.is_OLOF_donor = False - - if bin.child1.radius >= Rl2_1 - (1.0 * small_numerical_error|units.RSun): - bin.child1.is_OLOF_donor = True - if bin.child2.radius >= Rl2_2 - (1.0 * small_numerical_error|units.RSun): - bin.child2.is_OLOF_donor = True - + + if bin.child1.radius >= Rl2_1 - (1.0 * small_numerical_error | units.RSun): + bin.child1.is_OLOF_donor = True + if bin.child2.radius >= Rl2_2 - (1.0 * small_numerical_error | units.RSun): + bin.child2.is_OLOF_donor = True + if REPORT_TRIPLE_EVOLUTION: - print('L2 lobe radii:', Rl2_1, Rl2_2) - print('Stellar radii:', bin.child1.radius, bin.child2.radius) - print('Masses:', bin.child1.mass, bin.child2.mass, star.mass) - print('Semi:', bin.semimajor_axis, self.triple.semimajor_axis) - print('Ecc:', bin.eccentricity, self.triple.eccentricity) - print('Stellar type:', bin.child1.stellar_type, bin.child2.stellar_type, star.stellar_type) - print('Spin:', bin.child1.spin_angular_frequency, bin.child2.spin_angular_frequency, star.spin_angular_frequency) - + print("L2 lobe radii:", Rl2_1, Rl2_2) + print("Stellar radii:", bin.child1.radius, bin.child2.radius) + print("Masses:", bin.child1.mass, bin.child2.mass, star.mass) + print("Semi:", bin.semimajor_axis, self.triple.semimajor_axis) + print("Ecc:", bin.eccentricity, self.triple.eccentricity) + print( + "Stellar type:", + bin.child1.stellar_type, + bin.child2.stellar_type, + star.stellar_type, + ) + print( + "Spin:", + bin.child1.spin_angular_frequency, + bin.child2.spin_angular_frequency, + star.spin_angular_frequency, + ) + else: - print('check_OLOF: structure stellar system unknown') - sys.exit('check_OLOF: structure stellar system unknown') + print("check_OLOF: structure stellar system unknown") + sys.exit("check_OLOF: structure stellar system unknown") + def check_CHE(self): # future option: potentially use: che_flag in SeBa + # returns true when one or both of the inner binary components are chemically homogeneously evolving + # if !include_CHE, then return False + # problematic for quadruples - what if one binary is CHE, and other is not - def check_CHE(self): #future option: potentially use: che_flag in SeBa - #returns true when one or both of the inner binary components are chemically homogeneously evolving - #if !include_CHE, then return False - #problematic for quadruples - what if one binary is CHE, and other is not - metallicity = self.stellar_code.parameters.metallicity if self.triple.is_star: return False - elif self.is_binary(): + elif self.is_binary(): bin = self.triple - if self.include_CHE and ((bin.child1.spin_angular_frequency >= criticial_angular_frequency_CHE(bin.child1.mass, metallicity) and bin.child1.stellar_type <= 1|units.stellar_type) or - (bin.child2.spin_angular_frequency >= criticial_angular_frequency_CHE(bin.child2.mass, metallicity) and bin.child2.stellar_type <= 1|units.stellar_type)): - return True - else: + if self.include_CHE and ( + ( + bin.child1.spin_angular_frequency + >= criticial_angular_frequency_CHE(bin.child1.mass, metallicity) + and bin.child1.stellar_type <= 1 | units.stellar_type + ) + or ( + bin.child2.spin_angular_frequency + >= criticial_angular_frequency_CHE(bin.child2.mass, metallicity) + and bin.child2.stellar_type <= 1 | units.stellar_type + ) + ): + return True + else: return False - + elif self.is_triple(): if self.triple.child1.is_star: bin = self.triple.child2 else: bin = self.triple.child1 - if self.include_CHE and ((bin.child1.spin_angular_frequency >= criticial_angular_frequency_CHE(bin.child1.mass, metallicity) and bin.child1.stellar_type <= 1|units.stellar_type) or - (bin.child2.spin_angular_frequency >= criticial_angular_frequency_CHE(bin.child2.mass, metallicity) and bin.child2.stellar_type <= 1|units.stellar_type)): - return True - else: + if self.include_CHE and ( + ( + bin.child1.spin_angular_frequency + >= criticial_angular_frequency_CHE(bin.child1.mass, metallicity) + and bin.child1.stellar_type <= 1 | units.stellar_type + ) + or ( + bin.child2.spin_angular_frequency + >= criticial_angular_frequency_CHE(bin.child2.mass, metallicity) + and bin.child2.stellar_type <= 1 | units.stellar_type + ) + ): + return True + else: return False else: - print('check_CHE: structure stellar system unknown') - sys.exit('check_CHE: structure stellar system unknown') - - - - - -# -# def determine_partial_timestep_stable_mass_transfer(self, stellar_system = None): -# if stellar_system == None: -# stellar_system = self.triple -# -# if stellar_system.is_star: -# return np.inf |units.Myr -# else: -# dt1 = self.determine_partial_timestep_stable_mass_transfer(stellar_system.child1) -# dt2 = self.determine_partial_timestep_stable_mass_transfer(stellar_system.child2) -# dt = stellar_system.part_dt_mt -# return min(dt, min(dt1, dt2)) - - #------- - - #------- + print("check_CHE: structure stellar system unknown") + sys.exit("check_CHE: structure stellar system unknown") + + # + # def determine_partial_timestep_stable_mass_transfer(self, stellar_system = None): + # if stellar_system == None: + # stellar_system = self.triple + # + # if stellar_system.is_star: + # return np.inf |units.Myr + # else: + # dt1 = self.determine_partial_timestep_stable_mass_transfer(stellar_system.child1) + # dt2 = self.determine_partial_timestep_stable_mass_transfer(stellar_system.child2) + # dt = stellar_system.part_dt_mt + # return min(dt, min(dt1, dt2)) + + # ------- + + # ------- # useful functions for printing def print_star(self, star): if star.is_star: - print('star:') - print(star.age, ) - print(star.stellar_type, ) - print(star.mass, ) - print(star.radius, ) - print(star.core_mass, ) - print(star.core_radius,) - print(star.convective_envelope_mass,) - print(star.convective_envelope_radius,) - print(star.luminosity,) - print(star.temperature,) - print(star.wind_mass_loss_rate,) - print(star.spin_angular_frequency,) + print("star:") + print( + star.age, + ) + print( + star.stellar_type, + ) + print( + star.mass, + ) + print( + star.radius, + ) + print( + star.core_mass, + ) + print( + star.core_radius, + ) + print( + star.convective_envelope_mass, + ) + print( + star.convective_envelope_radius, + ) + print( + star.luminosity, + ) + print( + star.temperature, + ) + print( + star.wind_mass_loss_rate, + ) + print( + star.spin_angular_frequency, + ) print(star.is_donor) - print('\t') + print("\t") else: - sys.exit('print_star needs a star') - - + sys.exit("print_star needs a star") + def print_binary(self, binary): if not binary.is_star: - print(self.get_mass(binary), ) - print(binary.semimajor_axis,) - print(binary.eccentricity, ) - print(binary.argument_of_pericenter, ) - print(binary.longitude_of_ascending_node,) - print(binary.mass_transfer_rate,) -# print(binary.mass_transfer_timescale,) - print(binary.accretion_efficiency_mass_transfer,) - print(binary.accretion_efficiency_wind_child1_to_child2,) - print(binary.accretion_efficiency_wind_child2_to_child1,) - print(binary.specific_AM_loss_mass_transfer,) + print( + self.get_mass(binary), + ) + print( + binary.semimajor_axis, + ) + print( + binary.eccentricity, + ) + print( + binary.argument_of_pericenter, + ) + print( + binary.longitude_of_ascending_node, + ) + print( + binary.mass_transfer_rate, + ) + # print(binary.mass_transfer_timescale,) + print( + binary.accretion_efficiency_mass_transfer, + ) + print( + binary.accretion_efficiency_wind_child1_to_child2, + ) + print( + binary.accretion_efficiency_wind_child2_to_child1, + ) + print( + binary.specific_AM_loss_mass_transfer, + ) print(binary.is_mt_stable) - print('\t') + print("\t") else: - sys.exit('print_binary needs a binary') + sys.exit("print_binary needs a binary") - - - def print_stellar_system(self, stellar_system = None): + def print_stellar_system(self, stellar_system=None): if stellar_system == None: stellar_system = self.triple - print(stellar_system.number,) + print( + stellar_system.number, + ) print(stellar_system.relative_inclination) if stellar_system.is_star: self.print_star(stellar_system) else: - print('binary star: ') + print("binary star: ") self.print_binary(stellar_system) self.print_stellar_system(stellar_system.child1) self.print_stellar_system(stellar_system.child2) - print('\t') - #------- - #------- - #don't change this unless you know what you're doing - def remove_parents(self, stellar_system = None): + print("\t") + + # ------- + # ------- + # don't change this unless you know what you're doing + def remove_parents(self, stellar_system=None): if stellar_system == None: stellar_system = self.triple @@ -1039,54 +1319,53 @@ def remove_parents(self, stellar_system = None): p = stellar_system.parent stellar_system.parent = 0 return p - except AttributeError: #when there is no parent + except AttributeError: # when there is no parent return 0 else: parents.append(self.remove_parents(stellar_system.child1)) parents.append(self.remove_parents(stellar_system.child2)) p = stellar_system.parent -# except AttributeError: #when there is no parent= + # except AttributeError: #when there is no parent= if p != None: stellar_system.parent = 0 - parents.append(p) + parents.append(p) return parents - - #don't change this unless you know what you're doing - def set_parents(self, parents, stellar_system=None): + + # don't change this unless you know what you're doing + def set_parents(self, parents, stellar_system=None): if stellar_system == None: stellar_system = self.triple if stellar_system.is_star: - stellar_system.parent = parents + stellar_system.parent = parents else: self.set_parents(parents[0], stellar_system.child1) self.set_parents(parents[1], stellar_system.child2) if len(parents) == 3: stellar_system.parent = parents[2] elif len(parents) != 2: - sys.exit('set_parents: structure stellar system unknown') + sys.exit("set_parents: structure stellar system unknown") - def save_snapshot(self): file_name = self.file_name snapshot_triple = self.triple.copy() - #make nice recursive loop - #find star & bin particles sets + # make nice recursive loop + # find star & bin particles sets if snapshot_triple.is_star: star_particle_set = snapshot_triple.particles_set bin_particle_set = None else: bin_particle_set = snapshot_triple.particles_set - + if snapshot_triple.child1.is_star: star_particle_set = snapshot_triple.child1.particles_set else: - sys.exit('save_snapshot: structure stellar system unknown') + sys.exit("save_snapshot: structure stellar system unknown") - #deleting redundant parameters of stellar particle set + # deleting redundant parameters of stellar particle set del star_particle_set.apsidal_motion_constant del star_particle_set.convective_envelope_mass del star_particle_set.convective_envelope_radius @@ -1102,7 +1381,7 @@ def save_snapshot(self): del star_particle_set.time_derivative_of_radius del star_particle_set.wind_mass_loss_rate - #deleting redundant parameters of binary particle set + # deleting redundant parameters of binary particle set del bin_particle_set.accretion_efficiency_mass_transfer del bin_particle_set.accretion_efficiency_wind_child1_to_child2 del bin_particle_set.accretion_efficiency_wind_child2_to_child1 @@ -1113,174 +1392,249 @@ def save_snapshot(self): del bin_particle_set.previous_mass del bin_particle_set.specific_AM_loss_mass_transfer - - #double parameters -# del snapshot_triple.child2.particles_set.CPU_time -# del snapshot_triple.child2.particles_set.time -# del snapshot_triple.child2.particles_set.dynamical_instability -# del snapshot_triple.child2.particles_set.error_flag_secular -# del snapshot_triple.child2.particles_set.delta_e_in -# del snapshot_triple.child2.particles_set.max_delta_e_in -# del snapshot_triple.child2.particles_set.number - - #some minor parameters are not saved: -# self.instantaneous_evolution = False -# self.tend = tend #... -# self.triple.time = 0.0|units.yr -# self.previous_time = 0.0|units.yr -# self.file_name -# self.file_type - - - if self.file_type == 'txt': - print(self.file_name,self.file_type) + # double parameters + # del snapshot_triple.child2.particles_set.CPU_time + # del snapshot_triple.child2.particles_set.time + # del snapshot_triple.child2.particles_set.dynamical_instability + # del snapshot_triple.child2.particles_set.error_flag_secular + # del snapshot_triple.child2.particles_set.delta_e_in + # del snapshot_triple.child2.particles_set.max_delta_e_in + # del snapshot_triple.child2.particles_set.number + + # some minor parameters are not saved: + # self.instantaneous_evolution = False + # self.tend = tend #... + # self.triple.time = 0.0|units.yr + # self.previous_time = 0.0|units.yr + # self.file_name + # self.file_type + + if self.file_type == "txt": + print(self.file_name, self.file_type) bin_particle_set.parent = 0 star_particle_set.parent = 0 - write_set_to_file(snapshot_triple.as_set(), self.file_name, self.file_type) + write_set_to_file(snapshot_triple.as_set(), self.file_name, self.file_type) else: - write_set_to_file(snapshot_triple.as_set(), self.file_name, self.file_type, version='2.0', append_to_file=True) + write_set_to_file( + snapshot_triple.as_set(), + self.file_name, + self.file_type, + version="2.0", + append_to_file=True, + ) del snapshot_triple - + self.triple.child2.max_delta_e_in = 0 + # ------- - #------- - - #------- + # ------- # determining time steps - def determine_time_step_wind(self, stellar_system = None): - #note: returned value can be inf when the wind_mass_loss_rate = 0 + def determine_time_step_wind(self, stellar_system=None): + # note: returned value can be inf when the wind_mass_loss_rate = 0 if stellar_system == None: stellar_system = self.triple - - if stellar_system.is_star: - dt = np.inf |units.Myr - if stellar_system.wind_mass_loss_rate * -1. > quantities.zero: - dt = maximum_wind_mass_loss_factor * (stellar_system.mass - stellar_system.core_mass)/stellar_system.wind_mass_loss_rate*-1. + if stellar_system.is_star: + dt = np.inf | units.Myr + + if stellar_system.wind_mass_loss_rate * -1.0 > quantities.zero: + dt = ( + maximum_wind_mass_loss_factor + * (stellar_system.mass - stellar_system.core_mass) + / stellar_system.wind_mass_loss_rate + * -1.0 + ) if REPORT_DT: print("Dt_wind_star = ", dt) - return dt + return dt else: - dt1 = self.determine_time_step_wind(stellar_system.child1) + dt1 = self.determine_time_step_wind(stellar_system.child1) dt2 = self.determine_time_step_wind(stellar_system.child2) if REPORT_DT: print("Dt_wind_binary = ", dt1, dt2) - return min(dt1, dt2) - - + return min(dt1, dt2) - def determine_time_step_radius_change(self, stellar_system = None): - #note: returned value can be inf when the change in radius <= 0 - #radius is only necessary for tides + def determine_time_step_radius_change(self, stellar_system=None): + # note: returned value can be inf when the change in radius <= 0 + # radius is only necessary for tides - if not self.secular_code.parameters.include_inner_tidal_terms and not self.secular_code.parameters.include_outer_tidal_terms: - return np.inf |units.Myr + if ( + not self.secular_code.parameters.include_inner_tidal_terms + and not self.secular_code.parameters.include_outer_tidal_terms + ): + return np.inf | units.Myr if stellar_system == None: stellar_system = self.triple - + if stellar_system.is_star: if stellar_system.time_derivative_of_radius == quantities.zero: - dt = np.inf |units.Myr - else: + dt = np.inf | units.Myr + else: if stellar_system.previous_time_derivative_of_radius == quantities.zero: growth_factor = 0.1 - elif stellar_system.previous_time_derivative_of_radius * stellar_system.time_derivative_of_radius < quantities.zero: + elif ( + stellar_system.previous_time_derivative_of_radius + * stellar_system.time_derivative_of_radius + < quantities.zero + ): growth_factor = 0.01 else: - growth_factor = stellar_system.previous_time_derivative_of_radius/stellar_system.time_derivative_of_radius + growth_factor = ( + stellar_system.previous_time_derivative_of_radius + / stellar_system.time_derivative_of_radius + ) if growth_factor > 1: - growth_factor = 1./growth_factor - - if stellar_system.stellar_type > 1|units.stellar_type and stellar_system.time_derivative_of_radius < stellar_system.previous_time_derivative_of_radius: #not a MS star and Rdot < Rdot_prev - growth_factor = 1. - - dt = abs(growth_factor * self.maximum_radius_change_factor*stellar_system.radius / stellar_system.time_derivative_of_radius) - + growth_factor = 1.0 / growth_factor + + if ( + stellar_system.stellar_type > 1 | units.stellar_type + and stellar_system.time_derivative_of_radius + < stellar_system.previous_time_derivative_of_radius + ): # not a MS star and Rdot < Rdot_prev + growth_factor = 1.0 + + dt = abs( + growth_factor + * self.maximum_radius_change_factor + * stellar_system.radius + / stellar_system.time_derivative_of_radius + ) if REPORT_DT: print("Dt_radius_change_star = ", dt) - return dt + return dt else: - dt1 = self.determine_time_step_radius_change(stellar_system.child1) + dt1 = self.determine_time_step_radius_change(stellar_system.child1) dt2 = self.determine_time_step_radius_change(stellar_system.child2) if REPORT_DT: print("Dt_radius_change_binary = ", dt1, dt2) - return min(dt1, dt2) + return min(dt1, dt2) def determine_time_step_kozai(self): - #note: returned value can be inf when the system is a binary or single star + # note: returned value can be inf when the system is a binary or single star if self.is_triple(): - dt = self.kozai_timescale()*time_step_factor_kozai + dt = self.kozai_timescale() * time_step_factor_kozai if REPORT_DT: print("Dt_kozai = ", dt) else: - dt = np.inf |units.Myr - + dt = np.inf | units.Myr + P_out = self.orbital_period(self.triple) - P_in = self.orbital_period(self.triple.child2) + P_in = self.orbital_period(self.triple.child2) return dt - - def determine_time_step_stable_mt(self, stellar_system = None): - #note: returned value can be inf when the mass_transfer_rate = 0 + def determine_time_step_stable_mt(self, stellar_system=None): + # note: returned value can be inf when the mass_transfer_rate = 0 if stellar_system == None: stellar_system = self.triple - + if stellar_system.is_star: - dt = np.inf |units.Myr + dt = np.inf | units.Myr if stellar_system.is_donor: - dt = abs(time_step_factor_stable_mt*stellar_system.mass/stellar_system.parent.mass_transfer_rate) + dt = abs( + time_step_factor_stable_mt + * stellar_system.mass + / stellar_system.parent.mass_transfer_rate + ) if REPORT_DT: - print("Dt_mt_star = ", dt, time_step_factor_stable_mt, stellar_system.mass, stellar_system.parent.mass_transfer_rate ) + print( + "Dt_mt_star = ", + dt, + time_step_factor_stable_mt, + stellar_system.mass, + stellar_system.parent.mass_transfer_rate, + ) return dt else: - dt1 = self.determine_time_step_stable_mt(stellar_system.child1) + dt1 = self.determine_time_step_stable_mt(stellar_system.child1) dt2 = self.determine_time_step_stable_mt(stellar_system.child2) if REPORT_DT: print("Dt_mt_binary = ", dt1, dt2) - return min(dt1, dt2) - - - #based on secular code - def e_dot_tides(self, star,m_comp, semi, eccentricity): + return min(dt1, dt2) + + # based on secular code + def e_dot_tides(self, star, m_comp, semi, eccentricity): e_p2 = eccentricity**2 - l = np.sqrt(1.0 - e_p2) - f_tides3 = 1.0 + e_p2*(15./4. + e_p2*(15./8. + e_p2*5./64.)) - f_tides4 = 1.0 + e_p2*(3./2 + e_p2/8.) - - R_div_a = star.radius/semi - spin = star.spin_angular_frequency - k_div_T_tides = tidal_friction_constant(star.stellar_type, star.mass, m_comp, semi, star.radius, star.convective_envelope_mass, star.convective_envelope_radius, star.luminosity, spin, star.gyration_radius, star.apsidal_motion_constant) - n = corotating_spin_angular_frequency_binary(semi, star.mass, m_comp) # mean orbital angular speed + l = np.sqrt(1.0 - e_p2) + f_tides3 = 1.0 + e_p2 * (15.0 / 4.0 + e_p2 * (15.0 / 8.0 + e_p2 * 5.0 / 64.0)) + f_tides4 = 1.0 + e_p2 * (3.0 / 2 + e_p2 / 8.0) - e_dot = -27.0*(1.0+m_comp/star.mass)*(m_comp/star.mass) * R_div_a**6 * k_div_T_tides * R_div_a**2 *eccentricity* (l**-13.0) * (f_tides3 - 11.0/18.0*(l**3)*f_tides4*(spin/n)) -# print(star.mass, m_comp, semi, eccentricity, k_div_T_tides, e_dot) + R_div_a = star.radius / semi + spin = star.spin_angular_frequency + k_div_T_tides = tidal_friction_constant( + star.stellar_type, + star.mass, + m_comp, + semi, + star.radius, + star.convective_envelope_mass, + star.convective_envelope_radius, + star.luminosity, + spin, + star.gyration_radius, + star.apsidal_motion_constant, + ) + n = corotating_spin_angular_frequency_binary( + semi, star.mass, m_comp + ) # mean orbital angular speed + + e_dot = ( + -27.0 + * (1.0 + m_comp / star.mass) + * (m_comp / star.mass) + * R_div_a**6 + * k_div_T_tides + * R_div_a**2 + * eccentricity + * (l**-13.0) + * (f_tides3 - 11.0 / 18.0 * (l**3) * f_tides4 * (spin / n)) + ) + # print(star.mass, m_comp, semi, eccentricity, k_div_T_tides, e_dot) return e_dot - - - - def determine_time_step_tides(self, stellar_system = None): -# print("determine_time_step_tides") + + def determine_time_step_tides(self, stellar_system=None): + # print("determine_time_step_tides") if stellar_system == None: stellar_system = self.triple - if self.triple.is_star: - return False, 0 + return False, 0 elif self.is_binary(): Rl1 = roche_radius(self, self.child1) Rl2 = roche_radius(self, self.child2) if self.triple.child1.radius >= Rl1 or self.triple.child2.radius >= Rl2: - return abs(time_step_factor_stable_mt*min(self.triple.child1.mass, self.triple.child2.mass)/self.triple.mass_transfer_rate) - else: - de_dt_child1 = abs(self.e_dot_tides(self.triple.child1, self.triple.child2.mass, self.triple.semimajor_axis, self.triple.eccentricity)) - de_dt_child2 = abs(self.e_dot_tides(self.triple.child2, self.triple.child1.mass, self.triple.semimajor_axis, self.triple.eccentricity)) - return time_step_factor_ecc * self.triple.eccentricity / max(de_dt_child1, de_dt_child2) + return abs( + time_step_factor_stable_mt + * min(self.triple.child1.mass, self.triple.child2.mass) + / self.triple.mass_transfer_rate + ) + else: + de_dt_child1 = abs( + self.e_dot_tides( + self.triple.child1, + self.triple.child2.mass, + self.triple.semimajor_axis, + self.triple.eccentricity, + ) + ) + de_dt_child2 = abs( + self.e_dot_tides( + self.triple.child2, + self.triple.child1.mass, + self.triple.semimajor_axis, + self.triple.eccentricity, + ) + ) + return ( + time_step_factor_ecc + * self.triple.eccentricity + / max(de_dt_child1, de_dt_child2) + ) elif self.is_triple(): - + if self.triple.child1.is_star: star = self.triple.child1 bin = self.triple.child2 @@ -1290,387 +1644,470 @@ def determine_time_step_tides(self, stellar_system = None): Rl1, Rl2, Rl3 = self.secular_code.give_roche_radii(self.triple) if star.radius >= Rl3: - sys.exit('R>Rl3') + sys.exit("R>Rl3") elif bin.child1.radius >= Rl1 or bin.child2.radius >= Rl2: - return abs(time_step_factor_stable_mt*min(bin.child1.mass, bin.child2.mass)/self.triple.mass_transfer_rate) + return abs( + time_step_factor_stable_mt + * min(bin.child1.mass, bin.child2.mass) + / self.triple.mass_transfer_rate + ) else: - de_dt_star = abs(self.e_dot_tides(star, self.get_mass(bin), self.triple.semimajor_axis, self.triple.eccentricity)) - de_dt_bin_child1 = abs(self.e_dot_tides(bin.child1, bin.child2.mass, bin.semimajor_axis, bin.eccentricity)) - de_dt_bin_child2 = abs(self.e_dot_tides(bin.child2, bin.child1.mass, bin.semimajor_axis, bin.eccentricity)) + de_dt_star = abs( + self.e_dot_tides( + star, + self.get_mass(bin), + self.triple.semimajor_axis, + self.triple.eccentricity, + ) + ) + de_dt_bin_child1 = abs( + self.e_dot_tides( + bin.child1, + bin.child2.mass, + bin.semimajor_axis, + bin.eccentricity, + ) + ) + de_dt_bin_child2 = abs( + self.e_dot_tides( + bin.child2, + bin.child1.mass, + bin.semimajor_axis, + bin.eccentricity, + ) + ) dt_star = time_step_factor_ecc * self.triple.eccentricity / de_dt_star - dt_bin = time_step_factor_ecc * bin.eccentricity / max(de_dt_bin_child1, de_dt_bin_child2) + dt_bin = ( + time_step_factor_ecc + * bin.eccentricity + / max(de_dt_bin_child1, de_dt_bin_child2) + ) return min(dt_star, dt_bin) - else: - sys.exit('determine_time_step_tides: structure stellar system unknown') - - - - - -# def close_to_RLOF(self): -# -# if self.triple.is_star: -# return False, 0 -# elif self.is_binary(): -# Rl1 = roche_radius(self, self.child1) -# Rl2 = roche_radius(self, self.child2) -# if self.triple.child1.radius >= Rl1 or self.triple.child2.radius >= Rl2: -# print('close to rlof already rlof') -# exit(0) -# elif self.triple.child1.radius >= Rl_fraction*Rl1 and self.triple.child2.radius >= Rl_fraction*Rl2: -# ratio_rad_rlof = maximum(self.triple.child1.radius/Rl1, self.triple.child2.radius/Rl2) -# print('dt_close_to_mt', time_step_factor_stable_mt, self.triple.child1.mass, self.triple.child2.mass, self.triple.mass_transfer_rate) -# dt = abs(time_step_factor_stable_mt*min(self.triple.child1.mass, self.triple.child2.mass)/self.triple.mass_transfer_rate) -# return True, ratio_rad_rlof, dt -# elif self.triple.child1.radius >= Rl_fraction*Rl1: -# ratio_rad_rlof = self.triple.child1.radius/Rl1 -# print('dt_close_to_mt', time_step_factor_stable_mt, self.triple.child1.mass, self.triple.mass_transfer_rate) -# dt = abs(time_step_factor_stable_mt*self.triple.child1.mass/self.triple.mass_transfer_rate) -# return True, ratio_rad_rlof, dt -# elif self.triple.child2.radius >= Rl_fraction*Rl2: -# ratio_rad_rlof = self.triple.child2.radius/Rl2 -# print('dt_close_to_mt', time_step_factor_stable_mt, self.triple.child2.mass, self.triple.mass_transfer_rate) -# dt = abs(time_step_factor_stable_mt*self.triple.child2.mass/self.triple.mass_transfer_rate) -# return True, ratio_rad_rlof, dt -# else: -# return False, 0, 0 -# elif self.is_triple(): -# if self.triple.child1.is_star: -# star = self.triple.child1 -# bin = self.triple.child2 -# else: -# star = self.triple.child2 -# bin = self.triple.child1 -# -# #assumping secular code always returns inner binary first -# Rl1, Rl2, Rl3 = self.secular_code.give_roche_radii(self.triple) -# if bin.child1.radius >= Rl1 or bin.child2.radius >= Rl2 or star.radius >= Rl3: -# print('close to rlof already rlof') -# exit(0) -# -# dt=[] -# ratio_rad_rlof=[] -# if star.radius >= Rl_fraction*Rl3: -# ratio_rad_rlof.append(star.radius / Rl3) -# print('dt_close_to_mt', time_step_factor_stable_mt, star.mass, star.parent.mass_transfer_rate) -# dt.append(abs(time_step_factor_stable_mt*star.mass/star.parent.mass_transfer_rate)) -# if bin.child1.radius >= Rl_fraction*Rl1: -# ratio_rad_rlof.append(bin.child1.radius / Rl1) -# print('dt_close_to_mt', time_step_factor_stable_mt, bin.child1.mass, bin.mass_transfer_rate) -# dt.append(abs(time_step_factor_stable_mt*bin.child1.mass/bin.mass_transfer_rate)) -# if bin.child2.radius >= Rl_fraction*Rl2: -# ratio_rad_rlof.append(bin.child2.radius / Rl2) -# print('dt_close_to_mt', time_step_factor_stable_mt, bin.child2.mass, bin.mass_transfer_rate) -# dt.append(abs(time_step_factor_stable_mt*bin.child2.mass/bin.mass_transfer_rate)) -# -# if len(dt) > 0: -# print('close to rlof', ratio_rad_rlof, dt) -# return True, max(ratio_rad_rlof), min(dt) -# else: -# return False, 0, 0 -# else: -# print('close_to_RLOF: structure stellar system unknown') -# exit(2) - - - def determine_time_step(self): + else: + sys.exit("determine_time_step_tides: structure stellar system unknown") + + # def close_to_RLOF(self): + # + # if self.triple.is_star: + # return False, 0 + # elif self.is_binary(): + # Rl1 = roche_radius(self, self.child1) + # Rl2 = roche_radius(self, self.child2) + # if self.triple.child1.radius >= Rl1 or self.triple.child2.radius >= Rl2: + # print('close to rlof already rlof') + # exit(0) + # elif self.triple.child1.radius >= Rl_fraction*Rl1 and self.triple.child2.radius >= Rl_fraction*Rl2: + # ratio_rad_rlof = maximum(self.triple.child1.radius/Rl1, self.triple.child2.radius/Rl2) + # print('dt_close_to_mt', time_step_factor_stable_mt, self.triple.child1.mass, self.triple.child2.mass, self.triple.mass_transfer_rate) + # dt = abs(time_step_factor_stable_mt*min(self.triple.child1.mass, self.triple.child2.mass)/self.triple.mass_transfer_rate) + # return True, ratio_rad_rlof, dt + # elif self.triple.child1.radius >= Rl_fraction*Rl1: + # ratio_rad_rlof = self.triple.child1.radius/Rl1 + # print('dt_close_to_mt', time_step_factor_stable_mt, self.triple.child1.mass, self.triple.mass_transfer_rate) + # dt = abs(time_step_factor_stable_mt*self.triple.child1.mass/self.triple.mass_transfer_rate) + # return True, ratio_rad_rlof, dt + # elif self.triple.child2.radius >= Rl_fraction*Rl2: + # ratio_rad_rlof = self.triple.child2.radius/Rl2 + # print('dt_close_to_mt', time_step_factor_stable_mt, self.triple.child2.mass, self.triple.mass_transfer_rate) + # dt = abs(time_step_factor_stable_mt*self.triple.child2.mass/self.triple.mass_transfer_rate) + # return True, ratio_rad_rlof, dt + # else: + # return False, 0, 0 + # elif self.is_triple(): + # if self.triple.child1.is_star: + # star = self.triple.child1 + # bin = self.triple.child2 + # else: + # star = self.triple.child2 + # bin = self.triple.child1 + # + # #assumping secular code always returns inner binary first + # Rl1, Rl2, Rl3 = self.secular_code.give_roche_radii(self.triple) + # if bin.child1.radius >= Rl1 or bin.child2.radius >= Rl2 or star.radius >= Rl3: + # print('close to rlof already rlof') + # exit(0) + # + # dt=[] + # ratio_rad_rlof=[] + # if star.radius >= Rl_fraction*Rl3: + # ratio_rad_rlof.append(star.radius / Rl3) + # print('dt_close_to_mt', time_step_factor_stable_mt, star.mass, star.parent.mass_transfer_rate) + # dt.append(abs(time_step_factor_stable_mt*star.mass/star.parent.mass_transfer_rate)) + # if bin.child1.radius >= Rl_fraction*Rl1: + # ratio_rad_rlof.append(bin.child1.radius / Rl1) + # print('dt_close_to_mt', time_step_factor_stable_mt, bin.child1.mass, bin.mass_transfer_rate) + # dt.append(abs(time_step_factor_stable_mt*bin.child1.mass/bin.mass_transfer_rate)) + # if bin.child2.radius >= Rl_fraction*Rl2: + # ratio_rad_rlof.append(bin.child2.radius / Rl2) + # print('dt_close_to_mt', time_step_factor_stable_mt, bin.child2.mass, bin.mass_transfer_rate) + # dt.append(abs(time_step_factor_stable_mt*bin.child2.mass/bin.mass_transfer_rate)) + # + # if len(dt) > 0: + # print('close to rlof', ratio_rad_rlof, dt) + # return True, max(ratio_rad_rlof), min(dt) + # else: + # return False, 0, 0 + # else: + # print('close_to_RLOF: structure stellar system unknown') + # exit(2) + + def determine_time_step(self): if REPORT_DT: - print("Dt = ", self.stellar_code.particles.time_step, self.tend, self.previous_time) + print( + "Dt = ", + self.stellar_code.particles.time_step, + self.tend, + self.previous_time, + ) + + # maximum time_step + time_step_max = self.tend - self.triple.time - #maximum time_step - time_step_max = self.tend - self.triple.time - - #make sure we hit the timestamp of tinit + # make sure we hit the timestamp of tinit if self.triple.time < self.tinit: time_step_max = min(time_step_max, self.tinit - self.triple.time) - + # time_step of stellar evolution time_step_stellar_code = self.stellar_code.particles.time_step # small time_step after type change # done automatically by SeBa when due to wind mass losses, but not during RLOF if self.has_stellar_type_changed(): - time_step_stellar_code.append(minimum_time_step) - + time_step_stellar_code.append(minimum_time_step) + # small time_step during heavy wind mass losses - time_step_wind = self.determine_time_step_wind() + time_step_wind = self.determine_time_step_wind() # small time_step during phases of fast growth (note: not yet during fast shrinkage) - time_step_radius_change = self.determine_time_step_radius_change() - -# #during stable mass transfer -# if self.has_donor(): -## print(time_step, self.determine_time_step_stable_mt()) -# time_step = min(time_step, self.determine_time_step_stable_mt()) -# if REPORT_DT or REPORT_TRIPLE_EVOLUTION or REPORT_DEBUG: -# print('donor time:', self.determine_time_step_stable_mt()) - - #tides - ADD ALSO DURING MT - time_step_tides = np.inf |units.Myr - #interesting alternative, slows down code -# if self.secular_code.parameters.include_inner_tidal_terms or self.secular_code.parameters.include_outer_tidal_terms: -# time_step_tides = self.determine_time_step_tides() - - if REPORT_DT or REPORT_DEBUG: - print('time:', self.triple.time, time_step_max, time_step_stellar_code, time_step_wind, time_step_radius_change, time_step_tides) + time_step_radius_change = self.determine_time_step_radius_change() + # #during stable mass transfer + # if self.has_donor(): + ## print(time_step, self.determine_time_step_stable_mt()) + # time_step = min(time_step, self.determine_time_step_stable_mt()) + # if REPORT_DT or REPORT_TRIPLE_EVOLUTION or REPORT_DEBUG: + # print('donor time:', self.determine_time_step_stable_mt()) + # tides - ADD ALSO DURING MT + time_step_tides = np.inf | units.Myr + # interesting alternative, slows down code + # if self.secular_code.parameters.include_inner_tidal_terms or self.secular_code.parameters.include_outer_tidal_terms: + # time_step_tides = self.determine_time_step_tides() + + if REPORT_DT or REPORT_DEBUG: + print( + "time:", + self.triple.time, + time_step_max, + time_step_stellar_code, + time_step_wind, + time_step_radius_change, + time_step_tides, + ) if not self.has_donor(): if REPORT_DT: - print('no RLOF' ) - time_step = min(time_step_radius_change, min(time_step_wind, min( min(time_step_stellar_code), time_step_max))) + print("no RLOF") + time_step = min( + time_step_radius_change, + min(time_step_wind, min(min(time_step_stellar_code), time_step_max)), + ) if time_step_tides < time_step: Rl1, Rl2, Rl3 = self.secular_code.give_roche_radii(self.triple) if REPORT_DT: print(time_step, time_step_tides) - print(Rl1,Rl2,Rl3) - print(self.triple.child2.child1.radius, self.triple.child2.child2.radius, self.triple.child1.radius ) + print(Rl1, Rl2, Rl3) + print( + self.triple.child2.child1.radius, + self.triple.child2.child2.radius, + self.triple.child1.radius, + ) time_step = time_step_tides if REPORT_DT or REPORT_DEBUG: - print('min increase', time_step, maximum_time_step_factor*self.previous_dt) - - - time_step = min(time_step, maximum_time_step_factor*self.previous_dt) - - - elif self.has_donor() and self.triple.bin_type == 'detached' and self.triple.child2.bin_type == 'detached': - #find beginning of RLOF carefully - time_step = time_step_factor_find_RLOF*self.previous_dt + print( + "min increase", + time_step, + maximum_time_step_factor * self.previous_dt, + ) + + time_step = min(time_step, maximum_time_step_factor * self.previous_dt) + + elif ( + self.has_donor() + and self.triple.bin_type == "detached" + and self.triple.child2.bin_type == "detached" + ): + # find beginning of RLOF carefully + time_step = time_step_factor_find_RLOF * self.previous_dt if REPORT_DT: - print('find rlof', time_step_factor_find_RLOF,self.previous_dt) + print("find rlof", time_step_factor_find_RLOF, self.previous_dt) - #resetting is_donor + # resetting is_donor self.check_RLOF() else: - #during stable mass transfer - time_step = min(time_step_wind, min( min(time_step_stellar_code), time_step_max)) + # during stable mass transfer + time_step = min( + time_step_wind, min(min(time_step_stellar_code), time_step_max) + ) time_step = min(time_step, self.determine_time_step_stable_mt()) if REPORT_DT or REPORT_DEBUG: - print('donor time:', self.determine_time_step_stable_mt()) + print("donor time:", self.determine_time_step_stable_mt()) if REPORT_DT or REPORT_DEBUG: - print('min increase', time_step, maximum_time_step_factor*self.previous_dt) - time_step = min(time_step, maximum_time_step_factor*self.previous_dt) - - - if self.triple.child2.bin_type == 'detached' and self.triple.child2.previous_bin_type == 'stable_mass_transfer': - corotation_spin = corotating_spin_angular_frequency_binary(self.triple.child2.semimajor_axis, self.triple.child2.child1.mass, self.triple.child2.child2.mass) + print( + "min increase", + time_step, + maximum_time_step_factor * self.previous_dt, + ) + time_step = min(time_step, maximum_time_step_factor * self.previous_dt) + + if ( + self.triple.child2.bin_type == "detached" + and self.triple.child2.previous_bin_type == "stable_mass_transfer" + ): + corotation_spin = corotating_spin_angular_frequency_binary( + self.triple.child2.semimajor_axis, + self.triple.child2.child1.mass, + self.triple.child2.child2.mass, + ) self.triple.child2.child1.spin_angular_frequency = corotation_spin self.triple.child2.child2.spin_angular_frequency = corotation_spin - -# if REPORT_DT or REPORT_DEBUG: -# print('prev timestep', time_step, previous_time_step) - previous_time_step = self.triple.time - self.previous_time - time_step = min(time_step, maximum_time_step_factor_after_stable_mt*previous_time_step) - + # if REPORT_DT or REPORT_DEBUG: + # print('prev timestep', time_step, previous_time_step) + previous_time_step = self.triple.time - self.previous_time + time_step = min( + time_step, maximum_time_step_factor_after_stable_mt * previous_time_step + ) if self.triple.time == quantities.zero: - #initialization (e.g. time_derivative_of_radius) - P_out = self.orbital_period(self.triple) #period outer binary + # initialization (e.g. time_derivative_of_radius) + P_out = self.orbital_period(self.triple) # period outer binary # do not take 0.1*P_in -> resonance -> large error - time_step = min(min(P_out, time_step), 1.|units.yr) + time_step = min(min(P_out, time_step), 1.0 | units.yr) - - time_step = max(time_step, minimum_time_step) + time_step = max(time_step, minimum_time_step) if self.triple.time >= self.tinit: - time_step = min(time_step, maximum_time_step) - - - - - -# else: - #during run-up towards mass transfer -# close_to_RLOF_bool, ratio_rad_rlof, time_step_close_to_mt = self.close_to_RLOF() -# if close_to_RLOF_bool: -# if ratio_rad_rlof >= 1.0: -# print('ratio_rad_rlof >1?') -# exit(0) -# else: -# print('close to rlof', time_step_close_to_mt, time_step, ratio_rad_rlof) -# exit(0) -# time_step = min(time_step, time_step_close_to_mt) - - - # in case secular code finds RLOF - if self.fixed_timestep > 0.|units.yr: + time_step = min(time_step, maximum_time_step) + + # else: + # during run-up towards mass transfer + # close_to_RLOF_bool, ratio_rad_rlof, time_step_close_to_mt = self.close_to_RLOF() + # if close_to_RLOF_bool: + # if ratio_rad_rlof >= 1.0: + # print('ratio_rad_rlof >1?') + # exit(0) + # else: + # print('close to rlof', time_step_close_to_mt, time_step, ratio_rad_rlof) + # exit(0) + # time_step = min(time_step, time_step_close_to_mt) + + # in case secular code finds RLOF + if self.fixed_timestep > 0.0 | units.yr: if REPORT_DT or REPORT_DEBUG: - print('time:', self.fixed_timestep) - print('donor time:', self.determine_time_step_stable_mt()) + print("time:", self.fixed_timestep) + print("donor time:", self.determine_time_step_stable_mt()) - t_donor = self.determine_time_step_stable_mt()*time_step_factor_stable_mt # extra small for safety - t_donor_lim = max(minimum_time_step, min(time_step, t_donor))# + t_donor = ( + self.determine_time_step_stable_mt() * time_step_factor_stable_mt + ) # extra small for safety + t_donor_lim = max(minimum_time_step, min(time_step, t_donor)) # # although fixed_timestep < time_step, fixed_timestep can be > time_step_stable_mt - if t_donor == np.inf|units.Myr: - #bh or ns donors + if t_donor == np.inf | units.Myr: + # bh or ns donors time_step = self.fixed_timestep elif self.fixed_timestep < t_donor_lim: time_step = t_donor_lim self.secular_code.parameters.check_for_inner_RLOF = False else: time_step = self.fixed_timestep - - self.fixed_timestep = -1|units.Myr - return time_step # as previous timestep was effectively zero -> min increase is zero + + self.fixed_timestep = -1 | units.Myr + return time_step # as previous timestep was effectively zero -> min increase is zero return time_step - #------- - #------- - #SN functions - #based on SeBa (Portegies Zwart et al. 1996, Toonen et al. 2012) - + # ------- + + # ------- + # SN functions + # based on SeBa (Portegies Zwart et al. 1996, Toonen et al. 2012) + def anomaly_converter(self, e_a, ecc, m_a): - # mean_anomaly = eccentric_anomaly - ecc*sin(eccentric_anomaly) + # mean_anomaly = eccentric_anomaly - ecc*sin(eccentric_anomaly) return e_a - ecc * np.sin(e_a) - m_a - #Paczynski 1990, 348, 485 + # Paczynski 1990, 348, 485 def kick_velocity_paczynski(self): - return self.random_paczynski_velocity(270|units.km/units.s) + return self.random_paczynski_velocity(270 | units.km / units.s) def kick_velocity_SeBa_std(self): - return self.random_paczynski_velocity(600|units.km/units.s) + return self.random_paczynski_velocity(600 | units.km / units.s) - #Paczynski 1990, 348, 485 - #taken from SeBa (Portegies Zwart et al. 1996, Toonen et al. 2012) + # Paczynski 1990, 348, 485 + # taken from SeBa (Portegies Zwart et al. 1996, Toonen et al. 2012) def random_paczynski_velocity(self, v_disp): - #Velocity distribution used by Paczynski, B., 1990, ApJ 348, 485. - #with a dispersion of 270 km/s. - #Phinney uses the same distribution with a dispersion of 600 km/s. - #The distribution: - #P(u)du = \frac{4}{\pi} \cdot \frac{du}{(1+u^2)^2}, - #u=v/v_d, - #v_d is the dispersion velocity = 270 or 600 km/s respectively. - - max_distr = 4./np.pi + # Velocity distribution used by Paczynski, B., 1990, ApJ 348, 485. + # with a dispersion of 270 km/s. + # Phinney uses the same distribution with a dispersion of 600 km/s. + # The distribution: + # P(u)du = \frac{4}{\pi} \cdot \frac{du}{(1+u^2)^2}, + # u=v/v_d, + # v_d is the dispersion velocity = 270 or 600 km/s respectively. + + max_distr = 4.0 / np.pi v_max = 4 - prob = max_distr*np.random.uniform(0., 1.) - velocity = v_max*np.random.uniform(0., 1.) - dist_value = max_distr/(1+velocity**2.)**2. - - while(prob > dist_value): - prob = max_distr*np.random.uniform(0., 1.) - velocity = v_max*np.random.uniform(0., 1.) - dist_value = max_distr/(1+velocity**2.)**2. - + prob = max_distr * np.random.uniform(0.0, 1.0) + velocity = v_max * np.random.uniform(0.0, 1.0) + dist_value = max_distr / (1 + velocity**2.0) ** 2.0 + + while prob > dist_value: + prob = max_distr * np.random.uniform(0.0, 1.0) + velocity = v_max * np.random.uniform(0.0, 1.0) + dist_value = max_distr / (1 + velocity**2.0) ** 2.0 + vector = self.random_direction() - return velocity*v_disp*vector + return velocity * v_disp * vector - #Hansen & Phinney 1997, 291, 569 + # Hansen & Phinney 1997, 291, 569 # V_3d = 300, V_1d = 190 km/s def kick_velocity_hansen(self): vector = self.random_direction() - return vector*maxwell.rvs(loc=0, scale = 190)|units.km/units.s - - #Hobbs, Lorimer, Lyne & Kramer, 2005, 360, 974 + return vector * maxwell.rvs(loc=0, scale=190) | units.km / units.s + + # Hobbs, Lorimer, Lyne & Kramer, 2005, 360, 974 # V_3d = 400, V_1d = 265 km/s def kick_velocity_hobbs(self): vector = self.random_direction() - return vector*maxwell.rvs(loc=0, scale = 265)|units.km/units.s - - #Arzoumanian ea 2002, 568, 289 + return vector * maxwell.rvs(loc=0, scale=265) | units.km / units.s + + # Arzoumanian ea 2002, 568, 289 def kick_velocity_arzoumanian(self): vector = self.random_direction() - if np.random.uniform(0,1) < 0.4: - return vector*maxwell.rvs(loc=0, scale = 90)|units.km/units.s + if np.random.uniform(0, 1) < 0.4: + return vector * maxwell.rvs(loc=0, scale=90) | units.km / units.s else: - return vector*maxwell.rvs(loc=0, scale = 500)|units.km/units.s - + return vector * maxwell.rvs(loc=0, scale=500) | units.km / units.s - # Verbunt, Igoshev & Cator, 2017, 608, 57 - combination of two maxwellians + # Verbunt, Igoshev & Cator, 2017, 608, 57 - combination of two maxwellians def kick_velocity_verbunt(self): vector = self.random_direction() - if np.random.uniform(0,1) < 0.42: - return vector*maxwell.rvs(loc=0, scale = 75)|units.km/units.s + if np.random.uniform(0, 1) < 0.42: + return vector * maxwell.rvs(loc=0, scale=75) | units.km / units.s else: - return vector*maxwell.rvs(loc=0, scale = 316)|units.km/units.s + return vector * maxwell.rvs(loc=0, scale=316) | units.km / units.s - - def random_direction(self): theta_kick = np.arccos(np.random.uniform(-1, 1)) - phi_kick = np.random.uniform(0, 2*np.pi) - x_kick = np.sin(theta_kick)*np.cos(phi_kick) - y_kick = np.sin(theta_kick)*np.sin(phi_kick) + phi_kick = np.random.uniform(0, 2 * np.pi) + x_kick = np.sin(theta_kick) * np.cos(phi_kick) + y_kick = np.sin(theta_kick) * np.sin(phi_kick) z_kick = np.cos(theta_kick) return np.array([x_kick, y_kick, z_kick]) - def get_SN_kick(self, star): - v_kick = [0.,0.,0.]|units.kms - if star.stellar_type != star.previous_stellar_type and star.stellar_type in stellar_types_SN_remnants: - if self.SN_kick_distr == 0: - v_kick = [0.,0.,0.]|units.kms - elif self.SN_kick_distr in [1]: # Hobbs, Lorimer, Lyne & Kramer, 2005, 360, 974 + v_kick = [0.0, 0.0, 0.0] | units.kms + if ( + star.stellar_type != star.previous_stellar_type + and star.stellar_type in stellar_types_SN_remnants + ): + if self.SN_kick_distr == 0: + v_kick = [0.0, 0.0, 0.0] | units.kms + elif self.SN_kick_distr in [ + 1 + ]: # Hobbs, Lorimer, Lyne & Kramer, 2005, 360, 974 v_kick = self.kick_velocity_hobbs() - elif self.SN_kick_distr in [2]: #Arzoumanian ea 2002, 568, 289 + elif self.SN_kick_distr in [2]: # Arzoumanian ea 2002, 568, 289 v_kick = self.kick_velocity_arzoumanian() - elif self.SN_kick_distr in [3]: #Hansen & Phinney 1997, 291, 569 + elif self.SN_kick_distr in [3]: # Hansen & Phinney 1997, 291, 569 v_kick = self.kick_velocity_hansen() - elif self.SN_kick_distr in [4]: # Paczynski 1990, 348, 485 + elif self.SN_kick_distr in [4]: # Paczynski 1990, 348, 485 v_kick = self.kick_velocity_paczynski() - elif self.SN_kick_distr in [5]: # Verbunt, Igoshev & Cator, 2017, 608, 57 + elif self.SN_kick_distr in [5]: # Verbunt, Igoshev & Cator, 2017, 608, 57 v_kick = self.kick_velocity_verbunt() else: print("SN kick distribution not specified, assuming no kick") - v_kick = [0.,0.,0.]|units.kms - - - print(self.impulse_kick_for_black_holes, self.fallback_kick_for_black_holes, v_kick) - #reduce kick of BH by conservation of momentum - if self.impulse_kick_for_black_holes and star.stellar_type == 14|units.stellar_type: - v_kick *= (kanonical_neutron_star_mass / star.mass) -# print(star.mass, kanonical_neutron_star_mass) - if self.fallback_kick_for_black_holes and star.stellar_type == 14|units.stellar_type: -# self.channel_from_stellar.copy_attributes(["fallback"]) -# v_kick *= (1-star.fallback) - - star_in_stellar_code = star.as_set().get_intersecting_subset_in(self.stellar_code.particles)[0] - fallback = star_in_stellar_code.get_fallback() - v_kick *= (1-fallback) -# print(fallback) + v_kick = [0.0, 0.0, 0.0] | units.kms + + print( + self.impulse_kick_for_black_holes, + self.fallback_kick_for_black_holes, + v_kick, + ) + # reduce kick of BH by conservation of momentum + if ( + self.impulse_kick_for_black_holes + and star.stellar_type == 14 | units.stellar_type + ): + v_kick *= kanonical_neutron_star_mass / star.mass + # print(star.mass, kanonical_neutron_star_mass) + if ( + self.fallback_kick_for_black_holes + and star.stellar_type == 14 | units.stellar_type + ): + # self.channel_from_stellar.copy_attributes(["fallback"]) + # v_kick *= (1-star.fallback) + + star_in_stellar_code = star.as_set().get_intersecting_subset_in( + self.stellar_code.particles + )[0] + fallback = star_in_stellar_code.get_fallback() + v_kick *= 1 - fallback + # print(fallback) return v_kick - def save_mean_anomalies_at_SN(self, inner_mean_anomaly, outer_mean_anomaly, stellar_system = None): + def save_mean_anomalies_at_SN( + self, inner_mean_anomaly, outer_mean_anomaly, stellar_system=None + ): if stellar_system == None: stellar_system = self.triple if stellar_system.is_star: - if stellar_system.stellar_type != stellar_system.previous_stellar_type and stellar_system.stellar_type in stellar_types_SN_remnants: + if ( + stellar_system.stellar_type != stellar_system.previous_stellar_type + and stellar_system.stellar_type in stellar_types_SN_remnants + ): stellar_system.inner_mean_anomaly = inner_mean_anomaly - stellar_system.outer_mean_anomaly = outer_mean_anomaly + stellar_system.outer_mean_anomaly = outer_mean_anomaly else: - self.save_mean_anomalies_at_SN(inner_mean_anomaly, outer_mean_anomaly,stellar_system.child1) - self.save_mean_anomalies_at_SN(inner_mean_anomaly, outer_mean_anomaly,stellar_system.child2) - - def adjust_spin_after_supernova(self, stellar_system = None): + self.save_mean_anomalies_at_SN( + inner_mean_anomaly, outer_mean_anomaly, stellar_system.child1 + ) + self.save_mean_anomalies_at_SN( + inner_mean_anomaly, outer_mean_anomaly, stellar_system.child2 + ) + + def adjust_spin_after_supernova(self, stellar_system=None): if stellar_system == None: stellar_system = self.triple if stellar_system.is_star: - if stellar_system.stellar_type != stellar_system.previous_stellar_type and stellar_system.stellar_type in stellar_types_SN_remnants: - stellar_system.spin_angular_frequency *= stellar_system.previous_moment_of_inertia_of_star/stellar_system.moment_of_inertia_of_star + if ( + stellar_system.stellar_type != stellar_system.previous_stellar_type + and stellar_system.stellar_type in stellar_types_SN_remnants + ): + stellar_system.spin_angular_frequency *= ( + stellar_system.previous_moment_of_inertia_of_star + / stellar_system.moment_of_inertia_of_star + ) else: - self.adjust_spin_after_supernova(stellar_system.child1) + self.adjust_spin_after_supernova(stellar_system.child1) self.adjust_spin_after_supernova(stellar_system.child2) - - + def adjust_system_after_supernova_kick(self): if self.triple.is_star: - #only velocity kick needs to be taken into account here - #not followed currently + # only velocity kick needs to be taken into account here + # not followed currently return False elif not self.is_triple(): - sys.exit('SN only implemented in triple') - - #SN in triple + sys.exit("SN only implemented in triple") + + # SN in triple if self.triple.child1.is_star: star = self.triple.child1 bin = self.triple.child2 @@ -1678,108 +2115,158 @@ def adjust_system_after_supernova_kick(self): star = self.triple.child2 bin = self.triple.child1 - #needs BH mass + # needs BH mass vel_kick1 = self.get_SN_kick(bin.child1) vel_kick2 = self.get_SN_kick(bin.child2) vel_kick3 = self.get_SN_kick(star) - - #convention in secular code: dm > 0 + + # convention in secular code: dm > 0 dm1 = bin.child1.previous_mass - bin.child1.mass dm2 = bin.child2.previous_mass - bin.child2.mass dm3 = star.previous_mass - star.mass - - #secular code requires the mass of the stars to be the mass prior to the SN - bin.child1.mass = bin.child1.previous_mass + + # secular code requires the mass of the stars to be the mass prior to the SN + bin.child1.mass = bin.child1.previous_mass bin.child2.mass = bin.child2.previous_mass - star.mass = star.previous_mass - - #reset parameters to before SN - #to get correct values for the snapshot + star.mass = star.previous_mass + + # reset parameters to before SN + # to get correct values for the snapshot bin_child1_proper_stellar_type = bin.child1.stellar_type bin_child2_proper_stellar_type = bin.child2.stellar_type star_proper_stellar_type = star.stellar_type bin.child1.stellar_type = bin.child1.previous_stellar_type bin.child2.stellar_type = bin.child2.previous_stellar_type - star.stellar_type = star.previous_stellar_type + star.stellar_type = star.previous_stellar_type bin_child1_proper_radius = bin.child1.radius bin_child2_proper_radius = bin.child2.radius star_proper_radius = star.radius bin.child1.radius = bin.child1.previous_radius bin.child2.radius = bin.child2.previous_radius - star.radius = star.previous_radius - - self.save_snapshot() - - #reset orbital parameters tertiary in case of binary or ignore_tertiary + star.radius = star.previous_radius + + self.save_snapshot() + + # reset orbital parameters tertiary in case of binary or ignore_tertiary a_out_init = self.triple.semimajor_axis - e_out_init = self.triple.eccentricity + e_out_init = self.triple.eccentricity # determine stellar anomaly # mean anomaly increases uniformly from 0 to 2\pi radians during each orbit inner_ecc = bin.eccentricity - inner_mean_anomaly = np.random.uniform(0., 2.*np.pi) - inner_eccentric_anomaly = optimize.brentq(self.anomaly_converter, 0., 2.*np.pi, args=(inner_ecc, inner_mean_anomaly)) - inner_true_anomaly = 2.* np.arctan2(np.sqrt(1-inner_ecc) * np.cos(inner_eccentric_anomaly/2.), np.sqrt(1+inner_ecc) * np.sin(inner_eccentric_anomaly/2.)) + inner_mean_anomaly = np.random.uniform(0.0, 2.0 * np.pi) + inner_eccentric_anomaly = optimize.brentq( + self.anomaly_converter, + 0.0, + 2.0 * np.pi, + args=(inner_ecc, inner_mean_anomaly), + ) + inner_true_anomaly = 2.0 * np.arctan2( + np.sqrt(1 - inner_ecc) * np.cos(inner_eccentric_anomaly / 2.0), + np.sqrt(1 + inner_ecc) * np.sin(inner_eccentric_anomaly / 2.0), + ) # min teken verschil met cos_true_anomaly = (np.cos(eccentric_anomaly)-ecc) / (1-ecc*np.cos(eccentric_anomaly)) outer_ecc = self.triple.eccentricity - outer_mean_anomaly = np.random.uniform(0., 2.*np.pi) - outer_eccentric_anomaly = optimize.brentq(self.anomaly_converter, 0., 2.*np.pi, args=(outer_ecc, outer_mean_anomaly)) - outer_true_anomaly = 2.* np.arctan2(np.sqrt(1-outer_ecc) * np.cos(outer_eccentric_anomaly/2.), np.sqrt(1+outer_ecc) * np.sin(outer_eccentric_anomaly/2.)) + outer_mean_anomaly = np.random.uniform(0.0, 2.0 * np.pi) + outer_eccentric_anomaly = optimize.brentq( + self.anomaly_converter, + 0.0, + 2.0 * np.pi, + args=(outer_ecc, outer_mean_anomaly), + ) + outer_true_anomaly = 2.0 * np.arctan2( + np.sqrt(1 - outer_ecc) * np.cos(outer_eccentric_anomaly / 2.0), + np.sqrt(1 + outer_ecc) * np.sin(outer_eccentric_anomaly / 2.0), + ) if REPORT_SN_EVOLUTION: - print('before SN:', self.triple.number) - print('\n\ntime:', self.triple.time, self.previous_time, self.triple.time-self.previous_time) - print('eccentricity:', inner_ecc, outer_ecc) - print('semi-major axis:', bin.semimajor_axis, self.triple.semimajor_axis) - print('inner anomaly:', inner_mean_anomaly, inner_eccentric_anomaly, inner_true_anomaly) - print('outer anomaly:', outer_mean_anomaly, outer_eccentric_anomaly, outer_true_anomaly) - print('vel_kicks:', vel_kick1, vel_kick2, vel_kick3 ) - print('dm:', dm1, dm2, dm3) + print("before SN:", self.triple.number) + print( + "\n\ntime:", + self.triple.time, + self.previous_time, + self.triple.time - self.previous_time, + ) + print("eccentricity:", inner_ecc, outer_ecc) + print("semi-major axis:", bin.semimajor_axis, self.triple.semimajor_axis) + print( + "inner anomaly:", + inner_mean_anomaly, + inner_eccentric_anomaly, + inner_true_anomaly, + ) + print( + "outer anomaly:", + outer_mean_anomaly, + outer_eccentric_anomaly, + outer_true_anomaly, + ) + print("vel_kicks:", vel_kick1, vel_kick2, vel_kick3) + print("dm:", dm1, dm2, dm3) self.channel_to_secular.copy() - V1, V2, V3 = self.secular_code.compute_effect_of_SN_on_triple(vel_kick1, vel_kick2, vel_kick3, dm1, dm2, dm3, inner_true_anomaly, outer_true_anomaly) - self.channel_from_secular.copy() - - #as secular code required the mass of the stars to be the mass prior to the SN - #reset mass to after SN + V1, V2, V3 = self.secular_code.compute_effect_of_SN_on_triple( + vel_kick1, + vel_kick2, + vel_kick3, + dm1, + dm2, + dm3, + inner_true_anomaly, + outer_true_anomaly, + ) + self.channel_from_secular.copy() + + # as secular code required the mass of the stars to be the mass prior to the SN + # reset mass to after SN bin.child1.mass = bin.child1.previous_mass - dm1 bin.child2.mass = bin.child2.previous_mass - dm2 star.mass = star.previous_mass - dm3 - #reset the stellar types to after SN + # reset the stellar types to after SN bin.child1.stellar_type = bin_child1_proper_stellar_type bin.child2.stellar_type = bin_child2_proper_stellar_type - star.stellar_type = star_proper_stellar_type + star.stellar_type = star_proper_stellar_type bin.child1.radius = bin_child1_proper_radius bin.child2.radius = bin_child2_proper_radius - star.radius = star_proper_radius + star.radius = star_proper_radius if self.secular_code.parameters.ignore_tertiary: self.triple.semimajor_axis = a_out_init self.triple.eccentricity = e_out_init if REPORT_SN_EVOLUTION: - print('after SN') - print('eccentricity:', bin.eccentricity, self.triple.eccentricity) - print('semi-major axis:', bin.semimajor_axis, self.triple.semimajor_axis) - - if bin.eccentricity >= 1.0 or bin.eccentricity < 0.0 or bin.semimajor_axis <=0.0|units.RSun or np.isnan(bin.semimajor_axis.value_in(units.RSun)): + print("after SN") + print("eccentricity:", bin.eccentricity, self.triple.eccentricity) + print("semi-major axis:", bin.semimajor_axis, self.triple.semimajor_axis) + + if ( + bin.eccentricity >= 1.0 + or bin.eccentricity < 0.0 + or bin.semimajor_axis <= 0.0 | units.RSun + or np.isnan(bin.semimajor_axis.value_in(units.RSun)) + ): if REPORT_SN_EVOLUTION: - print("Inner orbit dissociated by SN at time = ",self.triple.time) - bin.bin_type = bin_type['disintegrated'] + print("Inner orbit dissociated by SN at time = ", self.triple.time) + bin.bin_type = bin_type["disintegrated"] return False - elif self.triple.eccentricity >= 1.0 or self.triple.eccentricity < 0.0 or self.triple.semimajor_axis <=0.0|units.RSun or np.isnan(self.triple.semimajor_axis.value_in(units.RSun)): + elif ( + self.triple.eccentricity >= 1.0 + or self.triple.eccentricity < 0.0 + or self.triple.semimajor_axis <= 0.0 | units.RSun + or np.isnan(self.triple.semimajor_axis.value_in(units.RSun)) + ): if REPORT_SN_EVOLUTION: - print("Outer orbit dissociated by SN at time = ",self.triple.time) - self.triple.bin_type = bin_type['disintegrated'] + print("Outer orbit dissociated by SN at time = ", self.triple.time) + self.triple.bin_type = bin_type["disintegrated"] - # When the outer orbit has disintegrated, change its orbital parameters such - # that it has no influence on the inner orbit for the remainder of the simulation - self.triple.semimajor_axis = 1e100|units.RSun + # When the outer orbit has disintegrated, change its orbital parameters such + # that it has no influence on the inner orbit for the remainder of the simulation + self.triple.semimajor_axis = 1e100 | units.RSun self.triple.eccentricity = 0 self.secular_code.parameters.ignore_tertiary = True @@ -1789,352 +2276,427 @@ def adjust_system_after_supernova_kick(self): # The evolution could be followed further by uncommenting the next line # For now we stop the simulation if we do not have a bound triple system anymore - return False + return False + + self.adjust_spin_after_supernova() - self.adjust_spin_after_supernova() + # bh spin frequency has no meaning. make sure it doesn't affect the evolution + bin.child1.previous_moment_of_inertia_of_star = ( + bin.child1.moment_of_inertia_of_star + ) + bin.child2.previous_moment_of_inertia_of_star = ( + bin.child2.moment_of_inertia_of_star + ) + star.previous_moment_of_inertia_of_star = star.moment_of_inertia_of_star - #bh spin frequency has no meaning. make sure it doesn't affect the evolution - bin.child1.previous_moment_of_inertia_of_star = bin.child1.moment_of_inertia_of_star - bin.child2.previous_moment_of_inertia_of_star = bin.child2.moment_of_inertia_of_star - star.previous_moment_of_inertia_of_star = star.moment_of_inertia_of_star - if bin.child1.stellar_type in stellar_types_SN_remnants: - self.secular_code.parameters.include_spin_radius_mass_coupling_terms_star1 = False + self.secular_code.parameters.include_spin_radius_mass_coupling_terms_star1 = ( + False + ) if bin.child2.stellar_type in stellar_types_SN_remnants: - self.secular_code.parameters.include_spin_radius_mass_coupling_terms_star2 = False + self.secular_code.parameters.include_spin_radius_mass_coupling_terms_star2 = ( + False + ) if star.stellar_type in stellar_types_SN_remnants: - self.secular_code.parameters.include_spin_radius_mass_coupling_terms_star3 = False + self.secular_code.parameters.include_spin_radius_mass_coupling_terms_star3 = ( + False + ) if self.stop_at_SN: if REPORT_SN_EVOLUTION: - print("Supernova at time = ",self.triple.time ) - print(self.triple.child2.child1.mass, self.triple.child2.child1.stellar_type) - print(self.triple.child2.child2.mass, self.triple.child2.child2.stellar_type) + print("Supernova at time = ", self.triple.time) + print( + self.triple.child2.child1.mass, + self.triple.child2.child1.stellar_type, + ) + print( + self.triple.child2.child2.mass, + self.triple.child2.child2.stellar_type, + ) print(self.triple.child1.mass, self.triple.child1.stellar_type) - return False - - #check for rlof -> if rlof than stop? -# self.check_RLOF() + return False + + # check for rlof -> if rlof than stop? + # self.check_RLOF() return True - - #------- - - #------- - #evolution - - # uses instantaneous eccentricity (from global timestep) to calculate an orbit averaged stellar flux, - # that can evaporise part of the planetary envelope. + + # ------- + + # ------- + # evolution + + # uses instantaneous eccentricity (from global timestep) to calculate an orbit averaged stellar flux, + # that can evaporise part of the planetary envelope. # would be best to do in secular code instead, such that eccentricity variations due to KL are taken into account properly - def planetary_mass_evaporation(self, dt, stellar_system = None): + def planetary_mass_evaporation(self, dt, stellar_system=None): if stellar_system == None: - stellar_system = self.triple - + stellar_system = self.triple + if stellar_system.is_star: return elif self.is_binary(stellar_system): - if stellar_system.child1.stellar_type in stellar_types_planetary_objects and stellar_system.child2.stellar_type not in stellar_types_planetary_objects: + if ( + stellar_system.child1.stellar_type in stellar_types_planetary_objects + and stellar_system.child2.stellar_type + not in stellar_types_planetary_objects + ): donor = stellar_system.child1 - dm = mass_lost_due_to_evaporation_in_binary(stellar_system, dt, donor, stellar_system.child2, self) + dm = mass_lost_due_to_evaporation_in_binary( + stellar_system, dt, donor, stellar_system.child2, self + ) donor.previous_mass = donor.mass - donor_in_stellar_code = donor.as_set().get_intersecting_subset_in(self.stellar_code.particles)[0] - donor_in_stellar_code.change_mass(-1*dm, 0.|units.yr) + donor_in_stellar_code = donor.as_set().get_intersecting_subset_in( + self.stellar_code.particles + )[0] + donor_in_stellar_code.change_mass(-1 * dm, 0.0 | units.yr) print("mass lost child1:", dm) - elif stellar_system.child2.stellar_type in stellar_types_planetary_objects and stellar_system.child1.stellar_type not in stellar_types_planetary_objects: + elif ( + stellar_system.child2.stellar_type in stellar_types_planetary_objects + and stellar_system.child1.stellar_type + not in stellar_types_planetary_objects + ): donor = stellar_system.child2 - dm = mass_lost_due_to_evaporation_in_binary(stellar_system, dt, donor, stellar_system.child1, self) + dm = mass_lost_due_to_evaporation_in_binary( + stellar_system, dt, donor, stellar_system.child1, self + ) donor.previous_mass = donor.mass - donor_in_stellar_code = donor.as_set().get_intersecting_subset_in(self.stellar_code.particles)[0] - donor_in_stellar_code.change_mass(-1*dm, 0.|units.yr) + donor_in_stellar_code = donor.as_set().get_intersecting_subset_in( + self.stellar_code.particles + )[0] + donor_in_stellar_code.change_mass(-1 * dm, 0.0 | units.yr) print("mass lost child2:", dm) elif self.is_triple(stellar_system): - if stellar_system.child1.is_star: #child1 is the tertiary + if stellar_system.child1.is_star: # child1 is the tertiary # effect on tertiary - if stellar_system.child1.stellar_type in stellar_types_planetary_objects: #evaporation if tertiary is a planet + if ( + stellar_system.child1.stellar_type + in stellar_types_planetary_objects + ): # evaporation if tertiary is a planet donor = stellar_system.child1 - dm = mass_lost_due_to_evaporation_tertiary(stellar_system, dt, donor, stellar_system.child2, self) + dm = mass_lost_due_to_evaporation_tertiary( + stellar_system, dt, donor, stellar_system.child2, self + ) donor.previous_mass = donor.mass - donor_in_stellar_code = donor.as_set().get_intersecting_subset_in(self.stellar_code.particles)[0] - donor_in_stellar_code.change_mass(-1*dm, 0.|units.yr) + donor_in_stellar_code = donor.as_set().get_intersecting_subset_in( + self.stellar_code.particles + )[0] + donor_in_stellar_code.change_mass(-1 * dm, 0.0 | units.yr) print("mass lost child1:", dm) - # check the inner binary: for now we only take into account evaporation due the closest stellar companion - self.planetary_mass_evaporation(dt, stellar_system.child2) - elif self.child2.is_star: #child2 is the tertiary + # check the inner binary: for now we only take into account evaporation due the closest stellar companion + self.planetary_mass_evaporation(dt, stellar_system.child2) + elif self.child2.is_star: # child2 is the tertiary # effect on tertiary - if self.child2.stellar_type in stellar_types_planetary_objects: #evaporation if tertiary is a planet + if ( + self.child2.stellar_type in stellar_types_planetary_objects + ): # evaporation if tertiary is a planet donor = stellar_system.child2 - dm = mass_lost_due_to_evaporation_tertiary(stellar_system, dt, donor, stellar_system.child1, self) + dm = mass_lost_due_to_evaporation_tertiary( + stellar_system, dt, donor, stellar_system.child1, self + ) donor.previous_mass = donor.mass - donor_in_stellar_code = donor.as_set().get_intersecting_subset_in(self.stellar_code.particles)[0] - donor_in_stellar_code.change_mass(-1*dm, 0.|units.yr) + donor_in_stellar_code = donor.as_set().get_intersecting_subset_in( + self.stellar_code.particles + )[0] + donor_in_stellar_code.change_mass(-1 * dm, 0.0 | units.yr) print("mass lost child2:", dm) - # check the inner binary: for now we only take into account evaporation due the closest stellar companion - self.planetary_mass_evaporation(dt, stellar_system.child1) - else: - sys.exit('planetary_mass_evaporation: structure stellar system unknown') - - else: - sys.exit('planetary_mass_evaporation: structure stellar system unknown') - - - - def resolve_stellar_interaction(self, stellar_system = None): - # the most inner binary is calculated first, and then move outwards + # check the inner binary: for now we only take into account evaporation due the closest stellar companion + self.planetary_mass_evaporation(dt, stellar_system.child1) + else: + sys.exit("planetary_mass_evaporation: structure stellar system unknown") + + else: + sys.exit("planetary_mass_evaporation: structure stellar system unknown") + + def resolve_stellar_interaction(self, stellar_system=None): + # the most inner binary is calculated first, and then move outwards if stellar_system == None: stellar_system = self.triple if stellar_system.is_star: if REPORT_TRIPLE_EVOLUTION: - print('single stellar evolution') - sys.exit('for now no single stellar evolution - exiting program') + print("single stellar evolution") + sys.exit("for now no single stellar evolution - exiting program") return elif self.is_binary(stellar_system): if REPORT_TRIPLE_EVOLUTION: - print('\n perform stellar interaction: binary') -# stellar_system = perform_stellar_interaction(stellar_system, self) + print("\n perform stellar interaction: binary") + # stellar_system = perform_stellar_interaction(stellar_system, self) stopping_condition = perform_stellar_interaction(stellar_system, self) - return stopping_condition #stellar interaction + return stopping_condition # stellar interaction else: if REPORT_TRIPLE_EVOLUTION: - print('\n perform stellar interaction') - - stopping_condition = perform_stellar_interaction(stellar_system, self) - if not stopping_condition: #stellar interaction - return False - - if stopping_condition>0: - #in case of outer mass transfer, skip inner evolution, is taken care of in outer mass transfer - if not stellar_system.child1.is_star: #child1 is a multiple - stopping_condition = self.resolve_stellar_interaction(stellar_system.child1) - if not stopping_condition: #stellar interaction - return False - elif not stellar_system.child2.is_star: #child2 is a multiple - stopping_condition = self.resolve_stellar_interaction(stellar_system.child2) - if not stopping_condition: #stellar interaction - return False + print("\n perform stellar interaction") + + stopping_condition = perform_stellar_interaction(stellar_system, self) + if not stopping_condition: # stellar interaction + return False + + if stopping_condition > 0: + # in case of outer mass transfer, skip inner evolution, is taken care of in outer mass transfer + if not stellar_system.child1.is_star: # child1 is a multiple + stopping_condition = self.resolve_stellar_interaction( + stellar_system.child1 + ) + if not stopping_condition: # stellar interaction + return False + elif not stellar_system.child2.is_star: # child2 is a multiple + stopping_condition = self.resolve_stellar_interaction( + stellar_system.child2 + ) + if not stopping_condition: # stellar interaction + return False else: - sys.exit('resolve_stellar_interaction: structure stellar system unknown, both children are binaries') + sys.exit( + "resolve_stellar_interaction: structure stellar system unknown, both children are binaries" + ) + + return True - return True - - - def determine_mass_transfer_timescale(self, stellar_system = None): + def determine_mass_transfer_timescale(self, stellar_system=None): if stellar_system == None: stellar_system = self.triple if stellar_system.is_star: if REPORT_TRIPLE_EVOLUTION: - print('single stellar evolution') + print("single stellar evolution") return elif self.is_binary(stellar_system): if REPORT_TRIPLE_EVOLUTION: - print('\n determine_mass_transfer_timescale: binary - double star') + print("\n determine_mass_transfer_timescale: binary - double star") mass_transfer_stability(stellar_system, self) if REPORT_TRIPLE_EVOLUTION: - print('mt rate double star:', stellar_system.mass_transfer_rate) + print("mt rate double star:", stellar_system.mass_transfer_rate) else: - self.determine_mass_transfer_timescale(stellar_system.child1) - self.determine_mass_transfer_timescale(stellar_system.child2) + self.determine_mass_transfer_timescale(stellar_system.child1) + self.determine_mass_transfer_timescale(stellar_system.child2) if REPORT_TRIPLE_EVOLUTION: - print('\n determine_mass_transfer_timescale: binary') - mass_transfer_stability(stellar_system, self) + print("\n determine_mass_transfer_timescale: binary") + mass_transfer_stability(stellar_system, self) if REPORT_TRIPLE_EVOLUTION: - print('mt rate binary:', stellar_system.mass_transfer_rate) - - - + print("mt rate binary:", stellar_system.mass_transfer_rate) def solve_for_partial_time_step_stable_mass_transfer(self): full_dt = self.triple.time - self.previous_time - self.secular_code.evolve_model(self.previous_time + full_dt * self.triple.child2.part_dt_mt) + self.secular_code.evolve_model( + self.previous_time + full_dt * self.triple.child2.part_dt_mt + ) self.channel_from_secular.copy() - self.check_RLOF() + self.check_RLOF() if self.has_donor(): - print('After partial timestep the system should be detached...') + print("After partial timestep the system should be detached...") print(self.has_donor()) - print(self.triple.child1.mass, self.triple.child2.child1.mass, self.triple.child2.child2.mass) + print( + self.triple.child1.mass, + self.triple.child2.child1.mass, + self.triple.child2.child2.mass, + ) return False - self.secular_code.model_time = self.triple.time # not redundant! - self.triple.child2.part_dt_mt = 1. - return True - - - def safety_check_time_step(self, stellar_system = None): + self.secular_code.model_time = self.triple.time # not redundant! + self.triple.child2.part_dt_mt = 1.0 + return True + + def safety_check_time_step(self, stellar_system=None): if stellar_system == None: stellar_system = self.triple successfull_dr = True - + if stellar_system.is_star: - dm = (stellar_system.previous_mass - stellar_system.mass)/stellar_system.mass -# if REPORT_DEBUG: -# print('wind mass loss rate:', stellar_system.wind_mass_loss_rate, stellar_system.mass,stellar_system.core_mass,) -# print('relative wind mass losses:', dm) - - if (abs(dm) > error_dm) and not (stellar_system.stellar_type != stellar_system.previous_stellar_type ) and not (stellar_system.stellar_type in stellar_types_SN_remnants): - successfull_dr = False - print('should this statement be here? does this give problems during mt?') - - if self.secular_code.parameters.include_inner_tidal_terms or self.secular_code.parameters.include_outer_tidal_terms: - dr = (stellar_system.radius - stellar_system.previous_radius)/stellar_system.radius - -# if REPORT_DEBUG: -# print('change in radius over time:', stellar_system.time_derivative_of_radius,) -# print('relative change in radius:', dr) - - - if (abs(dr) > error_dr) and not (stellar_system.stellar_type != stellar_system.previous_stellar_type and stellar_system.stellar_type in stellar_types_dr) and not stellar_system.parent.bin_type == 'stable_mass_transfer': - #during stable mass transfer we reset the system to synchronization, - #so tides and spin change due to moment of inertia change are not important, - #therefore the radius change is not important - - successfull_dr = False + dm = ( + stellar_system.previous_mass - stellar_system.mass + ) / stellar_system.mass + # if REPORT_DEBUG: + # print('wind mass loss rate:', stellar_system.wind_mass_loss_rate, stellar_system.mass,stellar_system.core_mass,) + # print('relative wind mass losses:', dm) + + if ( + (abs(dm) > error_dm) + and not ( + stellar_system.stellar_type != stellar_system.previous_stellar_type + ) + and not (stellar_system.stellar_type in stellar_types_SN_remnants) + ): + successfull_dr = False + print( + "should this statement be here? does this give problems during mt?" + ) + + if ( + self.secular_code.parameters.include_inner_tidal_terms + or self.secular_code.parameters.include_outer_tidal_terms + ): + dr = ( + stellar_system.radius - stellar_system.previous_radius + ) / stellar_system.radius + + # if REPORT_DEBUG: + # print('change in radius over time:', stellar_system.time_derivative_of_radius,) + # print('relative change in radius:', dr) + + if ( + (abs(dr) > error_dr) + and not ( + stellar_system.stellar_type + != stellar_system.previous_stellar_type + and stellar_system.stellar_type in stellar_types_dr + ) + and not stellar_system.parent.bin_type == "stable_mass_transfer" + ): + # during stable mass transfer we reset the system to synchronization, + # so tides and spin change due to moment of inertia change are not important, + # therefore the radius change is not important + + successfull_dr = False return successfull_dr, 1, stellar_system else: - successfull_dr1, nr_dr1, star_dr1 = self.safety_check_time_step(stellar_system.child1) - successfull_dr2, nr_dr2, star_dr2 = self.safety_check_time_step(stellar_system.child2) - if successfull_dr1==False and successfull_dr2==False: + successfull_dr1, nr_dr1, star_dr1 = self.safety_check_time_step( + stellar_system.child1 + ) + successfull_dr2, nr_dr2, star_dr2 = self.safety_check_time_step( + stellar_system.child2 + ) + if successfull_dr1 == False and successfull_dr2 == False: if nr_dr1 > 1: return False, 3, np.array([star_dr1[0], star_dr1[1], star_dr2]) elif nr_dr2 > 1: return False, 3, np.array([star_dr1, star_dr2[0], star_dr2[1]]) else: return False, 2, np.array([star_dr1, star_dr2]) - elif successfull_dr1==False: + elif successfull_dr1 == False: return False, nr_dr1, star_dr1 - elif successfull_dr2==False: + elif successfull_dr2 == False: return False, nr_dr2, star_dr2 else: - return True, 0, 0 - - - def recall_memory_one_step_stellar(self, nr_unsuccessfull, star_unsuccessfull): + return True, 0, 0 + + def recall_memory_one_step_stellar(self, nr_unsuccessfull, star_unsuccessfull): if REPORT_DEBUG: - print('recall_memory_one_step_stellar') + print("recall_memory_one_step_stellar") self.update_time_derivative_of_radius() - dt = self.triple.time-self.previous_time - #crashes for M=1.4Msun: MS hook at stellar type change - #dt_new = max(minimum_time_step, min(self.determine_time_step(), 0.9*dt)) - dt_new = max(minimum_time_step, 0.5*dt) + dt = self.triple.time - self.previous_time + # crashes for M=1.4Msun: MS hook at stellar type change + # dt_new = max(minimum_time_step, min(self.determine_time_step(), 0.9*dt)) + dt_new = max(minimum_time_step, 0.5 * dt) self.stellar_code.particles.recall_memory_one_step() - self.triple.time += (dt_new - dt) - + self.triple.time += dt_new - dt + self.stellar_code.evolve_model(self.triple.time) - + self.copy_from_stellar() - self.update_stellar_parameters() - + self.update_stellar_parameters() + if nr_unsuccessfull > 1: for i_rec in range(nr_unsuccessfull): triple_number = self.triple.number if dt_new <= minimum_time_step: triple_number += 0.5 - dr = (star_unsuccessfull[i_rec].radius - star_unsuccessfull[i_rec].previous_radius)/star_unsuccessfull[i_rec].radius + dr = ( + star_unsuccessfull[i_rec].radius + - star_unsuccessfull[i_rec].previous_radius + ) / star_unsuccessfull[i_rec].radius else: - dr = (star_unsuccessfull.radius - star_unsuccessfull.previous_radius)/star_unsuccessfull.radius + dr = ( + star_unsuccessfull.radius - star_unsuccessfull.previous_radius + ) / star_unsuccessfull.radius triple_number = self.triple.number if dt_new <= minimum_time_step: triple_number += 0.5 if dt_new <= minimum_time_step: - return True, 0, 0 + return True, 0, 0 + + return self.safety_check_time_step() - return self.safety_check_time_step() - - #when the stellar code finds RLOF - def rewind_to_begin_of_rlof_stellar(self, dt): + # when the stellar code finds RLOF + def rewind_to_begin_of_rlof_stellar(self, dt): if REPORT_DEBUG: - print('rewind to begin of rlof stellar') + print("rewind to begin of rlof stellar") dt_new = dt dt_min = max(minimum_time_step, self.determine_time_step_stable_mt()) while self.has_donor() == True and dt_new > dt_min: dt_old = self.triple.time - self.previous_time - dt_new = max(minimum_time_step, 0.5*dt_old) + dt_new = max(minimum_time_step, 0.5 * dt_old) self.stellar_code.particles.recall_memory_one_step() - self.triple.time += (dt_new - dt_old) + self.triple.time += dt_new - dt_old if REPORT_TRIPLE_EVOLUTION or REPORT_DEBUG: - print('\n\ntime:', self.triple.time, self.has_donor()) + print("\n\ntime:", self.triple.time, self.has_donor()) self.stellar_code.evolve_model(self.triple.time) self.copy_from_stellar() - self.update_stellar_parameters() - self.check_RLOF() - + self.update_stellar_parameters() + self.check_RLOF() - #when the secular code finds RLOF - def rewind_to_begin_of_rlof_secular(self): + # when the secular code finds RLOF + def rewind_to_begin_of_rlof_secular(self): if REPORT_DEBUG: - print('rewind to begin of rlof secular') + print("rewind to begin of rlof secular") - #find beginning of RLOF + # find beginning of RLOF self.fixed_timestep = self.secular_code.model_time - self.previous_time self.triple.time = self.previous_time - self.secular_code.model_time = self.previous_time - - if self.fixed_timestep < 0.|units.yr: - print(self.triple.time, self.secular_code.model_time, self.fixed_timestep) - sys.exit('fixed_timestep < 0: should not be possible') - - #rewind system + self.secular_code.model_time = self.previous_time + + if self.fixed_timestep < 0.0 | units.yr: + print(self.triple.time, self.secular_code.model_time, self.fixed_timestep) + sys.exit("fixed_timestep < 0: should not be possible") + + # rewind system self.stellar_code.particles.recall_memory_one_step() - self.refresh_memory() - - - def check_stopping_conditions_stellar_interaction(self): + self.refresh_memory() + + def check_stopping_conditions_stellar_interaction(self): if self.stop_at_merger and self.has_merger(): if REPORT_TRIPLE_EVOLUTION: - print('Merger at time = ',self.triple.time ) - return False + print("Merger at time = ", self.triple.time) + return False if self.stop_at_disintegrated and self.has_disintegrated(): if REPORT_TRIPLE_EVOLUTION: - print('Disintegration of system at time = ',self.triple.time ) + print("Disintegration of system at time = ", self.triple.time) return False - return True - - -# def check_stopping_conditions_stellar(self): -# if self.stop_at_outer_mass_transfer and self.has_tertiary_donor(): -# if self.secular_code.model_time < self.triple.time: -# self.triple.time = self.secular_code.model_time -# -# if REPORT_TRIPLE_EVOLUTION: -# print('Mass transfer in outer binary of triple at time = ',self.triple.time) -# self.triple.bin_type = bin_type['rlof'] -# -# self.determine_mass_transfer_timescale() # to set the stability #obsolete? -# return False -# -# elif self.stop_at_mass_transfer and self.has_donor(): -# if self.secular_code.model_time < self.triple.time: -# self.triple.time = self.secular_code.model_time -# -# if REPORT_TRIPLE_EVOLUTION: -# print('Mass transfer at time = ',self.triple.time) -# if self.is_binary(self.triple.child2): -# self.triple.child2.bin_type = bin_type['rlof'] -# elif self.is_binary(self.triple.child1): -# self.triple.child1.bin_type = bin_type['rlof'] -# else: -# print('currently not implemented') -# exit(-1) -# -# self.determine_mass_transfer_timescale() # to set the stability #obsolete? -# return False -# -# return True - - - - def check_stopping_conditions_stellar(self, stellar_system = None): - #before check stopping conditions_stellar, always make sure the stability labels are up to date - #by running self.determine_mass_transfer_timescale() + return True + + # def check_stopping_conditions_stellar(self): + # if self.stop_at_outer_mass_transfer and self.has_tertiary_donor(): + # if self.secular_code.model_time < self.triple.time: + # self.triple.time = self.secular_code.model_time + # + # if REPORT_TRIPLE_EVOLUTION: + # print('Mass transfer in outer binary of triple at time = ',self.triple.time) + # self.triple.bin_type = bin_type['rlof'] + # + # self.determine_mass_transfer_timescale() # to set the stability #obsolete? + # return False + # + # elif self.stop_at_mass_transfer and self.has_donor(): + # if self.secular_code.model_time < self.triple.time: + # self.triple.time = self.secular_code.model_time + # + # if REPORT_TRIPLE_EVOLUTION: + # print('Mass transfer at time = ',self.triple.time) + # if self.is_binary(self.triple.child2): + # self.triple.child2.bin_type = bin_type['rlof'] + # elif self.is_binary(self.triple.child1): + # self.triple.child1.bin_type = bin_type['rlof'] + # else: + # print('currently not implemented') + # exit(-1) + # + # self.determine_mass_transfer_timescale() # to set the stability #obsolete? + # return False + # + # return True + + def check_stopping_conditions_stellar(self, stellar_system=None): + # before check stopping conditions_stellar, always make sure the stability labels are up to date + # by running self.determine_mass_transfer_timescale() if stellar_system == None: stellar_system = self.triple @@ -2143,16 +2705,19 @@ def check_stopping_conditions_stellar(self, stellar_system = None): if self.stop_at_outer_mass_transfer and self.has_tertiary_donor(): if self.secular_code.model_time < self.triple.time: self.triple.time = self.secular_code.model_time - + if REPORT_TRIPLE_EVOLUTION: - print('Mass transfer in outer binary of triple at time = ',self.triple.time) + print( + "Mass transfer in outer binary of triple at time = ", + self.triple.time, + ) if stellar_system.is_mt_stable: - stellar_system.bin_type = bin_type['stable_mass_transfer'] + stellar_system.bin_type = bin_type["stable_mass_transfer"] else: - stellar_system.bin_type = bin_type['common_envelope'] + stellar_system.bin_type = bin_type["common_envelope"] - return False + return False else: if not self.check_stopping_conditions_stellar(stellar_system.child1): return False @@ -2161,109 +2726,144 @@ def check_stopping_conditions_stellar(self, stellar_system = None): return True elif stellar_system.is_star: return True - elif self.is_binary(stellar_system): - if (self.has_donor(stellar_system) or self.has_OLOF_donor(stellar_system)) and (self.stop_at_mass_transfer or - (self.stop_at_stable_mass_transfer and stellar_system.is_mt_stable) or - (self.stop_at_unstable_mass_transfer and not stellar_system.is_mt_stable) or - (self.stop_at_eccentric_stable_mass_transfer and stellar_system.is_mt_stable and stellar_system.eccentricity > minimum_eccentricity*5.) or - (self.stop_at_eccentric_unstable_mass_transfer and not stellar_system.is_mt_stable and stellar_system.eccentricity > minimum_eccentricity*5.)): + elif self.is_binary(stellar_system): + if ( + self.has_donor(stellar_system) or self.has_OLOF_donor(stellar_system) + ) and ( + self.stop_at_mass_transfer + or (self.stop_at_stable_mass_transfer and stellar_system.is_mt_stable) + or ( + self.stop_at_unstable_mass_transfer + and not stellar_system.is_mt_stable + ) + or ( + self.stop_at_eccentric_stable_mass_transfer + and stellar_system.is_mt_stable + and stellar_system.eccentricity > minimum_eccentricity * 5.0 + ) + or ( + self.stop_at_eccentric_unstable_mass_transfer + and not stellar_system.is_mt_stable + and stellar_system.eccentricity > minimum_eccentricity * 5.0 + ) + ): if REPORT_TRIPLE_EVOLUTION: - print('Mass transfer in inner binary at time = ',self.triple.time) - print(self.stop_at_mass_transfer,self.stop_at_stable_mass_transfer, self.stop_at_unstable_mass_transfer, self.stop_at_eccentric_stable_mass_transfer, self.stop_at_eccentric_unstable_mass_transfer, stellar_system.is_mt_stable) + print("Mass transfer in inner binary at time = ", self.triple.time) + print( + self.stop_at_mass_transfer, + self.stop_at_stable_mass_transfer, + self.stop_at_unstable_mass_transfer, + self.stop_at_eccentric_stable_mass_transfer, + self.stop_at_eccentric_unstable_mass_transfer, + stellar_system.is_mt_stable, + ) - if stellar_system.is_mt_stable: - stellar_system.bin_type = bin_type['stable_mass_transfer'] - else: - stellar_system.bin_type = bin_type['common_envelope'] + if stellar_system.is_mt_stable: + stellar_system.bin_type = bin_type["stable_mass_transfer"] + else: + stellar_system.bin_type = bin_type["common_envelope"] - return False + return False else: return True - + return True - - - #when these processes are implemented, also the bintypes need to be set in those functions + + # when these processes are implemented, also the bintypes need to be set in those functions def check_stopping_conditions(self): - if self.check_stopping_conditions_stellar()==False: + if self.check_stopping_conditions_stellar() == False: return False - if self.stop_at_dynamical_instability and self.triple.dynamical_instability == True: + if ( + self.stop_at_dynamical_instability + and self.triple.dynamical_instability == True + ): if self.secular_code.model_time < self.triple.time: - self.triple.time = self.secular_code.model_time - self.set_bintype_to_dynamical_instability() + self.triple.time = self.secular_code.model_time + self.set_bintype_to_dynamical_instability() if REPORT_TRIPLE_EVOLUTION: - print("Dynamical instability at time = ",self.triple.time) + print("Dynamical instability at time = ", self.triple.time) return False if self.stop_at_inner_collision and self.triple.inner_collision == True: if self.secular_code.model_time < self.triple.time: self.triple.time = self.secular_code.model_time - self.triple.child2.bin_type = bin_type['collision'] + self.triple.child2.bin_type = bin_type["collision"] if REPORT_TRIPLE_EVOLUTION: - print("Inner collision at time = ",self.triple.time) + print("Inner collision at time = ", self.triple.time) return False if self.stop_at_outer_collision and self.triple.outer_collision == True: if self.secular_code.model_time < self.triple.time: self.triple.time = self.secular_code.model_time - self.triple.bin_type = bin_type['collision'] + self.triple.bin_type = bin_type["collision"] if REPORT_TRIPLE_EVOLUTION: - print("Outer collision at time = ",self.triple.time) + print("Outer collision at time = ", self.triple.time) return False if self.stop_at_semisecular_regime and self.triple.semisecular_regime == True: if self.secular_code.model_time < self.triple.time: self.triple.time = self.secular_code.model_time - self.triple.bin_type = bin_type['semisecular'] + self.triple.bin_type = bin_type["semisecular"] if REPORT_TRIPLE_EVOLUTION: - print("Semisecular regime at time = ",self.triple.time) + print("Semisecular regime at time = ", self.triple.time) return False - if self.triple.time - self.secular_code.model_time > numerical_error|units.Myr: - print('triple time > sec time: should not be possible', self.triple.time, self.secular_code.model_time) - print(self.has_donor(), self.secular_code.triples[0].error_flag_secular, self.secular_code.triples[0].dynamical_instability) + if ( + self.triple.time - self.secular_code.model_time + > numerical_error | units.Myr + ): + print( + "triple time > sec time: should not be possible", + self.triple.time, + self.secular_code.model_time, + ) + print( + self.has_donor(), + self.secular_code.triples[0].error_flag_secular, + self.secular_code.triples[0].dynamical_instability, + ) return False - - return True + return True - def check_spin_angular_frequency(self, stellar_system = None): + def check_spin_angular_frequency(self, stellar_system=None): if stellar_system == None: stellar_system = self.triple if stellar_system.is_star: - if stellar_system.spin_angular_frequency < 0.0|1./units.Myr: + if stellar_system.spin_angular_frequency < 0.0 | 1.0 / units.Myr: if REPORT_DEBUG: - print("Error in spin at time = ",self.triple.time) - + print("Error in spin at time = ", self.triple.time) return False - return True + return True else: - if self.check_spin_angular_frequency(stellar_system.child1) == False or self.check_spin_angular_frequency(stellar_system.child2)==False: + if ( + self.check_spin_angular_frequency(stellar_system.child1) == False + or self.check_spin_angular_frequency(stellar_system.child2) == False + ): return False return True - def check_error_flag_secular(self): + def check_error_flag_secular(self): if self.triple.error_flag_secular < 0: if REPORT_TRIPLE_EVOLUTION: - print("Error in secular code at time = ",self.triple.time) + print("Error in secular code at time = ", self.triple.time) print(self.triple.error_flag_secular) return False return True - + def calculate_maximum_change_eccentricity(self): if self.triple.child2.delta_e_in > self.triple.child2.max_delta_e_in: self.triple.child2.max_delta_e_in = self.triple.child2.delta_e_in - - -#------------------------- + + # ------------------------- def evolve_model(self, tend): self.tend = tend CPU_start_time = time.time() - + if REPORT_DEBUG or MAKE_PLOTS: # for plotting data - times_array = quantities.AdaptingVectorQuantity() + times_array = quantities.AdaptingVectorQuantity() a_in_array = quantities.AdaptingVectorQuantity() e_in_array = [] g_in_array = [] @@ -2289,261 +2889,362 @@ def evolve_model(self, tend): RL2_array = [] RL3_array = [] delta_e_in_array = [] - + times_array.append(self.triple.time) e_in_array.append(self.triple.child2.eccentricity) a_in_array.append(self.triple.child2.semimajor_axis) - g_in_array.append(self.triple.child2.argument_of_pericenter) - o_in_array.append(self.triple.child2.longitude_of_ascending_node) + g_in_array.append(self.triple.child2.argument_of_pericenter) + o_in_array.append(self.triple.child2.longitude_of_ascending_node) e_out_array.append(self.triple.eccentricity) a_out_array.append(self.triple.semimajor_axis) - g_out_array.append(self.triple.argument_of_pericenter) - o_out_array.append(self.triple.longitude_of_ascending_node) - i_relative_array.append(self.triple.relative_inclination) + g_out_array.append(self.triple.argument_of_pericenter) + o_out_array.append(self.triple.longitude_of_ascending_node) + i_relative_array.append(self.triple.relative_inclination) m1_array.append(self.triple.child2.child1.mass) m2_array.append(self.triple.child2.child2.mass) m3_array.append(self.triple.child1.mass) - spin1_array.append(self.triple.child2.child1.spin_angular_frequency.value_in(1./units.Myr)) - spin2_array.append(self.triple.child2.child2.spin_angular_frequency.value_in(1./units.Myr)) - spin3_array.append(self.triple.child1.spin_angular_frequency.value_in(1./units.Myr)) + spin1_array.append( + self.triple.child2.child1.spin_angular_frequency.value_in( + 1.0 / units.Myr + ) + ) + spin2_array.append( + self.triple.child2.child2.spin_angular_frequency.value_in( + 1.0 / units.Myr + ) + ) + spin3_array.append( + self.triple.child1.spin_angular_frequency.value_in(1.0 / units.Myr) + ) r1_array.append(self.triple.child2.child1.radius.value_in(units.RSun)) r2_array.append(self.triple.child2.child2.radius.value_in(units.RSun)) r3_array.append(self.triple.child1.radius.value_in(units.RSun)) - moi1_array.append(self.triple.child2.child1.moment_of_inertia_of_star.value_in(units.RSun**2*units.MSun)) - moi2_array.append(self.triple.child2.child2.moment_of_inertia_of_star.value_in(units.RSun**2*units.MSun)) - moi3_array.append(self.triple.child1.moment_of_inertia_of_star.value_in(units.RSun**2*units.MSun)) + moi1_array.append( + self.triple.child2.child1.moment_of_inertia_of_star.value_in( + units.RSun**2 * units.MSun + ) + ) + moi2_array.append( + self.triple.child2.child2.moment_of_inertia_of_star.value_in( + units.RSun**2 * units.MSun + ) + ) + moi3_array.append( + self.triple.child1.moment_of_inertia_of_star.value_in( + units.RSun**2 * units.MSun + ) + ) RL1, RL2, RL3 = self.secular_code.give_roche_radii(self.triple) RL1_array.append(RL1.value_in(units.RSun)) RL2_array.append(RL2.value_in(units.RSun)) RL3_array.append(RL3.value_in(units.RSun)) delta_e_in_array.append(self.triple.child2.delta_e_in) - include_inner_RLOF_term_initial = self.secular_code.parameters.include_inner_RLOF_terms - include_outer_RLOF_term_initial = self.secular_code.parameters.include_outer_RLOF_terms - + include_inner_RLOF_term_initial = ( + self.secular_code.parameters.include_inner_RLOF_terms + ) + include_outer_RLOF_term_initial = ( + self.secular_code.parameters.include_outer_RLOF_terms + ) + if REPORT_TRIPLE_EVOLUTION or REPORT_DEBUG: - print('kozai timescale:', self.kozai_timescale(), self.triple.kozai_type, self.tend) + print( + "kozai timescale:", + self.kozai_timescale(), + self.triple.kozai_type, + self.tend, + ) self.determine_mass_transfer_timescale() - self.save_snapshot() - while self.triple.time self.max_CPU_time: - print('stopping conditions maximum CPU time') + if (self.stop_at_CPU_time == True) and float( + CPU_end_time - CPU_start_time + ) > self.max_CPU_time: + print("stopping conditions maximum CPU time") print("CPU time: ", self.triple.CPU_time) break - - #turning RLOF terms back on if they were on in the first place - #they might have been turned off for contact systems with is_mt_stable in perform_mass_equalisation_for_contact + + # turning RLOF terms back on if they were on in the first place + # they might have been turned off for contact systems with is_mt_stable in perform_mass_equalisation_for_contact if include_inner_RLOF_term_initial == True: - self.secular_code.parameters.include_inner_RLOF_terms = True + self.secular_code.parameters.include_inner_RLOF_terms = True if include_outer_RLOF_term_initial == True: - self.secular_code.parameters.include_outer_RLOF_terms = True - + self.secular_code.parameters.include_outer_RLOF_terms = True - #setting time parameters + # setting time parameters if self.has_stellar_type_changed() or self.has_kozai_type_changed(): - self.save_snapshot() + self.save_snapshot() - dt = self.determine_time_step() - if not no_stellar_evolution: + dt = self.determine_time_step() + if not no_stellar_evolution: self.update_previous_stellar_parameters() self.stellar_code.particles.refresh_memory() - self.triple.time += dt - self.previous_dt = dt + self.triple.time += dt + self.previous_dt = dt if REPORT_DEBUG or REPORT_DT: - print('\t time:', self.triple.time, self.previous_time, self.previous_dt) - - if self.triple.time minimum_time_step + ): + # self.rewind_to_begin_of_rlof_stellar(dt) + # print('RLOF:', self.triple.child2.child1.is_donor, self.triple.bin_type , self.triple.child2.bin_type ) self.stellar_code.particles.recall_memory_one_step() self.copy_from_stellar() - self.update_stellar_parameters() - if self.include_CHE:#only needed when including CHE - self.channel_to_stellar.copy_attributes(['rotation_period']) #for CHE - self.refresh_memory() - #note that 'previous' parameters cannot be reset - #resetting is_donor in determine_time_step + self.update_stellar_parameters() + if self.include_CHE: # only needed when including CHE + self.channel_to_stellar.copy_attributes( + ["rotation_period"] + ) # for CHE + self.refresh_memory() + # note that 'previous' parameters cannot be reset + # resetting is_donor in determine_time_step continue - + # needed for nucleair timescale + self.update_time_derivative_of_radius() - #needed for nucleair timescale - self.update_time_derivative_of_radius() - - #do stellar interaction + # do stellar interaction if REPORT_DEBUG: - print('Stellar interaction') + print("Stellar interaction") self.determine_mass_transfer_timescale() - if self.check_stopping_conditions_stellar()==False: - print('stopping conditions stellar') - break + if self.check_stopping_conditions_stellar() == False: + print("stopping conditions stellar") + break if not self.resolve_stellar_interaction(): - print('stopping conditions stellar interaction') - break - self.update_time_derivative_of_radius() # includes radius change from wind and ce, not stable mt - self.update_time_derivative_of_moment_of_inertia() # includes mass and radius change from wind and mass transfer - if self.check_stopping_conditions_stellar_interaction()==False: - print('stopping conditions stellar interaction 2') + print("stopping conditions stellar interaction") + break + self.update_time_derivative_of_radius() # includes radius change from wind and ce, not stable mt + self.update_time_derivative_of_moment_of_inertia() # includes mass and radius change from wind and mass transfer + if self.check_stopping_conditions_stellar_interaction() == False: + print("stopping conditions stellar interaction 2") break - - - + # do secular evolution if self.instantaneous_evolution == False: if REPORT_DEBUG: - print('Secular evolution') + print("Secular evolution") - #needed for refreshing memory in case secular finds RLOF + # needed for refreshing memory in case secular finds RLOF previous_semimajor_axis_in = self.triple.child2.semimajor_axis previous_eccentricity_in = self.triple.child2.eccentricity - previous_argument_of_pericenter_in = self.triple.child2.argument_of_pericenter - previous_longitude_of_ascending_node_in = self.triple.child2.longitude_of_ascending_node + previous_argument_of_pericenter_in = ( + self.triple.child2.argument_of_pericenter + ) + previous_longitude_of_ascending_node_in = ( + self.triple.child2.longitude_of_ascending_node + ) previous_spin1 = self.triple.child2.child1.spin_angular_frequency previous_spin2 = self.triple.child2.child2.spin_angular_frequency - self.channel_to_secular.copy() - + # if mass transfer should only take place for a fraction of the timestep # e.g. at the end of mass transfer when the envelope is thin - if self.triple.child2.part_dt_mt < 1: # inner binary, see function determine_partial_time_step_stable_mass_transfer - print('skipping') + if ( + self.triple.child2.part_dt_mt < 1 + ): # inner binary, see function determine_partial_time_step_stable_mass_transfer + print("skipping") if self.solve_for_partial_time_step_stable_mass_transfer() == False: break else: self.secular_code.evolve_model(self.triple.time) - + if REPORT_DEBUG: - print('Secular evolution finished') - - # to differentiate between semi-detached and contact + print("Secular evolution finished") + + # to differentiate between semi-detached and contact self.check_RLOF() self.check_OLOF() - - if self.triple.time - self.secular_code.model_time < -1*numerical_error|units.Myr and self.secular_code.triples[0].error_flag_secular >= 0: - print('triple time < sec time: should not be possible', self.triple.time, self.secular_code.model_time) - print(self.has_donor(), self.secular_code.triples[0].error_flag_secular) + + if ( + self.triple.time - self.secular_code.model_time + < -1 * numerical_error | units.Myr + and self.secular_code.triples[0].error_flag_secular >= 0 + ): + print( + "triple time < sec time: should not be possible", + self.triple.time, + self.secular_code.model_time, + ) + print( + self.has_donor(), + self.secular_code.triples[0].error_flag_secular, + ) break - elif (self.has_donor() or self.has_OLOF_donor()) and self.triple.bin_type == 'detached' and self.triple.child2.bin_type == 'detached' and self.secular_code.model_time < self.triple.time-max(minimum_time_step, 0.01*self.determine_time_step_stable_mt()): - #factor 0.01 times time_step_stable_mt as used mass_transfer_timescale from previous timestep - - self.determine_mass_transfer_timescale() - if self.check_stopping_conditions_stellar()==False: - print('stopping conditions stellar 2') - break + elif ( + (self.has_donor() or self.has_OLOF_donor()) + and self.triple.bin_type == "detached" + and self.triple.child2.bin_type == "detached" + and self.secular_code.model_time + < self.triple.time + - max( + minimum_time_step, 0.01 * self.determine_time_step_stable_mt() + ) + ): + # factor 0.01 times time_step_stable_mt as used mass_transfer_timescale from previous timestep + + self.determine_mass_transfer_timescale() + if self.check_stopping_conditions_stellar() == False: + print("stopping conditions stellar 2") + break self.rewind_to_begin_of_rlof_secular() self.triple.child2.semimajor_axis = previous_semimajor_axis_in self.triple.child2.eccentricity = previous_eccentricity_in - self.triple.child2.previous_argument_of_pericenter_in = previous_argument_of_pericenter_in - self.triple.child2.previous_longitude_of_ascending_node_in = previous_longitude_of_ascending_node_in + self.triple.child2.previous_argument_of_pericenter_in = ( + previous_argument_of_pericenter_in + ) + self.triple.child2.previous_longitude_of_ascending_node_in = ( + previous_longitude_of_ascending_node_in + ) self.triple.child2.child1.spin_angular_frequency = previous_spin1 self.triple.child2.child2.spin_angular_frequency = previous_spin2 continue - elif self.has_donor() and self.triple.bin_type == 'detached' and self.triple.child2.bin_type == 'detached': - #time difference secular code & tres small enough to continue mass transfer + elif ( + self.has_donor() + and self.triple.bin_type == "detached" + and self.triple.child2.bin_type == "detached" + ): + # time difference secular code & tres small enough to continue mass transfer self.secular_code.model_time = self.triple.time - - self.channel_from_secular.copy() + self.channel_from_secular.copy() - - if self.check_error_flag_secular()==False: + if self.check_error_flag_secular() == False: break - if self.check_spin_angular_frequency()==False: + if self.check_spin_angular_frequency() == False: break self.determine_mass_transfer_timescale() - if self.check_stopping_conditions()==False: - print('stopping conditions') - break - if not self.stop_at_inner_collision and self.triple.inner_collision == True: + if self.check_stopping_conditions() == False: + print("stopping conditions") + break + if ( + not self.stop_at_inner_collision + and self.triple.inner_collision == True + ): perform_inner_collision(self) - + else: if REPORT_DEBUG: - print('skip secular') + print("skip secular") self.secular_code.model_time = self.triple.time self.instantaneous_evolution = False - - self.calculate_maximum_change_eccentricity() + self.calculate_maximum_change_eccentricity() if REPORT_DEBUG or MAKE_PLOTS: # for plotting data times_array.append(self.triple.time) e_in_array.append(self.triple.child2.eccentricity) a_in_array.append(self.triple.child2.semimajor_axis) - g_in_array.append(self.triple.child2.argument_of_pericenter) - o_in_array.append(self.triple.child2.longitude_of_ascending_node) + g_in_array.append(self.triple.child2.argument_of_pericenter) + o_in_array.append(self.triple.child2.longitude_of_ascending_node) e_out_array.append(self.triple.eccentricity) a_out_array.append(self.triple.semimajor_axis) - g_out_array.append(self.triple.argument_of_pericenter) - o_out_array.append(self.triple.longitude_of_ascending_node) - i_relative_array.append(self.triple.relative_inclination) + g_out_array.append(self.triple.argument_of_pericenter) + o_out_array.append(self.triple.longitude_of_ascending_node) + i_relative_array.append(self.triple.relative_inclination) m1_array.append(self.triple.child2.child1.mass) m2_array.append(self.triple.child2.child2.mass) m3_array.append(self.triple.child1.mass) - spin1_array.append(self.triple.child2.child1.spin_angular_frequency.value_in(1./units.Myr)) - spin2_array.append(self.triple.child2.child2.spin_angular_frequency.value_in(1./units.Myr)) - spin3_array.append(self.triple.child1.spin_angular_frequency.value_in(1./units.Myr)) + spin1_array.append( + self.triple.child2.child1.spin_angular_frequency.value_in( + 1.0 / units.Myr + ) + ) + spin2_array.append( + self.triple.child2.child2.spin_angular_frequency.value_in( + 1.0 / units.Myr + ) + ) + spin3_array.append( + self.triple.child1.spin_angular_frequency.value_in(1.0 / units.Myr) + ) r1_array.append(self.triple.child2.child1.radius.value_in(units.RSun)) r2_array.append(self.triple.child2.child2.radius.value_in(units.RSun)) r3_array.append(self.triple.child1.radius.value_in(units.RSun)) - moi1_array.append(self.triple.child2.child1.moment_of_inertia_of_star.value_in(units.RSun**2*units.MSun)) - moi2_array.append(self.triple.child2.child2.moment_of_inertia_of_star.value_in(units.RSun**2*units.MSun)) - moi3_array.append(self.triple.child1.moment_of_inertia_of_star.value_in(units.RSun**2*units.MSun)) + moi1_array.append( + self.triple.child2.child1.moment_of_inertia_of_star.value_in( + units.RSun**2 * units.MSun + ) + ) + moi2_array.append( + self.triple.child2.child2.moment_of_inertia_of_star.value_in( + units.RSun**2 * units.MSun + ) + ) + moi3_array.append( + self.triple.child1.moment_of_inertia_of_star.value_in( + units.RSun**2 * units.MSun + ) + ) RL1, RL2, RL3 = self.secular_code.give_roche_radii(self.triple) RL1_array.append(RL1.value_in(units.RSun)) RL2_array.append(RL2.value_in(units.RSun)) RL3_array.append(RL3.value_in(units.RSun)) delta_e_in_array.append(self.triple.child2.delta_e_in) - - self.save_snapshot() - - + + self.save_snapshot() + if (REPORT_DEBUG or MAKE_PLOTS) and self.triple.time >= self.tinit: # for plotting data e_in_array = np.array(e_in_array) @@ -2566,17 +3267,17 @@ def evolve_model(self, tend): RL1_array = np.array(RL1_array) RL2_array = np.array(RL2_array) RL3_array = np.array(RL3_array) - + self.plot_data = plot_data_container() self.plot_data.times_array = times_array self.plot_data.a_in_array = a_in_array self.plot_data.e_in_array = e_in_array self.plot_data.g_in_array = g_in_array - self.plot_data.o_in_array = o_in_array + self.plot_data.o_in_array = o_in_array self.plot_data.a_out_array = a_out_array self.plot_data.e_out_array = e_out_array self.plot_data.g_out_array = g_out_array - self.plot_data.o_out_array = o_out_array + self.plot_data.o_out_array = o_out_array self.plot_data.i_relative_array = i_relative_array self.plot_data.m1_array = m1_array self.plot_data.m2_array = m2_array @@ -2594,6 +3295,5 @@ def evolve_model(self, tend): self.plot_data.RL2_array = RL2_array self.plot_data.RL3_array = RL3_array self.plot_data.delta_e_in_array = delta_e_in_array - - - #------- + + # ------- From eae9f0c985ec0b27fdbc0d5f9920c564c89e49b9 Mon Sep 17 00:00:00 2001 From: Steven Rieder Date: Fri, 1 Nov 2024 15:31:39 +0100 Subject: [PATCH 08/30] updates --- src/tres/setup.py | 4 ++-- src/tres/triple_class.py | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/tres/setup.py b/src/tres/setup.py index 3f267cd..32d57f1 100644 --- a/src/tres/setup.py +++ b/src/tres/setup.py @@ -1,9 +1,9 @@ -from amuse.community.seba.interface import SeBa +from amuse.community.seba import Seba from amuse.datamodel import Particles from amuse.units import units from tres.seculartriple_TPS.interface import SecularTriple -from tres.TRES_options import max_mass, absolute_min_mass +from tres.options import max_mass, absolute_min_mass from tres.interactions import * from tres.tidal_friction_constant import * diff --git a/src/tres/triple_class.py b/src/tres/triple_class.py index 7a96cc7..66756e5 100644 --- a/src/tres/triple_class.py +++ b/src/tres/triple_class.py @@ -13,7 +13,7 @@ from tres.interactions import * from tres.tidal_friction_constant import * -# from tres_options import REPORT_USER_WARNINGS, \ +# from tres.options import REPORT_USER_WARNINGS, \ # GET_GYRATION_RADIUS_FROM_STELLAR_CODE, \ # GET_AMC_FROM_STELLAR_CODE, \ # REPORT_TRIPLE_EVOLUTION, \ @@ -24,9 +24,9 @@ # maximum_time_step_factor, \ # minimum_time_step -from tres.TRES_options import * -from tres.TRES_setup import setup_secular_code, setup_stellar_code -from tres.TRES_plotting import plot_data_container +from tres.options import * +from tres.setup import setup_secular_code, setup_stellar_code +from tres.plotting import plot_data_container class Triple_Class: From e07309b58697551cb0958d5f7755ba452d560fcb Mon Sep 17 00:00:00 2001 From: Steven Rieder Date: Mon, 4 Nov 2024 10:16:40 +0100 Subject: [PATCH 09/30] convert line endings --- src/tres/rdc_TRES.py | 650 +++++++++++++++++++++---------------------- 1 file changed, 325 insertions(+), 325 deletions(-) diff --git a/src/tres/rdc_TRES.py b/src/tres/rdc_TRES.py index 03c4060..b90a24c 100644 --- a/src/tres/rdc_TRES.py +++ b/src/tres/rdc_TRES.py @@ -1,167 +1,167 @@ -from amuse.units import units, constants -from amuse.io import write_set_to_file -from amuse.io import read_set_from_file -from amuse.support.console import set_printing_strategy -import numpy as np +from amuse.units import units, constants +from amuse.io import write_set_to_file +from amuse.io import read_set_from_file +from amuse.support.console import set_printing_strategy +import numpy as np import io -import sys - -minimum_time_step = 1.e-9 |units.Myr - -star_type = { 'all': -1, - 'lm_ms': 0, - 'ms': 1, - 'hg': 2, - 'rgb': 3, - 'cheb': 4, - 'eagb': 5, - 'tpagb': 6, - 'agb':[5,6], - 'hems':7, - 'hehg':8, - 'hergb':9, - 'heg':[8,9], - 'hewd': 10, - 'cowd': 11, - 'onewd': 12, - 'wd': [10,11,12], - 'ns': 13, - 'bh': 14, - 'sn': 15, - 'unknown': 16, - 'prems': 17, - 'planet': 18, - 'bd': 19, - } - -bin_type = { 'all': -1, - 'unknown': 0, - 'merger': 1, - 'disintegrated': 2, - 'dynamical_instability': 3, - 'detached': 4, - 'contact': 5, - 'collision': 6, - 'semisecular': 7, - 'rlof': 8, #only used for stopping conditions - 'olof': 9, #only used for stopping conditions - 'stable_mass_transfer': 10, - 'common_envelope': 11, - 'common_envelope_energy_balance': 12, - 'common_envelope_angular_momentum_balance': 13, - 'double_common_envelope': 14, - } - -tr_type = { 'all': -1, - 'hierarchical': 0, - 'dynamical_instability': 1, - 'semisecular_regime': 2, - 'error_flag_secular': 3, - } - +import sys + +minimum_time_step = 1.e-9 |units.Myr + +star_type = { 'all': -1, + 'lm_ms': 0, + 'ms': 1, + 'hg': 2, + 'rgb': 3, + 'cheb': 4, + 'eagb': 5, + 'tpagb': 6, + 'agb':[5,6], + 'hems':7, + 'hehg':8, + 'hergb':9, + 'heg':[8,9], + 'hewd': 10, + 'cowd': 11, + 'onewd': 12, + 'wd': [10,11,12], + 'ns': 13, + 'bh': 14, + 'sn': 15, + 'unknown': 16, + 'prems': 17, + 'planet': 18, + 'bd': 19, + } + +bin_type = { 'all': -1, + 'unknown': 0, + 'merger': 1, + 'disintegrated': 2, + 'dynamical_instability': 3, + 'detached': 4, + 'contact': 5, + 'collision': 6, + 'semisecular': 7, + 'rlof': 8, #only used for stopping conditions + 'olof': 9, #only used for stopping conditions + 'stable_mass_transfer': 10, + 'common_envelope': 11, + 'common_envelope_energy_balance': 12, + 'common_envelope_angular_momentum_balance': 13, + 'double_common_envelope': 14, + } + +tr_type = { 'all': -1, + 'hierarchical': 0, + 'dynamical_instability': 1, + 'semisecular_regime': 2, + 'error_flag_secular': 3, + } + lib_print_style = { 0: "Readable format", 1: "Full", - 2: "TRES standard; selected parameters", - 3: "TRES standard; selected parameters - csv style", - }#default - -def print_particle(particle): - if particle.is_star: - print(particle) - else: - print(particle) - print_particle(particle.child1) - print_particle(particle.child2) - - + 2: "TRES standard; selected parameters", + 3: "TRES standard; selected parameters - csv style", + }#default + +def print_particle(particle): + if particle.is_star: + print(particle) + else: + print(particle) + print_particle(particle.child1) + print_particle(particle.child2) + + def print_to_string(*args, **kwargs): - output = io.StringIO() - print(*args, file=output, **kwargs, sep=' ') - contents = output.getvalue() + output = io.StringIO() + print(*args, file=output, **kwargs, sep=' ') + contents = output.getvalue() output.close() - return contents + return contents def print_to_string_csv(*args, **kwargs): - output = io.StringIO() - print(*args, file=output, **kwargs, sep=',') - contents = output.getvalue() + output = io.StringIO() + print(*args, file=output, **kwargs, sep=',') + contents = output.getvalue() output.close() - return contents - - -#for more info on mass transfer stability, see triple[0].is_mt_stable & triple[0].child2.is_mt_stable -def rdc(file_name_root, print_style, print_full, print_init, line_number, inner_primary_star_type, inner_secondary_star_type, outer_star_type, inner_primary_star_type_string, inner_secondary_star_type_string, outer_star_type_string, -inner_bin_type, outer_bin_type, inner_bin_type_string, outer_bin_type_string, triple_type, triple_type_string): - - file_name = file_name_root + ".hdf" - if file_name_root[-4:]==".hdf": - file_name = file_name_root - - triple=read_set_from_file(file_name , "hdf5") -# counter = list(enumerate(triple.history))[0][1].number - - if print_init: - for i, triple in enumerate(triple.history): - if i == line_number: - print('amuse TRES.py ', end = '' ) - print(' -M ', triple[0].child2.child1.mass.value_in(units.MSun), ' -m ', triple[0].child2.child2.mass.value_in(units.MSun), ' -l ', triple[0].child1.mass.value_in(units.MSun), end = '') - print(' -A ', triple[0].child2.semimajor_axis.value_in(units.RSun), ' -a ', triple[0].semimajor_axis.value_in(units.RSun), end = '') - print(' -E ', triple[0].child2.eccentricity, ' -e ', triple[0].eccentricity, end = '') - print(' -G ', triple[0].child2.argument_of_pericenter, ' -g ', triple[0].argument_of_pericenter, end = '') - print(' -I ', triple[0].relative_inclination, end = '\t') - - if triple[0].time > minimum_time_step: - print('Warning: these parameters do not represent a system at birth (ZAMS).') - - return - - - correct_system = False - correct_system_previous = False -# print(inner_primary_star_type, inner_secondary_star_type, outer_star_type) -# print(star_type[inner_primary_star_type_string],star_type[inner_secondary_star_type_string],star_type[outer_star_type_string] ) -# print(inner_bin_type, outer_bin_type, triple_type) -# print(bin_type[inner_bin_type_string], bin_type[outer_bin_type_string], tr_type[triple_type_string]) - - if inner_primary_star_type != -1 and star_type[inner_primary_star_type_string] != -1 and inner_primary_star_type != star_type[inner_primary_star_type_string] : - print('error: two different inner primary star types requested') - return - if inner_secondary_star_type != -1 and star_type[inner_secondary_star_type_string] != -1 and inner_secondary_star_type != star_type[inner_secondary_star_type_string] : - print('error: two different inner secondary star types requested') - return - if outer_star_type != -1 and star_type[outer_star_type_string] != -1 and outer_star_type != star_type[outer_star_type_string] : - print('error: two different outer star types requested') - return - if inner_bin_type > -1 and bin_type[inner_bin_type_string] > -1 and inner_bin_type != bin_type[inner_bin_type_string] : - print('error: two different inner binary types requested') - return - if outer_bin_type > -1 and bin_type[outer_bin_type_string] > -1 and outer_bin_type != bin_type[outer_bin_type_string]: - print('error: two different outer binary types requested') - return - if triple_type > -1 and tr_type[triple_type_string] > -1 and triple_type != tr_type[triple_type_string] : - print('error: two different triple types requested') - return - - if star_type[inner_primary_star_type_string] != -1: - inner_primary_star_type = star_type[inner_primary_star_type_string] - if star_type[inner_secondary_star_type_string] != -1: - inner_secondary_star_type = star_type[inner_secondary_star_type_string] - if star_type[outer_star_type_string] != -1: - outer_star_type = star_type[outer_star_type_string] - inner_bin_type = max(inner_bin_type, bin_type[inner_bin_type_string]) - outer_bin_type = max(outer_bin_type, bin_type[outer_bin_type_string]) - triple_type = max(triple_type, tr_type[triple_type_string]) - -# print(inner_primary_star_type, inner_secondary_star_type, outer_star_type) -# print(star_type[inner_primary_star_type_string],star_type[inner_secondary_star_type_string],star_type[outer_star_type_string] ) -# print(inner_bin_type, outer_bin_type, triple_type) -# print(bin_type[inner_bin_type_string], bin_type[outer_bin_type_string], tr_type[triple_type_string]) - + return contents + + +#for more info on mass transfer stability, see triple[0].is_mt_stable & triple[0].child2.is_mt_stable +def rdc(file_name_root, print_style, print_full, print_init, line_number, inner_primary_star_type, inner_secondary_star_type, outer_star_type, inner_primary_star_type_string, inner_secondary_star_type_string, outer_star_type_string, +inner_bin_type, outer_bin_type, inner_bin_type_string, outer_bin_type_string, triple_type, triple_type_string): + + file_name = file_name_root + ".hdf" + if file_name_root[-4:]==".hdf": + file_name = file_name_root + + triple=read_set_from_file(file_name , "hdf5") +# counter = list(enumerate(triple.history))[0][1].number + + if print_init: + for i, triple in enumerate(triple.history): + if i == line_number: + print('amuse TRES.py ', end = '' ) + print(' -M ', triple[0].child2.child1.mass.value_in(units.MSun), ' -m ', triple[0].child2.child2.mass.value_in(units.MSun), ' -l ', triple[0].child1.mass.value_in(units.MSun), end = '') + print(' -A ', triple[0].child2.semimajor_axis.value_in(units.RSun), ' -a ', triple[0].semimajor_axis.value_in(units.RSun), end = '') + print(' -E ', triple[0].child2.eccentricity, ' -e ', triple[0].eccentricity, end = '') + print(' -G ', triple[0].child2.argument_of_pericenter, ' -g ', triple[0].argument_of_pericenter, end = '') + print(' -I ', triple[0].relative_inclination, end = '\t') + + if triple[0].time > minimum_time_step: + print('Warning: these parameters do not represent a system at birth (ZAMS).') + + return + + + correct_system = False + correct_system_previous = False +# print(inner_primary_star_type, inner_secondary_star_type, outer_star_type) +# print(star_type[inner_primary_star_type_string],star_type[inner_secondary_star_type_string],star_type[outer_star_type_string] ) +# print(inner_bin_type, outer_bin_type, triple_type) +# print(bin_type[inner_bin_type_string], bin_type[outer_bin_type_string], tr_type[triple_type_string]) + + if inner_primary_star_type != -1 and star_type[inner_primary_star_type_string] != -1 and inner_primary_star_type != star_type[inner_primary_star_type_string] : + print('error: two different inner primary star types requested') + return + if inner_secondary_star_type != -1 and star_type[inner_secondary_star_type_string] != -1 and inner_secondary_star_type != star_type[inner_secondary_star_type_string] : + print('error: two different inner secondary star types requested') + return + if outer_star_type != -1 and star_type[outer_star_type_string] != -1 and outer_star_type != star_type[outer_star_type_string] : + print('error: two different outer star types requested') + return + if inner_bin_type > -1 and bin_type[inner_bin_type_string] > -1 and inner_bin_type != bin_type[inner_bin_type_string] : + print('error: two different inner binary types requested') + return + if outer_bin_type > -1 and bin_type[outer_bin_type_string] > -1 and outer_bin_type != bin_type[outer_bin_type_string]: + print('error: two different outer binary types requested') + return + if triple_type > -1 and tr_type[triple_type_string] > -1 and triple_type != tr_type[triple_type_string] : + print('error: two different triple types requested') + return + + if star_type[inner_primary_star_type_string] != -1: + inner_primary_star_type = star_type[inner_primary_star_type_string] + if star_type[inner_secondary_star_type_string] != -1: + inner_secondary_star_type = star_type[inner_secondary_star_type_string] + if star_type[outer_star_type_string] != -1: + outer_star_type = star_type[outer_star_type_string] + inner_bin_type = max(inner_bin_type, bin_type[inner_bin_type_string]) + outer_bin_type = max(outer_bin_type, bin_type[outer_bin_type_string]) + triple_type = max(triple_type, tr_type[triple_type_string]) + +# print(inner_primary_star_type, inner_secondary_star_type, outer_star_type) +# print(star_type[inner_primary_star_type_string],star_type[inner_secondary_star_type_string],star_type[outer_star_type_string] ) +# print(inner_bin_type, outer_bin_type, triple_type) +# print(bin_type[inner_bin_type_string], bin_type[outer_bin_type_string], tr_type[triple_type_string]) + print('#', lib_print_style[print_style]) - triple_string = '' + triple_string = '' snapshot_string = '' if print_style == 2: - snapshot_string = snapshot_string + '# ' + snapshot_string = snapshot_string + '# ' if print_style == 2 or print_style == 3: snapshot_string = snapshot_string + 'number, time, incl, dyn_inst, kozai_type, error_flag, CPU_time,' snapshot_string = snapshot_string + ' bin_type2, a2, e2, p2, l2, bin_type1, a1, e1, p1, l1,' @@ -169,179 +169,179 @@ def rdc(file_name_root, print_style, print_full, print_init, line_number, inner_ snapshot_string = snapshot_string + ' m2_donor, m2_stellar_type, m2_mass, m2_spin, m2_radius, m2_core,' snapshot_string = snapshot_string + ' m3_donor, m3_stellar_type, m3_mass, m3_spin, m3_radius, m3_core,' snapshot_string = snapshot_string + '\n' - triple_number = 0 - previous_triple_number = -1 - - for i, triple in enumerate(triple.history): -# print(triple[0].number, triple[0].time) -# if triple[0].number == counter: -# counter += 1 -# print('\n\n') - - #which snapshots to save - if print_full and correct_system: #all snapshots - triple_string = triple_string + snapshot_string - else: #first & last line -# print(i, triple[0].number,triple_number, previous_triple_number) - if triple[0].number>triple_number: # last line & correct_system - triple_string = triple_string + snapshot_string - triple_number = triple[0].number - if correct_system: - print(triple_string[:-2]) #prevents empty line - triple_string = '' - correct_system = False - correct_system_previous = False - elif triple_number > previous_triple_number: #first line - triple_string = triple_string + snapshot_string - previous_triple_number = triple_number - if correct_system == True: - correct_system_previous = True - elif correct_system==True and correct_system_previous==False: - triple_string = triple_string + snapshot_string - previous_triple_number = triple_number - correct_system_previous = True - snapshot_string = '' - - if triple_type != tr_type['all']: - triple_type_snapshot = tr_type['hierarchical'] - if triple[0].dynamical_instability: - triple_type_snapshot = tr_type['dynamical_instability'] -# if triple[0].semisecular_regime: -# triple_type_snapshot = tr_type['semisecular_regime'] - if triple[0].error_flag_secular: - triple_type_snapshot = tr_type['error_flag_secular'] - - - if print_style == 0: -# print(' ') -# print(i, triple[0].number, triple[0].time, triple[0].relative_inclination, triple[0].dynamical_instability, triple[0].kozai_type, triple[0].error_flag_secular, triple[0].CPU_time) -# -# print( ' bs: ', triple[0].child2.bin_type, triple[0].child2.semimajor_axis, triple[0].child2.eccentricity, triple[0].child2.argument_of_pericenter, triple[0].child2.longitude_of_ascending_node,)# triple[0].child2.mass_transfer_rate, -# print( '|', triple[0].bin_type, triple[0].semimajor_axis, triple[0].eccentricity, triple[0].argument_of_pericenter, triple[0].longitude_of_ascending_node)#, triple[0].mass_transfer_rate -# print( ' st: ', triple[0].child2.child1.is_donor, triple[0].child2.child1.stellar_type, triple[0].child2.child1.mass, triple[0].child2.child1.spin_angular_frequency, triple[0].child2.child1.radius, triple[0].child2.child1.core_mass,) -# print( '|', triple[0].child2.child2.is_donor, triple[0].child2.child2.stellar_type, triple[0].child2.child2.mass, triple[0].child2.child2.spin_angular_frequency, triple[0].child2.child2.radius,triple[0].child2.child2.core_mass, ) -# print( '|', triple[0].child1.is_donor, triple[0].child1.stellar_type, triple[0].child1.mass, triple[0].child1.spin_angular_frequency, triple[0].child1.radius, triple[0].child1.core_mass) - - if i>0: - snapshot_string = snapshot_string + print_to_string(' ') - snapshot_string = snapshot_string + print_to_string(i, triple[0].number, triple[0].time, triple[0].relative_inclination, triple[0].dynamical_instability, triple[0].kozai_type, triple[0].error_flag_secular, triple[0].CPU_time) - snapshot_string = snapshot_string + print_to_string(' bs: ', triple[0].child2.bin_type, triple[0].child2.semimajor_axis, triple[0].child2.eccentricity, triple[0].child2.argument_of_pericenter, triple[0].child2.longitude_of_ascending_node) - snapshot_string = snapshot_string + print_to_string('|', triple[0].bin_type, triple[0].semimajor_axis, triple[0].eccentricity, triple[0].argument_of_pericenter, triple[0].longitude_of_ascending_node) - snapshot_string = snapshot_string + print_to_string(' st: ', triple[0].child2.child1.is_donor, triple[0].child2.child1.stellar_type, triple[0].child2.child1.mass, triple[0].child2.child1.spin_angular_frequency, triple[0].child2.child1.radius, triple[0].child2.child1.core_mass) - snapshot_string = snapshot_string + print_to_string('|', triple[0].child2.child2.is_donor, triple[0].child2.child2.stellar_type, triple[0].child2.child2.mass, triple[0].child2.child2.spin_angular_frequency, triple[0].child2.child2.radius,triple[0].child2.child2.core_mass) - snapshot_string = snapshot_string + print_to_string('|', triple[0].child1.is_donor, triple[0].child1.stellar_type, triple[0].child1.mass, triple[0].child1.spin_angular_frequency, triple[0].child1.radius, triple[0].child1.core_mass) - - elif print_style == 1: - print_particle(triple[0]) - -# print('triple particle', triple[0]) -# print('child1', triple[0].child1) -# print('child2',triple[0].child2) -# print('child2.child1',triple[0].child2.child1) -# print('child2.child2',triple[0].child2.child2) - sys.exit(0) - else: -# print(triple[0].number, triple[0].time.value_in(units.Myr), triple[0].relative_inclination, int(triple[0].dynamical_instability), int(triple[0].kozai_type), int(triple[0].error_flag_secular), triple[0].CPU_time, end = '\t') -# print(bin_type[triple[0].child2.bin_type], triple[0].child2.semimajor_axis.value_in(units.RSun), triple[0].child2.eccentricity, triple[0].child2.argument_of_pericenter, triple[0].child2.longitude_of_ascending_node, end = '\t') -# print(bin_type[triple[0].bin_type], triple[0].semimajor_axis.value_in(units.RSun), triple[0].eccentricity, triple[0].argument_of_pericenter, triple[0].longitude_of_ascending_node, end = '\t') -# print(int(triple[0].child2.child1.is_donor), triple[0].child2.child1.stellar_type.value_in(units.stellar_type), triple[0].child2.child1.mass.value_in(units.MSun), triple[0].child2.child1.spin_angular_frequency.value_in(1./units.Myr), triple[0].child2.child1.radius.value_in(units.RSun), triple[0].child2.child1.core_mass.value_in(units.MSun), end = '\t') -# print(int(triple[0].child2.child2.is_donor), triple[0].child2.child2.stellar_type.value_in(units.stellar_type), triple[0].child2.child2.mass.value_in(units.MSun), triple[0].child2.child2.spin_angular_frequency.value_in(1./units.Myr), triple[0].child2.child2.radius.value_in(units.RSun),triple[0].child2.child2.core_mass.value_in(units.MSun), end = '\t' ) -# print(int(triple[0].child1.is_donor), triple[0].child1.stellar_type.value_in(units.stellar_type), triple[0].child1.mass.value_in(units.MSun), triple[0].child1.spin_angular_frequency.value_in(1./units.Myr), triple[0].child1.radius.value_in(units.RSun), triple[0].child1.core_mass.value_in(units.MSun)) + triple_number = 0 + previous_triple_number = -1 + + for i, triple in enumerate(triple.history): +# print(triple[0].number, triple[0].time) +# if triple[0].number == counter: +# counter += 1 +# print('\n\n') + + #which snapshots to save + if print_full and correct_system: #all snapshots + triple_string = triple_string + snapshot_string + else: #first & last line +# print(i, triple[0].number,triple_number, previous_triple_number) + if triple[0].number>triple_number: # last line & correct_system + triple_string = triple_string + snapshot_string + triple_number = triple[0].number + if correct_system: + print(triple_string[:-2]) #prevents empty line + triple_string = '' + correct_system = False + correct_system_previous = False + elif triple_number > previous_triple_number: #first line + triple_string = triple_string + snapshot_string + previous_triple_number = triple_number + if correct_system == True: + correct_system_previous = True + elif correct_system==True and correct_system_previous==False: + triple_string = triple_string + snapshot_string + previous_triple_number = triple_number + correct_system_previous = True + snapshot_string = '' + + if triple_type != tr_type['all']: + triple_type_snapshot = tr_type['hierarchical'] + if triple[0].dynamical_instability: + triple_type_snapshot = tr_type['dynamical_instability'] +# if triple[0].semisecular_regime: +# triple_type_snapshot = tr_type['semisecular_regime'] + if triple[0].error_flag_secular: + triple_type_snapshot = tr_type['error_flag_secular'] + + + if print_style == 0: +# print(' ') +# print(i, triple[0].number, triple[0].time, triple[0].relative_inclination, triple[0].dynamical_instability, triple[0].kozai_type, triple[0].error_flag_secular, triple[0].CPU_time) +# +# print( ' bs: ', triple[0].child2.bin_type, triple[0].child2.semimajor_axis, triple[0].child2.eccentricity, triple[0].child2.argument_of_pericenter, triple[0].child2.longitude_of_ascending_node,)# triple[0].child2.mass_transfer_rate, +# print( '|', triple[0].bin_type, triple[0].semimajor_axis, triple[0].eccentricity, triple[0].argument_of_pericenter, triple[0].longitude_of_ascending_node)#, triple[0].mass_transfer_rate +# print( ' st: ', triple[0].child2.child1.is_donor, triple[0].child2.child1.stellar_type, triple[0].child2.child1.mass, triple[0].child2.child1.spin_angular_frequency, triple[0].child2.child1.radius, triple[0].child2.child1.core_mass,) +# print( '|', triple[0].child2.child2.is_donor, triple[0].child2.child2.stellar_type, triple[0].child2.child2.mass, triple[0].child2.child2.spin_angular_frequency, triple[0].child2.child2.radius,triple[0].child2.child2.core_mass, ) +# print( '|', triple[0].child1.is_donor, triple[0].child1.stellar_type, triple[0].child1.mass, triple[0].child1.spin_angular_frequency, triple[0].child1.radius, triple[0].child1.core_mass) + + if i>0: + snapshot_string = snapshot_string + print_to_string(' ') + snapshot_string = snapshot_string + print_to_string(i, triple[0].number, triple[0].time, triple[0].relative_inclination, triple[0].dynamical_instability, triple[0].kozai_type, triple[0].error_flag_secular, triple[0].CPU_time) + snapshot_string = snapshot_string + print_to_string(' bs: ', triple[0].child2.bin_type, triple[0].child2.semimajor_axis, triple[0].child2.eccentricity, triple[0].child2.argument_of_pericenter, triple[0].child2.longitude_of_ascending_node) + snapshot_string = snapshot_string + print_to_string('|', triple[0].bin_type, triple[0].semimajor_axis, triple[0].eccentricity, triple[0].argument_of_pericenter, triple[0].longitude_of_ascending_node) + snapshot_string = snapshot_string + print_to_string(' st: ', triple[0].child2.child1.is_donor, triple[0].child2.child1.stellar_type, triple[0].child2.child1.mass, triple[0].child2.child1.spin_angular_frequency, triple[0].child2.child1.radius, triple[0].child2.child1.core_mass) + snapshot_string = snapshot_string + print_to_string('|', triple[0].child2.child2.is_donor, triple[0].child2.child2.stellar_type, triple[0].child2.child2.mass, triple[0].child2.child2.spin_angular_frequency, triple[0].child2.child2.radius,triple[0].child2.child2.core_mass) + snapshot_string = snapshot_string + print_to_string('|', triple[0].child1.is_donor, triple[0].child1.stellar_type, triple[0].child1.mass, triple[0].child1.spin_angular_frequency, triple[0].child1.radius, triple[0].child1.core_mass) + + elif print_style == 1: + print_particle(triple[0]) + +# print('triple particle', triple[0]) +# print('child1', triple[0].child1) +# print('child2',triple[0].child2) +# print('child2.child1',triple[0].child2.child1) +# print('child2.child2',triple[0].child2.child2) + sys.exit(0) + else: +# print(triple[0].number, triple[0].time.value_in(units.Myr), triple[0].relative_inclination, int(triple[0].dynamical_instability), int(triple[0].kozai_type), int(triple[0].error_flag_secular), triple[0].CPU_time, end = '\t') +# print(bin_type[triple[0].child2.bin_type], triple[0].child2.semimajor_axis.value_in(units.RSun), triple[0].child2.eccentricity, triple[0].child2.argument_of_pericenter, triple[0].child2.longitude_of_ascending_node, end = '\t') +# print(bin_type[triple[0].bin_type], triple[0].semimajor_axis.value_in(units.RSun), triple[0].eccentricity, triple[0].argument_of_pericenter, triple[0].longitude_of_ascending_node, end = '\t') +# print(int(triple[0].child2.child1.is_donor), triple[0].child2.child1.stellar_type.value_in(units.stellar_type), triple[0].child2.child1.mass.value_in(units.MSun), triple[0].child2.child1.spin_angular_frequency.value_in(1./units.Myr), triple[0].child2.child1.radius.value_in(units.RSun), triple[0].child2.child1.core_mass.value_in(units.MSun), end = '\t') +# print(int(triple[0].child2.child2.is_donor), triple[0].child2.child2.stellar_type.value_in(units.stellar_type), triple[0].child2.child2.mass.value_in(units.MSun), triple[0].child2.child2.spin_angular_frequency.value_in(1./units.Myr), triple[0].child2.child2.radius.value_in(units.RSun),triple[0].child2.child2.core_mass.value_in(units.MSun), end = '\t' ) +# print(int(triple[0].child1.is_donor), triple[0].child1.stellar_type.value_in(units.stellar_type), triple[0].child1.mass.value_in(units.MSun), triple[0].child1.spin_angular_frequency.value_in(1./units.Myr), triple[0].child1.radius.value_in(units.RSun), triple[0].child1.core_mass.value_in(units.MSun)) + - if print_style == 3: - snapshot_string = snapshot_string + print_to_string_csv(triple[0].number, triple[0].time.value_in(units.Myr), triple[0].relative_inclination, int(triple[0].dynamical_instability), int(triple[0].kozai_type), int(triple[0].error_flag_secular), triple[0].CPU_time, end = ',') - snapshot_string = snapshot_string + print_to_string_csv(bin_type[triple[0].child2.bin_type], triple[0].child2.semimajor_axis.value_in(units.RSun), triple[0].child2.eccentricity, triple[0].child2.argument_of_pericenter, triple[0].child2.longitude_of_ascending_node, end = ',') - snapshot_string = snapshot_string + print_to_string_csv(bin_type[triple[0].bin_type], triple[0].semimajor_axis.value_in(units.RSun), triple[0].eccentricity, triple[0].argument_of_pericenter, triple[0].longitude_of_ascending_node, end = ',') - snapshot_string = snapshot_string + print_to_string_csv(int(triple[0].child2.child1.is_donor), triple[0].child2.child1.stellar_type.value_in(units.stellar_type), triple[0].child2.child1.mass.value_in(units.MSun), triple[0].child2.child1.spin_angular_frequency.value_in(1./units.Myr), triple[0].child2.child1.radius.value_in(units.RSun), triple[0].child2.child1.core_mass.value_in(units.MSun), end = ',') - snapshot_string = snapshot_string + print_to_string_csv(int(triple[0].child2.child2.is_donor), triple[0].child2.child2.stellar_type.value_in(units.stellar_type), triple[0].child2.child2.mass.value_in(units.MSun), triple[0].child2.child2.spin_angular_frequency.value_in(1./units.Myr), triple[0].child2.child2.radius.value_in(units.RSun),triple[0].child2.child2.core_mass.value_in(units.MSun), end = ',') - snapshot_string = snapshot_string + print_to_string_csv(int(triple[0].child1.is_donor), triple[0].child1.stellar_type.value_in(units.stellar_type), triple[0].child1.mass.value_in(units.MSun), triple[0].child1.spin_angular_frequency.value_in(1./units.Myr), triple[0].child1.radius.value_in(units.RSun), triple[0].child1.core_mass.value_in(units.MSun)) + snapshot_string = snapshot_string + print_to_string_csv(triple[0].number, triple[0].time.value_in(units.Myr), triple[0].relative_inclination, int(triple[0].dynamical_instability), int(triple[0].kozai_type), int(triple[0].error_flag_secular), triple[0].CPU_time, end = ',') + snapshot_string = snapshot_string + print_to_string_csv(bin_type[triple[0].child2.bin_type], triple[0].child2.semimajor_axis.value_in(units.RSun), triple[0].child2.eccentricity, triple[0].child2.argument_of_pericenter, triple[0].child2.longitude_of_ascending_node, end = ',') + snapshot_string = snapshot_string + print_to_string_csv(bin_type[triple[0].bin_type], triple[0].semimajor_axis.value_in(units.RSun), triple[0].eccentricity, triple[0].argument_of_pericenter, triple[0].longitude_of_ascending_node, end = ',') + snapshot_string = snapshot_string + print_to_string_csv(int(triple[0].child2.child1.is_donor), triple[0].child2.child1.stellar_type.value_in(units.stellar_type), triple[0].child2.child1.mass.value_in(units.MSun), triple[0].child2.child1.spin_angular_frequency.value_in(1./units.Myr), triple[0].child2.child1.radius.value_in(units.RSun), triple[0].child2.child1.core_mass.value_in(units.MSun), end = ',') + snapshot_string = snapshot_string + print_to_string_csv(int(triple[0].child2.child2.is_donor), triple[0].child2.child2.stellar_type.value_in(units.stellar_type), triple[0].child2.child2.mass.value_in(units.MSun), triple[0].child2.child2.spin_angular_frequency.value_in(1./units.Myr), triple[0].child2.child2.radius.value_in(units.RSun),triple[0].child2.child2.core_mass.value_in(units.MSun), end = ',') + snapshot_string = snapshot_string + print_to_string_csv(int(triple[0].child1.is_donor), triple[0].child1.stellar_type.value_in(units.stellar_type), triple[0].child1.mass.value_in(units.MSun), triple[0].child1.spin_angular_frequency.value_in(1./units.Myr), triple[0].child1.radius.value_in(units.RSun), triple[0].child1.core_mass.value_in(units.MSun)) else: - snapshot_string = snapshot_string + print_to_string(triple[0].number, triple[0].time.value_in(units.Myr), triple[0].relative_inclination, int(triple[0].dynamical_instability), int(triple[0].kozai_type), int(triple[0].error_flag_secular), triple[0].CPU_time, end = '\t') - snapshot_string = snapshot_string + print_to_string(bin_type[triple[0].child2.bin_type], triple[0].child2.semimajor_axis.value_in(units.RSun), triple[0].child2.eccentricity, triple[0].child2.argument_of_pericenter, triple[0].child2.longitude_of_ascending_node, end = '\t') - snapshot_string = snapshot_string + print_to_string(bin_type[triple[0].bin_type], triple[0].semimajor_axis.value_in(units.RSun), triple[0].eccentricity, triple[0].argument_of_pericenter, triple[0].longitude_of_ascending_node, end = '\t') - snapshot_string = snapshot_string + print_to_string(int(triple[0].child2.child1.is_donor), triple[0].child2.child1.stellar_type.value_in(units.stellar_type), triple[0].child2.child1.mass.value_in(units.MSun), triple[0].child2.child1.spin_angular_frequency.value_in(1./units.Myr), triple[0].child2.child1.radius.value_in(units.RSun), triple[0].child2.child1.core_mass.value_in(units.MSun), end = '\t') - snapshot_string = snapshot_string + print_to_string(int(triple[0].child2.child2.is_donor), triple[0].child2.child2.stellar_type.value_in(units.stellar_type), triple[0].child2.child2.mass.value_in(units.MSun), triple[0].child2.child2.spin_angular_frequency.value_in(1./units.Myr), triple[0].child2.child2.radius.value_in(units.RSun),triple[0].child2.child2.core_mass.value_in(units.MSun), end = '\t') - snapshot_string = snapshot_string + print_to_string(int(triple[0].child1.is_donor), triple[0].child1.stellar_type.value_in(units.stellar_type), triple[0].child1.mass.value_in(units.MSun), triple[0].child1.spin_angular_frequency.value_in(1./units.Myr), triple[0].child1.radius.value_in(units.RSun), triple[0].child1.core_mass.value_in(units.MSun)) -# snapshot_string = snapshot_string + '\n' - - if (inner_primary_star_type == star_type['all'] or triple[0].child2.child1.stellar_type.value_in(units.stellar_type) in np.array(inner_primary_star_type)) and \ - (inner_secondary_star_type == star_type['all'] or triple[0].child2.child2.stellar_type.value_in(units.stellar_type) in np.array(inner_secondary_star_type)) and \ - (outer_star_type == star_type['all'] or triple[0].child1.stellar_type.value_in(units.stellar_type) in np.array(outer_star_type)) and \ - (inner_bin_type == bin_type['all'] or inner_bin_type == bin_type[triple[0].child2.bin_type]) and \ - (outer_bin_type == bin_type['all'] or outer_bin_type == bin_type[triple[0].bin_type]) and \ - (triple_type == tr_type['all'] or triple_type == triple_type_snapshot): - correct_system = True - - if i==0 and print_full==False: - triple_string = triple_string + snapshot_string - #in case triple[0].number in file doesn't start at 0 - triple_number = triple[0].number - previous_triple_number = triple_number - if correct_system == True: - correct_system_previous = True - - triple_string = triple_string + snapshot_string - if correct_system: - print(triple_string, end='') - - -def parse_arguments(): - from amuse.units.optparse import OptionParser - parser = OptionParser() - parser.add_option("-f", dest="file_name_root", default = "TRES", - help="file name [%default]") - parser.add_option("-S", dest="print_style", type="int", default = 2, - help="print style [%default]") - parser.add_option("-F", dest="print_full", action="store_true", default = False, - help="print every snapshot for specified triple [%default]") - parser.add_option("--print_init", dest="print_init", action="store_true", default = False, - help="print initial conditions for re running [%default]") - parser.add_option("-l", dest="line_number", type="int", default = 0, - help="line number for printing initial conditions [%default]") #will only do something when print_init = True - - #returns first instance where desired star_type, bin_type & triple_type is reached - parser.add_option("--st1", dest="inner_primary_star_type", type="int", default = -1, - help="desired stellar type of inner binary primary star (int) [%default]") - parser.add_option("--st2", dest="inner_secondary_star_type", type="int", default = -1, - help="desired stellar type of inner binary secondary star (int) [%default]") - parser.add_option("--st3", dest="outer_star_type", type="int", default = -1, - help="desired stellar type of tertiary star (int) [%default]") - parser.add_option("--st1str", dest="inner_primary_star_type_string", default = "all", - help="desired stellar type of inner binary primary star (int) [%default]") - parser.add_option("--st2str", dest="inner_secondary_star_type_string", default = "all", - help="desired stellar type of inner binary secondary star (int) [%default]") - parser.add_option("--st3str", dest="outer_star_type_string", default = "all", - help="desired stellar type of tertiary star [%default]") - parser.add_option("--btin", dest="inner_bin_type", type="int", default = -1, - help="desired binary type of inner binary (int) [%default]") - parser.add_option("--btout", dest="outer_bin_type", type="int", default = -1, - help="desired binary type of inner binary (int) [%default]") - parser.add_option("--btinstr", dest="inner_bin_type_string", default = "all", - help="desired binary type of inner binary (string) [%default]") - parser.add_option("--btoutstr", dest="outer_bin_type_string", default = "all", - help="desired binary type of outer binary (string) [%default]") - parser.add_option("--trt", dest="triple_type", type="int", default = -1, - help="desired triple type (int) [%default]") - parser.add_option("--trtstr", dest="triple_type_string", default = "all", - help="desired triple type [%default]") - - - options, args = parser.parse_args() - return options.__dict__ - - -if __name__ == '__main__': - options = parse_arguments() - - set_printing_strategy("custom", - preferred_units = [units.MSun, units.RSun, units.Myr], - precision = 11, prefix = "", - separator = " [", suffix = "]") - - - - print(' ') - rdc(**options) - + snapshot_string = snapshot_string + print_to_string(triple[0].number, triple[0].time.value_in(units.Myr), triple[0].relative_inclination, int(triple[0].dynamical_instability), int(triple[0].kozai_type), int(triple[0].error_flag_secular), triple[0].CPU_time, end = '\t') + snapshot_string = snapshot_string + print_to_string(bin_type[triple[0].child2.bin_type], triple[0].child2.semimajor_axis.value_in(units.RSun), triple[0].child2.eccentricity, triple[0].child2.argument_of_pericenter, triple[0].child2.longitude_of_ascending_node, end = '\t') + snapshot_string = snapshot_string + print_to_string(bin_type[triple[0].bin_type], triple[0].semimajor_axis.value_in(units.RSun), triple[0].eccentricity, triple[0].argument_of_pericenter, triple[0].longitude_of_ascending_node, end = '\t') + snapshot_string = snapshot_string + print_to_string(int(triple[0].child2.child1.is_donor), triple[0].child2.child1.stellar_type.value_in(units.stellar_type), triple[0].child2.child1.mass.value_in(units.MSun), triple[0].child2.child1.spin_angular_frequency.value_in(1./units.Myr), triple[0].child2.child1.radius.value_in(units.RSun), triple[0].child2.child1.core_mass.value_in(units.MSun), end = '\t') + snapshot_string = snapshot_string + print_to_string(int(triple[0].child2.child2.is_donor), triple[0].child2.child2.stellar_type.value_in(units.stellar_type), triple[0].child2.child2.mass.value_in(units.MSun), triple[0].child2.child2.spin_angular_frequency.value_in(1./units.Myr), triple[0].child2.child2.radius.value_in(units.RSun),triple[0].child2.child2.core_mass.value_in(units.MSun), end = '\t') + snapshot_string = snapshot_string + print_to_string(int(triple[0].child1.is_donor), triple[0].child1.stellar_type.value_in(units.stellar_type), triple[0].child1.mass.value_in(units.MSun), triple[0].child1.spin_angular_frequency.value_in(1./units.Myr), triple[0].child1.radius.value_in(units.RSun), triple[0].child1.core_mass.value_in(units.MSun)) +# snapshot_string = snapshot_string + '\n' + + if (inner_primary_star_type == star_type['all'] or triple[0].child2.child1.stellar_type.value_in(units.stellar_type) in np.array(inner_primary_star_type)) and \ + (inner_secondary_star_type == star_type['all'] or triple[0].child2.child2.stellar_type.value_in(units.stellar_type) in np.array(inner_secondary_star_type)) and \ + (outer_star_type == star_type['all'] or triple[0].child1.stellar_type.value_in(units.stellar_type) in np.array(outer_star_type)) and \ + (inner_bin_type == bin_type['all'] or inner_bin_type == bin_type[triple[0].child2.bin_type]) and \ + (outer_bin_type == bin_type['all'] or outer_bin_type == bin_type[triple[0].bin_type]) and \ + (triple_type == tr_type['all'] or triple_type == triple_type_snapshot): + correct_system = True + + if i==0 and print_full==False: + triple_string = triple_string + snapshot_string + #in case triple[0].number in file doesn't start at 0 + triple_number = triple[0].number + previous_triple_number = triple_number + if correct_system == True: + correct_system_previous = True + + triple_string = triple_string + snapshot_string + if correct_system: + print(triple_string, end='') + + +def parse_arguments(): + from amuse.units.optparse import OptionParser + parser = OptionParser() + parser.add_option("-f", dest="file_name_root", default = "TRES", + help="file name [%default]") + parser.add_option("-S", dest="print_style", type="int", default = 2, + help="print style [%default]") + parser.add_option("-F", dest="print_full", action="store_true", default = False, + help="print every snapshot for specified triple [%default]") + parser.add_option("--print_init", dest="print_init", action="store_true", default = False, + help="print initial conditions for re running [%default]") + parser.add_option("-l", dest="line_number", type="int", default = 0, + help="line number for printing initial conditions [%default]") #will only do something when print_init = True + + #returns first instance where desired star_type, bin_type & triple_type is reached + parser.add_option("--st1", dest="inner_primary_star_type", type="int", default = -1, + help="desired stellar type of inner binary primary star (int) [%default]") + parser.add_option("--st2", dest="inner_secondary_star_type", type="int", default = -1, + help="desired stellar type of inner binary secondary star (int) [%default]") + parser.add_option("--st3", dest="outer_star_type", type="int", default = -1, + help="desired stellar type of tertiary star (int) [%default]") + parser.add_option("--st1str", dest="inner_primary_star_type_string", default = "all", + help="desired stellar type of inner binary primary star (int) [%default]") + parser.add_option("--st2str", dest="inner_secondary_star_type_string", default = "all", + help="desired stellar type of inner binary secondary star (int) [%default]") + parser.add_option("--st3str", dest="outer_star_type_string", default = "all", + help="desired stellar type of tertiary star [%default]") + parser.add_option("--btin", dest="inner_bin_type", type="int", default = -1, + help="desired binary type of inner binary (int) [%default]") + parser.add_option("--btout", dest="outer_bin_type", type="int", default = -1, + help="desired binary type of inner binary (int) [%default]") + parser.add_option("--btinstr", dest="inner_bin_type_string", default = "all", + help="desired binary type of inner binary (string) [%default]") + parser.add_option("--btoutstr", dest="outer_bin_type_string", default = "all", + help="desired binary type of outer binary (string) [%default]") + parser.add_option("--trt", dest="triple_type", type="int", default = -1, + help="desired triple type (int) [%default]") + parser.add_option("--trtstr", dest="triple_type_string", default = "all", + help="desired triple type [%default]") + + + options, args = parser.parse_args() + return options.__dict__ + + +if __name__ == '__main__': + options = parse_arguments() + + set_printing_strategy("custom", + preferred_units = [units.MSun, units.RSun, units.Myr], + precision = 11, prefix = "", + separator = " [", suffix = "]") + + + + print(' ') + rdc(**options) + From 658e857d94e435ecb21cc80b2a4b367e39eeb646 Mon Sep 17 00:00:00 2001 From: Steven Rieder Date: Mon, 4 Nov 2024 10:17:03 +0100 Subject: [PATCH 10/30] restyle with Black --- src/tres/rdc_TRES.py | 857 +++++++++++++++++++++++++++++-------------- 1 file changed, 591 insertions(+), 266 deletions(-) diff --git a/src/tres/rdc_TRES.py b/src/tres/rdc_TRES.py index b90a24c..0e44f42 100644 --- a/src/tres/rdc_TRES.py +++ b/src/tres/rdc_TRES.py @@ -5,343 +5,668 @@ import numpy as np import io import sys - -minimum_time_step = 1.e-9 |units.Myr - -star_type = { 'all': -1, - 'lm_ms': 0, - 'ms': 1, - 'hg': 2, - 'rgb': 3, - 'cheb': 4, - 'eagb': 5, - 'tpagb': 6, - 'agb':[5,6], - 'hems':7, - 'hehg':8, - 'hergb':9, - 'heg':[8,9], - 'hewd': 10, - 'cowd': 11, - 'onewd': 12, - 'wd': [10,11,12], - 'ns': 13, - 'bh': 14, - 'sn': 15, - 'unknown': 16, - 'prems': 17, - 'planet': 18, - 'bd': 19, - } - -bin_type = { 'all': -1, - 'unknown': 0, - 'merger': 1, - 'disintegrated': 2, - 'dynamical_instability': 3, - 'detached': 4, - 'contact': 5, - 'collision': 6, - 'semisecular': 7, - 'rlof': 8, #only used for stopping conditions - 'olof': 9, #only used for stopping conditions - 'stable_mass_transfer': 10, - 'common_envelope': 11, - 'common_envelope_energy_balance': 12, - 'common_envelope_angular_momentum_balance': 13, - 'double_common_envelope': 14, - } - -tr_type = { 'all': -1, - 'hierarchical': 0, - 'dynamical_instability': 1, - 'semisecular_regime': 2, - 'error_flag_secular': 3, - } - -lib_print_style = { 0: "Readable format", - 1: "Full", - 2: "TRES standard; selected parameters", - 3: "TRES standard; selected parameters - csv style", - }#default + +minimum_time_step = 1.0e-9 | units.Myr + +star_type = { + "all": -1, + "lm_ms": 0, + "ms": 1, + "hg": 2, + "rgb": 3, + "cheb": 4, + "eagb": 5, + "tpagb": 6, + "agb": [5, 6], + "hems": 7, + "hehg": 8, + "hergb": 9, + "heg": [8, 9], + "hewd": 10, + "cowd": 11, + "onewd": 12, + "wd": [10, 11, 12], + "ns": 13, + "bh": 14, + "sn": 15, + "unknown": 16, + "prems": 17, + "planet": 18, + "bd": 19, +} + +bin_type = { + "all": -1, + "unknown": 0, + "merger": 1, + "disintegrated": 2, + "dynamical_instability": 3, + "detached": 4, + "contact": 5, + "collision": 6, + "semisecular": 7, + "rlof": 8, # only used for stopping conditions + "olof": 9, # only used for stopping conditions + "stable_mass_transfer": 10, + "common_envelope": 11, + "common_envelope_energy_balance": 12, + "common_envelope_angular_momentum_balance": 13, + "double_common_envelope": 14, +} + +tr_type = { + "all": -1, + "hierarchical": 0, + "dynamical_instability": 1, + "semisecular_regime": 2, + "error_flag_secular": 3, +} + +lib_print_style = { + 0: "Readable format", + 1: "Full", + 2: "TRES standard; selected parameters", + 3: "TRES standard; selected parameters - csv style", +} # default + def print_particle(particle): - if particle.is_star: - print(particle) - else: - print(particle) - print_particle(particle.child1) - print_particle(particle.child2) + if particle.is_star: + print(particle) + else: + print(particle) + print_particle(particle.child1) + print_particle(particle.child2) def print_to_string(*args, **kwargs): output = io.StringIO() - print(*args, file=output, **kwargs, sep=' ') + print(*args, file=output, **kwargs, sep=" ") contents = output.getvalue() output.close() return contents + def print_to_string_csv(*args, **kwargs): output = io.StringIO() - print(*args, file=output, **kwargs, sep=',') + print(*args, file=output, **kwargs, sep=",") contents = output.getvalue() output.close() return contents - -#for more info on mass transfer stability, see triple[0].is_mt_stable & triple[0].child2.is_mt_stable -def rdc(file_name_root, print_style, print_full, print_init, line_number, inner_primary_star_type, inner_secondary_star_type, outer_star_type, inner_primary_star_type_string, inner_secondary_star_type_string, outer_star_type_string, -inner_bin_type, outer_bin_type, inner_bin_type_string, outer_bin_type_string, triple_type, triple_type_string): - file_name = file_name_root + ".hdf" - if file_name_root[-4:]==".hdf": +# for more info on mass transfer stability, see triple[0].is_mt_stable & triple[0].child2.is_mt_stable +def rdc( + file_name_root, + print_style, + print_full, + print_init, + line_number, + inner_primary_star_type, + inner_secondary_star_type, + outer_star_type, + inner_primary_star_type_string, + inner_secondary_star_type_string, + outer_star_type_string, + inner_bin_type, + outer_bin_type, + inner_bin_type_string, + outer_bin_type_string, + triple_type, + triple_type_string, +): + + file_name = file_name_root + ".hdf" + if file_name_root[-4:] == ".hdf": file_name = file_name_root - triple=read_set_from_file(file_name , "hdf5") -# counter = list(enumerate(triple.history))[0][1].number + triple = read_set_from_file(file_name, "hdf5") + # counter = list(enumerate(triple.history))[0][1].number if print_init: for i, triple in enumerate(triple.history): if i == line_number: - print('amuse TRES.py ', end = '' ) - print(' -M ', triple[0].child2.child1.mass.value_in(units.MSun), ' -m ', triple[0].child2.child2.mass.value_in(units.MSun), ' -l ', triple[0].child1.mass.value_in(units.MSun), end = '') - print(' -A ', triple[0].child2.semimajor_axis.value_in(units.RSun), ' -a ', triple[0].semimajor_axis.value_in(units.RSun), end = '') - print(' -E ', triple[0].child2.eccentricity, ' -e ', triple[0].eccentricity, end = '') - print(' -G ', triple[0].child2.argument_of_pericenter, ' -g ', triple[0].argument_of_pericenter, end = '') - print(' -I ', triple[0].relative_inclination, end = '\t') - + print("amuse TRES.py ", end="") + print( + " -M ", + triple[0].child2.child1.mass.value_in(units.MSun), + " -m ", + triple[0].child2.child2.mass.value_in(units.MSun), + " -l ", + triple[0].child1.mass.value_in(units.MSun), + end="", + ) + print( + " -A ", + triple[0].child2.semimajor_axis.value_in(units.RSun), + " -a ", + triple[0].semimajor_axis.value_in(units.RSun), + end="", + ) + print( + " -E ", + triple[0].child2.eccentricity, + " -e ", + triple[0].eccentricity, + end="", + ) + print( + " -G ", + triple[0].child2.argument_of_pericenter, + " -g ", + triple[0].argument_of_pericenter, + end="", + ) + print(" -I ", triple[0].relative_inclination, end="\t") + if triple[0].time > minimum_time_step: - print('Warning: these parameters do not represent a system at birth (ZAMS).') + print( + "Warning: these parameters do not represent a system at birth (ZAMS)." + ) return - correct_system = False correct_system_previous = False -# print(inner_primary_star_type, inner_secondary_star_type, outer_star_type) -# print(star_type[inner_primary_star_type_string],star_type[inner_secondary_star_type_string],star_type[outer_star_type_string] ) -# print(inner_bin_type, outer_bin_type, triple_type) -# print(bin_type[inner_bin_type_string], bin_type[outer_bin_type_string], tr_type[triple_type_string]) - - if inner_primary_star_type != -1 and star_type[inner_primary_star_type_string] != -1 and inner_primary_star_type != star_type[inner_primary_star_type_string] : - print('error: two different inner primary star types requested') + # print(inner_primary_star_type, inner_secondary_star_type, outer_star_type) + # print(star_type[inner_primary_star_type_string],star_type[inner_secondary_star_type_string],star_type[outer_star_type_string] ) + # print(inner_bin_type, outer_bin_type, triple_type) + # print(bin_type[inner_bin_type_string], bin_type[outer_bin_type_string], tr_type[triple_type_string]) + + if ( + inner_primary_star_type != -1 + and star_type[inner_primary_star_type_string] != -1 + and inner_primary_star_type != star_type[inner_primary_star_type_string] + ): + print("error: two different inner primary star types requested") + return + if ( + inner_secondary_star_type != -1 + and star_type[inner_secondary_star_type_string] != -1 + and inner_secondary_star_type != star_type[inner_secondary_star_type_string] + ): + print("error: two different inner secondary star types requested") return - if inner_secondary_star_type != -1 and star_type[inner_secondary_star_type_string] != -1 and inner_secondary_star_type != star_type[inner_secondary_star_type_string] : - print('error: two different inner secondary star types requested') + if ( + outer_star_type != -1 + and star_type[outer_star_type_string] != -1 + and outer_star_type != star_type[outer_star_type_string] + ): + print("error: two different outer star types requested") return - if outer_star_type != -1 and star_type[outer_star_type_string] != -1 and outer_star_type != star_type[outer_star_type_string] : - print('error: two different outer star types requested') + if ( + inner_bin_type > -1 + and bin_type[inner_bin_type_string] > -1 + and inner_bin_type != bin_type[inner_bin_type_string] + ): + print("error: two different inner binary types requested") return - if inner_bin_type > -1 and bin_type[inner_bin_type_string] > -1 and inner_bin_type != bin_type[inner_bin_type_string] : - print('error: two different inner binary types requested') + if ( + outer_bin_type > -1 + and bin_type[outer_bin_type_string] > -1 + and outer_bin_type != bin_type[outer_bin_type_string] + ): + print("error: two different outer binary types requested") return - if outer_bin_type > -1 and bin_type[outer_bin_type_string] > -1 and outer_bin_type != bin_type[outer_bin_type_string]: - print('error: two different outer binary types requested') + if ( + triple_type > -1 + and tr_type[triple_type_string] > -1 + and triple_type != tr_type[triple_type_string] + ): + print("error: two different triple types requested") return - if triple_type > -1 and tr_type[triple_type_string] > -1 and triple_type != tr_type[triple_type_string] : - print('error: two different triple types requested') - return - + if star_type[inner_primary_star_type_string] != -1: inner_primary_star_type = star_type[inner_primary_star_type_string] if star_type[inner_secondary_star_type_string] != -1: inner_secondary_star_type = star_type[inner_secondary_star_type_string] if star_type[outer_star_type_string] != -1: outer_star_type = star_type[outer_star_type_string] - inner_bin_type = max(inner_bin_type, bin_type[inner_bin_type_string]) - outer_bin_type = max(outer_bin_type, bin_type[outer_bin_type_string]) - triple_type = max(triple_type, tr_type[triple_type_string]) - -# print(inner_primary_star_type, inner_secondary_star_type, outer_star_type) -# print(star_type[inner_primary_star_type_string],star_type[inner_secondary_star_type_string],star_type[outer_star_type_string] ) -# print(inner_bin_type, outer_bin_type, triple_type) -# print(bin_type[inner_bin_type_string], bin_type[outer_bin_type_string], tr_type[triple_type_string]) - - print('#', lib_print_style[print_style]) - triple_string = '' - snapshot_string = '' + inner_bin_type = max(inner_bin_type, bin_type[inner_bin_type_string]) + outer_bin_type = max(outer_bin_type, bin_type[outer_bin_type_string]) + triple_type = max(triple_type, tr_type[triple_type_string]) + + # print(inner_primary_star_type, inner_secondary_star_type, outer_star_type) + # print(star_type[inner_primary_star_type_string],star_type[inner_secondary_star_type_string],star_type[outer_star_type_string] ) + # print(inner_bin_type, outer_bin_type, triple_type) + # print(bin_type[inner_bin_type_string], bin_type[outer_bin_type_string], tr_type[triple_type_string]) + + print("#", lib_print_style[print_style]) + triple_string = "" + snapshot_string = "" if print_style == 2: - snapshot_string = snapshot_string + '# ' + snapshot_string = snapshot_string + "# " if print_style == 2 or print_style == 3: - snapshot_string = snapshot_string + 'number, time, incl, dyn_inst, kozai_type, error_flag, CPU_time,' - snapshot_string = snapshot_string + ' bin_type2, a2, e2, p2, l2, bin_type1, a1, e1, p1, l1,' - snapshot_string = snapshot_string + ' m1_donor, m1_stellar_type, m1_mass, m1_spin, m1_radius, m1_core,' - snapshot_string = snapshot_string + ' m2_donor, m2_stellar_type, m2_mass, m2_spin, m2_radius, m2_core,' - snapshot_string = snapshot_string + ' m3_donor, m3_stellar_type, m3_mass, m3_spin, m3_radius, m3_core,' - snapshot_string = snapshot_string + '\n' + snapshot_string = ( + snapshot_string + + "number, time, incl, dyn_inst, kozai_type, error_flag, CPU_time," + ) + snapshot_string = ( + snapshot_string + " bin_type2, a2, e2, p2, l2, bin_type1, a1, e1, p1, l1," + ) + snapshot_string = ( + snapshot_string + + " m1_donor, m1_stellar_type, m1_mass, m1_spin, m1_radius, m1_core," + ) + snapshot_string = ( + snapshot_string + + " m2_donor, m2_stellar_type, m2_mass, m2_spin, m2_radius, m2_core," + ) + snapshot_string = ( + snapshot_string + + " m3_donor, m3_stellar_type, m3_mass, m3_spin, m3_radius, m3_core," + ) + snapshot_string = snapshot_string + "\n" triple_number = 0 - previous_triple_number = -1 - + previous_triple_number = -1 + for i, triple in enumerate(triple.history): -# print(triple[0].number, triple[0].time) -# if triple[0].number == counter: -# counter += 1 -# print('\n\n') - - #which snapshots to save - if print_full and correct_system: #all snapshots - triple_string = triple_string + snapshot_string - else: #first & last line -# print(i, triple[0].number,triple_number, previous_triple_number) - if triple[0].number>triple_number: # last line & correct_system - triple_string = triple_string + snapshot_string - triple_number = triple[0].number - if correct_system: - print(triple_string[:-2]) #prevents empty line - triple_string = '' - correct_system = False - correct_system_previous = False - elif triple_number > previous_triple_number: #first line - triple_string = triple_string + snapshot_string - previous_triple_number = triple_number - if correct_system == True: + # print(triple[0].number, triple[0].time) + # if triple[0].number == counter: + # counter += 1 + # print('\n\n') + + # which snapshots to save + if print_full and correct_system: # all snapshots + triple_string = triple_string + snapshot_string + else: # first & last line + # print(i, triple[0].number,triple_number, previous_triple_number) + if triple[0].number > triple_number: # last line & correct_system + triple_string = triple_string + snapshot_string + triple_number = triple[0].number + if correct_system: + print(triple_string[:-2]) # prevents empty line + triple_string = "" + correct_system = False + correct_system_previous = False + elif triple_number > previous_triple_number: # first line + triple_string = triple_string + snapshot_string + previous_triple_number = triple_number + if correct_system == True: correct_system_previous = True - elif correct_system==True and correct_system_previous==False: - triple_string = triple_string + snapshot_string - previous_triple_number = triple_number - correct_system_previous = True - snapshot_string = '' - - if triple_type != tr_type['all']: - triple_type_snapshot = tr_type['hierarchical'] + elif correct_system == True and correct_system_previous == False: + triple_string = triple_string + snapshot_string + previous_triple_number = triple_number + correct_system_previous = True + snapshot_string = "" + + if triple_type != tr_type["all"]: + triple_type_snapshot = tr_type["hierarchical"] if triple[0].dynamical_instability: - triple_type_snapshot = tr_type['dynamical_instability'] -# if triple[0].semisecular_regime: -# triple_type_snapshot = tr_type['semisecular_regime'] + triple_type_snapshot = tr_type["dynamical_instability"] + # if triple[0].semisecular_regime: + # triple_type_snapshot = tr_type['semisecular_regime'] if triple[0].error_flag_secular: - triple_type_snapshot = tr_type['error_flag_secular'] - - + triple_type_snapshot = tr_type["error_flag_secular"] + if print_style == 0: -# print(' ') -# print(i, triple[0].number, triple[0].time, triple[0].relative_inclination, triple[0].dynamical_instability, triple[0].kozai_type, triple[0].error_flag_secular, triple[0].CPU_time) -# -# print( ' bs: ', triple[0].child2.bin_type, triple[0].child2.semimajor_axis, triple[0].child2.eccentricity, triple[0].child2.argument_of_pericenter, triple[0].child2.longitude_of_ascending_node,)# triple[0].child2.mass_transfer_rate, -# print( '|', triple[0].bin_type, triple[0].semimajor_axis, triple[0].eccentricity, triple[0].argument_of_pericenter, triple[0].longitude_of_ascending_node)#, triple[0].mass_transfer_rate -# print( ' st: ', triple[0].child2.child1.is_donor, triple[0].child2.child1.stellar_type, triple[0].child2.child1.mass, triple[0].child2.child1.spin_angular_frequency, triple[0].child2.child1.radius, triple[0].child2.child1.core_mass,) -# print( '|', triple[0].child2.child2.is_donor, triple[0].child2.child2.stellar_type, triple[0].child2.child2.mass, triple[0].child2.child2.spin_angular_frequency, triple[0].child2.child2.radius,triple[0].child2.child2.core_mass, ) -# print( '|', triple[0].child1.is_donor, triple[0].child1.stellar_type, triple[0].child1.mass, triple[0].child1.spin_angular_frequency, triple[0].child1.radius, triple[0].child1.core_mass) - - if i>0: - snapshot_string = snapshot_string + print_to_string(' ') - snapshot_string = snapshot_string + print_to_string(i, triple[0].number, triple[0].time, triple[0].relative_inclination, triple[0].dynamical_instability, triple[0].kozai_type, triple[0].error_flag_secular, triple[0].CPU_time) - snapshot_string = snapshot_string + print_to_string(' bs: ', triple[0].child2.bin_type, triple[0].child2.semimajor_axis, triple[0].child2.eccentricity, triple[0].child2.argument_of_pericenter, triple[0].child2.longitude_of_ascending_node) - snapshot_string = snapshot_string + print_to_string('|', triple[0].bin_type, triple[0].semimajor_axis, triple[0].eccentricity, triple[0].argument_of_pericenter, triple[0].longitude_of_ascending_node) - snapshot_string = snapshot_string + print_to_string(' st: ', triple[0].child2.child1.is_donor, triple[0].child2.child1.stellar_type, triple[0].child2.child1.mass, triple[0].child2.child1.spin_angular_frequency, triple[0].child2.child1.radius, triple[0].child2.child1.core_mass) - snapshot_string = snapshot_string + print_to_string('|', triple[0].child2.child2.is_donor, triple[0].child2.child2.stellar_type, triple[0].child2.child2.mass, triple[0].child2.child2.spin_angular_frequency, triple[0].child2.child2.radius,triple[0].child2.child2.core_mass) - snapshot_string = snapshot_string + print_to_string('|', triple[0].child1.is_donor, triple[0].child1.stellar_type, triple[0].child1.mass, triple[0].child1.spin_angular_frequency, triple[0].child1.radius, triple[0].child1.core_mass) + # print(' ') + # print(i, triple[0].number, triple[0].time, triple[0].relative_inclination, triple[0].dynamical_instability, triple[0].kozai_type, triple[0].error_flag_secular, triple[0].CPU_time) + # + # print( ' bs: ', triple[0].child2.bin_type, triple[0].child2.semimajor_axis, triple[0].child2.eccentricity, triple[0].child2.argument_of_pericenter, triple[0].child2.longitude_of_ascending_node,)# triple[0].child2.mass_transfer_rate, + # print( '|', triple[0].bin_type, triple[0].semimajor_axis, triple[0].eccentricity, triple[0].argument_of_pericenter, triple[0].longitude_of_ascending_node)#, triple[0].mass_transfer_rate + # print( ' st: ', triple[0].child2.child1.is_donor, triple[0].child2.child1.stellar_type, triple[0].child2.child1.mass, triple[0].child2.child1.spin_angular_frequency, triple[0].child2.child1.radius, triple[0].child2.child1.core_mass,) + # print( '|', triple[0].child2.child2.is_donor, triple[0].child2.child2.stellar_type, triple[0].child2.child2.mass, triple[0].child2.child2.spin_angular_frequency, triple[0].child2.child2.radius,triple[0].child2.child2.core_mass, ) + # print( '|', triple[0].child1.is_donor, triple[0].child1.stellar_type, triple[0].child1.mass, triple[0].child1.spin_angular_frequency, triple[0].child1.radius, triple[0].child1.core_mass) + + if i > 0: + snapshot_string = snapshot_string + print_to_string(" ") + snapshot_string = snapshot_string + print_to_string( + i, + triple[0].number, + triple[0].time, + triple[0].relative_inclination, + triple[0].dynamical_instability, + triple[0].kozai_type, + triple[0].error_flag_secular, + triple[0].CPU_time, + ) + snapshot_string = snapshot_string + print_to_string( + " bs: ", + triple[0].child2.bin_type, + triple[0].child2.semimajor_axis, + triple[0].child2.eccentricity, + triple[0].child2.argument_of_pericenter, + triple[0].child2.longitude_of_ascending_node, + ) + snapshot_string = snapshot_string + print_to_string( + "|", + triple[0].bin_type, + triple[0].semimajor_axis, + triple[0].eccentricity, + triple[0].argument_of_pericenter, + triple[0].longitude_of_ascending_node, + ) + snapshot_string = snapshot_string + print_to_string( + " st: ", + triple[0].child2.child1.is_donor, + triple[0].child2.child1.stellar_type, + triple[0].child2.child1.mass, + triple[0].child2.child1.spin_angular_frequency, + triple[0].child2.child1.radius, + triple[0].child2.child1.core_mass, + ) + snapshot_string = snapshot_string + print_to_string( + "|", + triple[0].child2.child2.is_donor, + triple[0].child2.child2.stellar_type, + triple[0].child2.child2.mass, + triple[0].child2.child2.spin_angular_frequency, + triple[0].child2.child2.radius, + triple[0].child2.child2.core_mass, + ) + snapshot_string = snapshot_string + print_to_string( + "|", + triple[0].child1.is_donor, + triple[0].child1.stellar_type, + triple[0].child1.mass, + triple[0].child1.spin_angular_frequency, + triple[0].child1.radius, + triple[0].child1.core_mass, + ) elif print_style == 1: print_particle(triple[0]) - -# print('triple particle', triple[0]) -# print('child1', triple[0].child1) -# print('child2',triple[0].child2) -# print('child2.child1',triple[0].child2.child1) -# print('child2.child2',triple[0].child2.child2) + + # print('triple particle', triple[0]) + # print('child1', triple[0].child1) + # print('child2',triple[0].child2) + # print('child2.child1',triple[0].child2.child1) + # print('child2.child2',triple[0].child2.child2) sys.exit(0) else: -# print(triple[0].number, triple[0].time.value_in(units.Myr), triple[0].relative_inclination, int(triple[0].dynamical_instability), int(triple[0].kozai_type), int(triple[0].error_flag_secular), triple[0].CPU_time, end = '\t') -# print(bin_type[triple[0].child2.bin_type], triple[0].child2.semimajor_axis.value_in(units.RSun), triple[0].child2.eccentricity, triple[0].child2.argument_of_pericenter, triple[0].child2.longitude_of_ascending_node, end = '\t') -# print(bin_type[triple[0].bin_type], triple[0].semimajor_axis.value_in(units.RSun), triple[0].eccentricity, triple[0].argument_of_pericenter, triple[0].longitude_of_ascending_node, end = '\t') -# print(int(triple[0].child2.child1.is_donor), triple[0].child2.child1.stellar_type.value_in(units.stellar_type), triple[0].child2.child1.mass.value_in(units.MSun), triple[0].child2.child1.spin_angular_frequency.value_in(1./units.Myr), triple[0].child2.child1.radius.value_in(units.RSun), triple[0].child2.child1.core_mass.value_in(units.MSun), end = '\t') -# print(int(triple[0].child2.child2.is_donor), triple[0].child2.child2.stellar_type.value_in(units.stellar_type), triple[0].child2.child2.mass.value_in(units.MSun), triple[0].child2.child2.spin_angular_frequency.value_in(1./units.Myr), triple[0].child2.child2.radius.value_in(units.RSun),triple[0].child2.child2.core_mass.value_in(units.MSun), end = '\t' ) -# print(int(triple[0].child1.is_donor), triple[0].child1.stellar_type.value_in(units.stellar_type), triple[0].child1.mass.value_in(units.MSun), triple[0].child1.spin_angular_frequency.value_in(1./units.Myr), triple[0].child1.radius.value_in(units.RSun), triple[0].child1.core_mass.value_in(units.MSun)) - - + # print(triple[0].number, triple[0].time.value_in(units.Myr), triple[0].relative_inclination, int(triple[0].dynamical_instability), int(triple[0].kozai_type), int(triple[0].error_flag_secular), triple[0].CPU_time, end = '\t') + # print(bin_type[triple[0].child2.bin_type], triple[0].child2.semimajor_axis.value_in(units.RSun), triple[0].child2.eccentricity, triple[0].child2.argument_of_pericenter, triple[0].child2.longitude_of_ascending_node, end = '\t') + # print(bin_type[triple[0].bin_type], triple[0].semimajor_axis.value_in(units.RSun), triple[0].eccentricity, triple[0].argument_of_pericenter, triple[0].longitude_of_ascending_node, end = '\t') + # print(int(triple[0].child2.child1.is_donor), triple[0].child2.child1.stellar_type.value_in(units.stellar_type), triple[0].child2.child1.mass.value_in(units.MSun), triple[0].child2.child1.spin_angular_frequency.value_in(1./units.Myr), triple[0].child2.child1.radius.value_in(units.RSun), triple[0].child2.child1.core_mass.value_in(units.MSun), end = '\t') + # print(int(triple[0].child2.child2.is_donor), triple[0].child2.child2.stellar_type.value_in(units.stellar_type), triple[0].child2.child2.mass.value_in(units.MSun), triple[0].child2.child2.spin_angular_frequency.value_in(1./units.Myr), triple[0].child2.child2.radius.value_in(units.RSun),triple[0].child2.child2.core_mass.value_in(units.MSun), end = '\t' ) + # print(int(triple[0].child1.is_donor), triple[0].child1.stellar_type.value_in(units.stellar_type), triple[0].child1.mass.value_in(units.MSun), triple[0].child1.spin_angular_frequency.value_in(1./units.Myr), triple[0].child1.radius.value_in(units.RSun), triple[0].child1.core_mass.value_in(units.MSun)) + if print_style == 3: - snapshot_string = snapshot_string + print_to_string_csv(triple[0].number, triple[0].time.value_in(units.Myr), triple[0].relative_inclination, int(triple[0].dynamical_instability), int(triple[0].kozai_type), int(triple[0].error_flag_secular), triple[0].CPU_time, end = ',') - snapshot_string = snapshot_string + print_to_string_csv(bin_type[triple[0].child2.bin_type], triple[0].child2.semimajor_axis.value_in(units.RSun), triple[0].child2.eccentricity, triple[0].child2.argument_of_pericenter, triple[0].child2.longitude_of_ascending_node, end = ',') - snapshot_string = snapshot_string + print_to_string_csv(bin_type[triple[0].bin_type], triple[0].semimajor_axis.value_in(units.RSun), triple[0].eccentricity, triple[0].argument_of_pericenter, triple[0].longitude_of_ascending_node, end = ',') - snapshot_string = snapshot_string + print_to_string_csv(int(triple[0].child2.child1.is_donor), triple[0].child2.child1.stellar_type.value_in(units.stellar_type), triple[0].child2.child1.mass.value_in(units.MSun), triple[0].child2.child1.spin_angular_frequency.value_in(1./units.Myr), triple[0].child2.child1.radius.value_in(units.RSun), triple[0].child2.child1.core_mass.value_in(units.MSun), end = ',') - snapshot_string = snapshot_string + print_to_string_csv(int(triple[0].child2.child2.is_donor), triple[0].child2.child2.stellar_type.value_in(units.stellar_type), triple[0].child2.child2.mass.value_in(units.MSun), triple[0].child2.child2.spin_angular_frequency.value_in(1./units.Myr), triple[0].child2.child2.radius.value_in(units.RSun),triple[0].child2.child2.core_mass.value_in(units.MSun), end = ',') - snapshot_string = snapshot_string + print_to_string_csv(int(triple[0].child1.is_donor), triple[0].child1.stellar_type.value_in(units.stellar_type), triple[0].child1.mass.value_in(units.MSun), triple[0].child1.spin_angular_frequency.value_in(1./units.Myr), triple[0].child1.radius.value_in(units.RSun), triple[0].child1.core_mass.value_in(units.MSun)) + snapshot_string = snapshot_string + print_to_string_csv( + triple[0].number, + triple[0].time.value_in(units.Myr), + triple[0].relative_inclination, + int(triple[0].dynamical_instability), + int(triple[0].kozai_type), + int(triple[0].error_flag_secular), + triple[0].CPU_time, + end=",", + ) + snapshot_string = snapshot_string + print_to_string_csv( + bin_type[triple[0].child2.bin_type], + triple[0].child2.semimajor_axis.value_in(units.RSun), + triple[0].child2.eccentricity, + triple[0].child2.argument_of_pericenter, + triple[0].child2.longitude_of_ascending_node, + end=",", + ) + snapshot_string = snapshot_string + print_to_string_csv( + bin_type[triple[0].bin_type], + triple[0].semimajor_axis.value_in(units.RSun), + triple[0].eccentricity, + triple[0].argument_of_pericenter, + triple[0].longitude_of_ascending_node, + end=",", + ) + snapshot_string = snapshot_string + print_to_string_csv( + int(triple[0].child2.child1.is_donor), + triple[0].child2.child1.stellar_type.value_in(units.stellar_type), + triple[0].child2.child1.mass.value_in(units.MSun), + triple[0].child2.child1.spin_angular_frequency.value_in( + 1.0 / units.Myr + ), + triple[0].child2.child1.radius.value_in(units.RSun), + triple[0].child2.child1.core_mass.value_in(units.MSun), + end=",", + ) + snapshot_string = snapshot_string + print_to_string_csv( + int(triple[0].child2.child2.is_donor), + triple[0].child2.child2.stellar_type.value_in(units.stellar_type), + triple[0].child2.child2.mass.value_in(units.MSun), + triple[0].child2.child2.spin_angular_frequency.value_in( + 1.0 / units.Myr + ), + triple[0].child2.child2.radius.value_in(units.RSun), + triple[0].child2.child2.core_mass.value_in(units.MSun), + end=",", + ) + snapshot_string = snapshot_string + print_to_string_csv( + int(triple[0].child1.is_donor), + triple[0].child1.stellar_type.value_in(units.stellar_type), + triple[0].child1.mass.value_in(units.MSun), + triple[0].child1.spin_angular_frequency.value_in(1.0 / units.Myr), + triple[0].child1.radius.value_in(units.RSun), + triple[0].child1.core_mass.value_in(units.MSun), + ) else: - snapshot_string = snapshot_string + print_to_string(triple[0].number, triple[0].time.value_in(units.Myr), triple[0].relative_inclination, int(triple[0].dynamical_instability), int(triple[0].kozai_type), int(triple[0].error_flag_secular), triple[0].CPU_time, end = '\t') - snapshot_string = snapshot_string + print_to_string(bin_type[triple[0].child2.bin_type], triple[0].child2.semimajor_axis.value_in(units.RSun), triple[0].child2.eccentricity, triple[0].child2.argument_of_pericenter, triple[0].child2.longitude_of_ascending_node, end = '\t') - snapshot_string = snapshot_string + print_to_string(bin_type[triple[0].bin_type], triple[0].semimajor_axis.value_in(units.RSun), triple[0].eccentricity, triple[0].argument_of_pericenter, triple[0].longitude_of_ascending_node, end = '\t') - snapshot_string = snapshot_string + print_to_string(int(triple[0].child2.child1.is_donor), triple[0].child2.child1.stellar_type.value_in(units.stellar_type), triple[0].child2.child1.mass.value_in(units.MSun), triple[0].child2.child1.spin_angular_frequency.value_in(1./units.Myr), triple[0].child2.child1.radius.value_in(units.RSun), triple[0].child2.child1.core_mass.value_in(units.MSun), end = '\t') - snapshot_string = snapshot_string + print_to_string(int(triple[0].child2.child2.is_donor), triple[0].child2.child2.stellar_type.value_in(units.stellar_type), triple[0].child2.child2.mass.value_in(units.MSun), triple[0].child2.child2.spin_angular_frequency.value_in(1./units.Myr), triple[0].child2.child2.radius.value_in(units.RSun),triple[0].child2.child2.core_mass.value_in(units.MSun), end = '\t') - snapshot_string = snapshot_string + print_to_string(int(triple[0].child1.is_donor), triple[0].child1.stellar_type.value_in(units.stellar_type), triple[0].child1.mass.value_in(units.MSun), triple[0].child1.spin_angular_frequency.value_in(1./units.Myr), triple[0].child1.radius.value_in(units.RSun), triple[0].child1.core_mass.value_in(units.MSun)) -# snapshot_string = snapshot_string + '\n' - - if (inner_primary_star_type == star_type['all'] or triple[0].child2.child1.stellar_type.value_in(units.stellar_type) in np.array(inner_primary_star_type)) and \ - (inner_secondary_star_type == star_type['all'] or triple[0].child2.child2.stellar_type.value_in(units.stellar_type) in np.array(inner_secondary_star_type)) and \ - (outer_star_type == star_type['all'] or triple[0].child1.stellar_type.value_in(units.stellar_type) in np.array(outer_star_type)) and \ - (inner_bin_type == bin_type['all'] or inner_bin_type == bin_type[triple[0].child2.bin_type]) and \ - (outer_bin_type == bin_type['all'] or outer_bin_type == bin_type[triple[0].bin_type]) and \ - (triple_type == tr_type['all'] or triple_type == triple_type_snapshot): + snapshot_string = snapshot_string + print_to_string( + triple[0].number, + triple[0].time.value_in(units.Myr), + triple[0].relative_inclination, + int(triple[0].dynamical_instability), + int(triple[0].kozai_type), + int(triple[0].error_flag_secular), + triple[0].CPU_time, + end="\t", + ) + snapshot_string = snapshot_string + print_to_string( + bin_type[triple[0].child2.bin_type], + triple[0].child2.semimajor_axis.value_in(units.RSun), + triple[0].child2.eccentricity, + triple[0].child2.argument_of_pericenter, + triple[0].child2.longitude_of_ascending_node, + end="\t", + ) + snapshot_string = snapshot_string + print_to_string( + bin_type[triple[0].bin_type], + triple[0].semimajor_axis.value_in(units.RSun), + triple[0].eccentricity, + triple[0].argument_of_pericenter, + triple[0].longitude_of_ascending_node, + end="\t", + ) + snapshot_string = snapshot_string + print_to_string( + int(triple[0].child2.child1.is_donor), + triple[0].child2.child1.stellar_type.value_in(units.stellar_type), + triple[0].child2.child1.mass.value_in(units.MSun), + triple[0].child2.child1.spin_angular_frequency.value_in( + 1.0 / units.Myr + ), + triple[0].child2.child1.radius.value_in(units.RSun), + triple[0].child2.child1.core_mass.value_in(units.MSun), + end="\t", + ) + snapshot_string = snapshot_string + print_to_string( + int(triple[0].child2.child2.is_donor), + triple[0].child2.child2.stellar_type.value_in(units.stellar_type), + triple[0].child2.child2.mass.value_in(units.MSun), + triple[0].child2.child2.spin_angular_frequency.value_in( + 1.0 / units.Myr + ), + triple[0].child2.child2.radius.value_in(units.RSun), + triple[0].child2.child2.core_mass.value_in(units.MSun), + end="\t", + ) + snapshot_string = snapshot_string + print_to_string( + int(triple[0].child1.is_donor), + triple[0].child1.stellar_type.value_in(units.stellar_type), + triple[0].child1.mass.value_in(units.MSun), + triple[0].child1.spin_angular_frequency.value_in(1.0 / units.Myr), + triple[0].child1.radius.value_in(units.RSun), + triple[0].child1.core_mass.value_in(units.MSun), + ) + # snapshot_string = snapshot_string + '\n' + + if ( + ( + inner_primary_star_type == star_type["all"] + or triple[0].child2.child1.stellar_type.value_in(units.stellar_type) + in np.array(inner_primary_star_type) + ) + and ( + inner_secondary_star_type == star_type["all"] + or triple[0].child2.child2.stellar_type.value_in(units.stellar_type) + in np.array(inner_secondary_star_type) + ) + and ( + outer_star_type == star_type["all"] + or triple[0].child1.stellar_type.value_in(units.stellar_type) + in np.array(outer_star_type) + ) + and ( + inner_bin_type == bin_type["all"] + or inner_bin_type == bin_type[triple[0].child2.bin_type] + ) + and ( + outer_bin_type == bin_type["all"] + or outer_bin_type == bin_type[triple[0].bin_type] + ) + and (triple_type == tr_type["all"] or triple_type == triple_type_snapshot) + ): correct_system = True - if i==0 and print_full==False: + if i == 0 and print_full == False: triple_string = triple_string + snapshot_string - #in case triple[0].number in file doesn't start at 0 + # in case triple[0].number in file doesn't start at 0 triple_number = triple[0].number previous_triple_number = triple_number - if correct_system == True: - correct_system_previous = True - + if correct_system == True: + correct_system_previous = True + triple_string = triple_string + snapshot_string if correct_system: - print(triple_string, end='') + print(triple_string, end="") def parse_arguments(): from amuse.units.optparse import OptionParser + parser = OptionParser() - parser.add_option("-f", dest="file_name_root", default = "TRES", - help="file name [%default]") - parser.add_option("-S", dest="print_style", type="int", default = 2, - help="print style [%default]") - parser.add_option("-F", dest="print_full", action="store_true", default = False, - help="print every snapshot for specified triple [%default]") - parser.add_option("--print_init", dest="print_init", action="store_true", default = False, - help="print initial conditions for re running [%default]") - parser.add_option("-l", dest="line_number", type="int", default = 0, - help="line number for printing initial conditions [%default]") #will only do something when print_init = True - - #returns first instance where desired star_type, bin_type & triple_type is reached - parser.add_option("--st1", dest="inner_primary_star_type", type="int", default = -1, - help="desired stellar type of inner binary primary star (int) [%default]") - parser.add_option("--st2", dest="inner_secondary_star_type", type="int", default = -1, - help="desired stellar type of inner binary secondary star (int) [%default]") - parser.add_option("--st3", dest="outer_star_type", type="int", default = -1, - help="desired stellar type of tertiary star (int) [%default]") - parser.add_option("--st1str", dest="inner_primary_star_type_string", default = "all", - help="desired stellar type of inner binary primary star (int) [%default]") - parser.add_option("--st2str", dest="inner_secondary_star_type_string", default = "all", - help="desired stellar type of inner binary secondary star (int) [%default]") - parser.add_option("--st3str", dest="outer_star_type_string", default = "all", - help="desired stellar type of tertiary star [%default]") - parser.add_option("--btin", dest="inner_bin_type", type="int", default = -1, - help="desired binary type of inner binary (int) [%default]") - parser.add_option("--btout", dest="outer_bin_type", type="int", default = -1, - help="desired binary type of inner binary (int) [%default]") - parser.add_option("--btinstr", dest="inner_bin_type_string", default = "all", - help="desired binary type of inner binary (string) [%default]") - parser.add_option("--btoutstr", dest="outer_bin_type_string", default = "all", - help="desired binary type of outer binary (string) [%default]") - parser.add_option("--trt", dest="triple_type", type="int", default = -1, - help="desired triple type (int) [%default]") - parser.add_option("--trtstr", dest="triple_type_string", default = "all", - help="desired triple type [%default]") - - + parser.add_option( + "-f", dest="file_name_root", default="TRES", help="file name [%default]" + ) + parser.add_option( + "-S", dest="print_style", type="int", default=2, help="print style [%default]" + ) + parser.add_option( + "-F", + dest="print_full", + action="store_true", + default=False, + help="print every snapshot for specified triple [%default]", + ) + parser.add_option( + "--print_init", + dest="print_init", + action="store_true", + default=False, + help="print initial conditions for re running [%default]", + ) + parser.add_option( + "-l", + dest="line_number", + type="int", + default=0, + help="line number for printing initial conditions [%default]", + ) # will only do something when print_init = True + + # returns first instance where desired star_type, bin_type & triple_type is reached + parser.add_option( + "--st1", + dest="inner_primary_star_type", + type="int", + default=-1, + help="desired stellar type of inner binary primary star (int) [%default]", + ) + parser.add_option( + "--st2", + dest="inner_secondary_star_type", + type="int", + default=-1, + help="desired stellar type of inner binary secondary star (int) [%default]", + ) + parser.add_option( + "--st3", + dest="outer_star_type", + type="int", + default=-1, + help="desired stellar type of tertiary star (int) [%default]", + ) + parser.add_option( + "--st1str", + dest="inner_primary_star_type_string", + default="all", + help="desired stellar type of inner binary primary star (int) [%default]", + ) + parser.add_option( + "--st2str", + dest="inner_secondary_star_type_string", + default="all", + help="desired stellar type of inner binary secondary star (int) [%default]", + ) + parser.add_option( + "--st3str", + dest="outer_star_type_string", + default="all", + help="desired stellar type of tertiary star [%default]", + ) + parser.add_option( + "--btin", + dest="inner_bin_type", + type="int", + default=-1, + help="desired binary type of inner binary (int) [%default]", + ) + parser.add_option( + "--btout", + dest="outer_bin_type", + type="int", + default=-1, + help="desired binary type of inner binary (int) [%default]", + ) + parser.add_option( + "--btinstr", + dest="inner_bin_type_string", + default="all", + help="desired binary type of inner binary (string) [%default]", + ) + parser.add_option( + "--btoutstr", + dest="outer_bin_type_string", + default="all", + help="desired binary type of outer binary (string) [%default]", + ) + parser.add_option( + "--trt", + dest="triple_type", + type="int", + default=-1, + help="desired triple type (int) [%default]", + ) + parser.add_option( + "--trtstr", + dest="triple_type_string", + default="all", + help="desired triple type [%default]", + ) + options, args = parser.parse_args() return options.__dict__ -if __name__ == '__main__': +if __name__ == "__main__": options = parse_arguments() - set_printing_strategy("custom", - preferred_units = [units.MSun, units.RSun, units.Myr], - precision = 11, prefix = "", - separator = " [", suffix = "]") - - - - print(' ') - rdc(**options) - + set_printing_strategy( + "custom", + preferred_units=[units.MSun, units.RSun, units.Myr], + precision=11, + prefix="", + separator=" [", + suffix="]", + ) + + print(" ") + rdc(**options) From 6735a4dc90472677c8b569b8ce290822052eed8a Mon Sep 17 00:00:00 2001 From: Steven Rieder Date: Mon, 4 Nov 2024 13:42:26 +0100 Subject: [PATCH 11/30] Refactor interactions.py --- src/tres/interactions.py | 1945 +++++++++++++++++++++++--------------- 1 file changed, 1190 insertions(+), 755 deletions(-) diff --git a/src/tres/interactions.py b/src/tres/interactions.py index 28ba1bd..556ffe6 100644 --- a/src/tres/interactions.py +++ b/src/tres/interactions.py @@ -1,170 +1,231 @@ -from amuse.units import units, constants, quantities +import sys import numpy as np -import sys -import scipy.integrate as integrate +from scipy import integrate + +from amuse.units import units, constants, quantities -from tres.TRES_options import REPORT_BINARY_EVOLUTION, REPORT_FUNCTION_NAMES, REPORT_MASS_TRANSFER_STABILITY +from tres.options import ( + REPORT_BINARY_EVOLUTION, + REPORT_FUNCTION_NAMES, + REPORT_MASS_TRANSFER_STABILITY, +) -#constants -numerical_error = 1.e-6 -small_numerical_error = 1.e-10 -minimum_eccentricity = 1.e-5 +# constants +numerical_error = 1.0e-6 +small_numerical_error = 1.0e-10 +minimum_eccentricity = 1.0e-5 -const_common_envelope_efficiency = 4.0 #1.0, 4 for now for easier testing with SeBa +const_common_envelope_efficiency = 4.0 # 1.0, 4 for now for easier testing with SeBa const_envelope_structure_parameter = 0.5 const_common_envelope_efficiency_gamma = 1.75 -stellar_types_compact_objects = [10,11,12,13,14]|units.stellar_type -stellar_types_giants = [2,3,4,5,6,8,9]|units.stellar_type -stellar_types_planetary_objects = [18,19]|units.stellar_type # planets & brown dwarfs - -stellar_types_SN_remnants = [13,14,15]|units.stellar_type # remnant types created through a supernova -stellar_types_remnants = [7,8,9,10,11,12,13,14,15]|units.stellar_type -stellar_types_dr = [2,4,7,8,9,10,11,12,13,14,15]|units.stellar_type #stars which go through a instantaneous radius change at formation; hertzsprung gap stars (small envelope perturbation) + horizontal branch stars + remnants - - - -#q_crit = 3. -#q_crit_giants_conv_env = 0.9 -nucleair_efficiency = 0.007 # nuc. energy production eff, Delta E = 0.007 Mc^2 - - - - - -#dictionaries -bin_type = { - 'unknown': 'unknown', - 'merger': 'merger', - 'disintegrated': 'disintegrated', - 'dyn_inst': 'dynamical_instability', - - 'detached': 'detached', - 'contact': 'contact', - 'collision': 'collision', - 'semisecular': 'semisecular', - 'rlof': 'rlof', #only used for stopping conditions - 'olof' : 'olof', #only used for stopping conditions - - 'stable_mass_transfer': 'stable_mass_transfer', - 'common_envelope': 'common_envelope', - 'common_envelope_energy_balance': 'common_envelope_energy_balance', - 'common_envelope_angular_momentum_balance': 'common_envelope_angular_momentum_balance', - 'double_common_envelope': 'double_common_envelope', - - } - -#------------------------- -#general functions +stellar_types_compact_objects = [10, 11, 12, 13, 14] | units.stellar_type +stellar_types_giants = [2, 3, 4, 5, 6, 8, 9] | units.stellar_type +stellar_types_planetary_objects = [ + 18, + 19, +] | units.stellar_type # planets & brown dwarfs + +stellar_types_SN_remnants = [ + 13, + 14, + 15, +] | units.stellar_type # remnant types created through a supernova +stellar_types_remnants = [7, 8, 9, 10, 11, 12, 13, 14, 15] | units.stellar_type +stellar_types_dr = [ + 2, + 4, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, +] | units.stellar_type # stars which go through a instantaneous radius change at formation; hertzsprung gap stars (small envelope perturbation) + horizontal branch stars + remnants + + +# q_crit = 3. +# q_crit_giants_conv_env = 0.9 +nucleair_efficiency = 0.007 # nuc. energy production eff, Delta E = 0.007 Mc^2 + + +# dictionaries +bin_type = { + "unknown": "unknown", + "merger": "merger", + "disintegrated": "disintegrated", + "dyn_inst": "dynamical_instability", + "detached": "detached", + "contact": "contact", + "collision": "collision", + "semisecular": "semisecular", + "rlof": "rlof", # only used for stopping conditions + "olof": "olof", # only used for stopping conditions + "stable_mass_transfer": "stable_mass_transfer", + "common_envelope": "common_envelope", + "common_envelope_energy_balance": "common_envelope_energy_balance", + "common_envelope_angular_momentum_balance": "common_envelope_angular_momentum_balance", + "double_common_envelope": "double_common_envelope", +} + + +# ------------------------- +# general functions def roche_radius_dimensionless(M, m): # Assure that the q is calculated in identical units. unit = M.unit # and that q itself has no unit - q = M.value_in(unit)/m.value_in(unit) - q13 = q**(1./3.) - q23 = q13**2 - return 0.49*q23/(0.6*q23 + np.log(1 + q13)) + q = M.value_in(unit) / m.value_in(unit) + q13 = q ** (1.0 / 3.0) + q23 = q13**2 + return 0.49 * q23 / (0.6 * q23 + np.log(1 + q13)) + def roche_radius(bin, primary, self): if not bin.is_star and primary.is_star: - return bin.semimajor_axis * roche_radius_dimensionless(primary.mass, self.get_mass(bin)-primary.mass) + return bin.semimajor_axis * roche_radius_dimensionless( + primary.mass, self.get_mass(bin) - primary.mass + ) + + sys.exit("error in roche radius: Roche radius can only be determined in a binary") - sys.exit('error in roche radius: Roche radius can only be determined in a binary') -def L2_radius_dimensionless(M,m): +def L2_radius_dimensionless(M, m): # approximation for l2 overflow # see Marchant+ 2016 equation 2 - q = M/m + q = M / m rl1 = roche_radius_dimensionless(M, m) - rl2_div_rl1 = 0.299 * np.arctan(1.83*q**0.397) + 1 + rl2_div_rl1 = 0.299 * np.arctan(1.83 * q**0.397) + 1 return rl2_div_rl1 * rl1 + def L2_radius(bin, primary, self): # note: this prescription is based on the Eggleton approximation for how to adjust a circular RL to an eccentric one # may not be consistent with Sepinsky's method for eccentric RL (L1) if not bin.is_star and primary.is_star: - return bin.semimajor_axis * L2_radius_dimensionless(primary.mass, self.get_mass(bin)-primary.mass)*(1-bin.eccentricity) - sys.exit('Error: L2 radius can only be determined in a binary') + return ( + bin.semimajor_axis + * L2_radius_dimensionless(primary.mass, self.get_mass(bin) - primary.mass) + * (1 - bin.eccentricity) + ) + sys.exit("Error: L2 radius can only be determined in a binary") + -#for comparison with kozai timescale +# for comparison with kozai timescale def stellar_evolution_timescale(star): if REPORT_FUNCTION_NAMES: print("Stellar evolution timescale") - - if star.stellar_type in [0,1,7]|units.stellar_type: - return (0.1 * star.mass * nucleair_efficiency * constants.c**2 / star.luminosity).in_(units.Gyr) - elif star.stellar_type in stellar_types_compact_objects: - return np.inf|units.Myr - elif star.stellar_type in stellar_types_planetary_objects: - return np.inf|units.Myr - else: - return 0.1*star.age + + if star.stellar_type in [0, 1, 7] | units.stellar_type: + return ( + 0.1 * star.mass * nucleair_efficiency * constants.c**2 / star.luminosity + ).in_(units.Gyr) + if star.stellar_type in stellar_types_compact_objects: + return np.inf | units.Myr + if star.stellar_type in stellar_types_planetary_objects: + return np.inf | units.Myr + return 0.1 * star.age -#for mass transfer rate +# for mass transfer rate def nuclear_evolution_timescale(star): if REPORT_FUNCTION_NAMES: print("Nuclear evolution timescale:") - - if star.stellar_type in [0,1,7]|units.stellar_type: - return (0.1 * star.mass * nucleair_efficiency * constants.c**2 / star.luminosity).in_(units.Gyr) - elif star.stellar_type in stellar_types_planetary_objects: -# print('nuclear evolution timescale for planetary objects requested') -# return np.inf|units.Myr + + if star.stellar_type in [0, 1, 7] | units.stellar_type: + return ( + 0.1 * star.mass * nucleair_efficiency * constants.c**2 / star.luminosity + ).in_(units.Gyr) + if star.stellar_type in stellar_types_planetary_objects: + # print('nuclear evolution timescale for planetary objects requested') + # return np.inf | units.Myr return dynamic_timescale(star) - else: #t_nuc ~ delta t * R/ delta R, other prescription gave long timescales in SeBa which destables the mass transfer - if star.time_derivative_of_radius <= (quantities.zero+numerical_error**2)|units.RSun/units.yr: - #when star is shrinking -# t_nuc = 0.1*main_sequence_time() # in SeBa - t_nuc = 0.1*star.age - else: - t_nuc = star.radius / star.time_derivative_of_radius #does not include the effect of mass loss on R + # t_nuc ~ delta t * R/ delta R, other prescription gave long timescales in + # SeBa which destables the mass transfer + if ( + star.time_derivative_of_radius + <= (quantities.zero + numerical_error**2) | units.RSun / units.yr + ): + # when star is shrinking + # t_nuc = 0.1*main_sequence_time() # in SeBa + t_nuc = 0.1 * star.age + else: + t_nuc = ( + star.radius / star.time_derivative_of_radius + ) # does not include the effect of mass loss on R + + return t_nuc - return t_nuc def kelvin_helmholds_timescale(star): if star.stellar_type in stellar_types_planetary_objects: -# print('thermal evolution timescale for planetary objects requested') + # print('thermal evolution timescale for planetary objects requested') return dynamic_timescale(star) if REPORT_FUNCTION_NAMES: - print("KH timescale:", (constants.G*star.mass**2/star.radius/star.luminosity).in_(units.Myr)) - return constants.G*star.mass**2/star.radius/star.luminosity + print( + "KH timescale:", + (constants.G * star.mass**2 / star.radius / star.luminosity).in_(units.Myr), + ) + return constants.G * star.mass**2 / star.radius / star.luminosity + def dynamic_timescale(star): if REPORT_FUNCTION_NAMES: - print("Dynamic timescale:", (np.sqrt(star.radius**3/star.mass/constants.G)[0]).in_(units.yr)) - return np.sqrt(star.radius**3/star.mass/constants.G) - + print( + "Dynamic timescale:", + (np.sqrt(star.radius**3 / star.mass / constants.G)[0]).in_(units.yr), + ) + return np.sqrt(star.radius**3 / star.mass / constants.G) + + def corotating_spin_angular_frequency_binary(semi, m1, m2): - return 1./np.sqrt(semi**3/constants.G / (m1+m2)) + return 1.0 / np.sqrt(semi**3 / constants.G / (m1 + m2)) + -#Hurley, Pols en Tout 2000, eq 107-108 +# Hurley, Pols en Tout 2000, eq 107-108 def lang_spin_angular_frequency(star): - v_rot = 330*star.mass.value_in(units.MSun)**3.3/(15.0+star.mass.value_in(units.MSun)**3.45) - w = 45.35 * v_rot/star.radius.value_in(units.RSun) - return w|1./units.yr + v_rot = ( + 330 + * star.mass.value_in(units.MSun) ** 3.3 + / (15.0 + star.mass.value_in(units.MSun) ** 3.45) + ) + w = 45.35 * v_rot / star.radius.value_in(units.RSun) + return w | 1.0 / units.yr + def break_up_angular_frequency(object): - return np.sqrt( constants.G * object.mass / object.radius ) / object.radius + return np.sqrt(constants.G * object.mass / object.radius) / object.radius def criticial_angular_frequency_CHE(m, Z): - #angular frequency of spin for CHE threshold - #Fitting formula for CHE from Riley+ 2021 - - a_coeff = np.array([5.7914 * 10 ** - 4, -1.9196 * 10 ** - 6, - -4.0602 * 10 ** - 7, 1.0150 * 10 ** - 8, - -9.1792 * 10 ** - 11, 2.9051 * 10 ** - 13]) - mass_power = np.linspace(0,5,6) - omega_at_z_0d004 = np.sum(a_coeff * m.value_in(units.MSun)** mass_power / m.value_in(units.MSun) ** 0.4) - omega_crit = omega_at_z_0d004/(0.09 * np.log(Z/0.004) + 1) |1./units.s + # angular frequency of spin for CHE threshold + # Fitting formula for CHE from Riley+ 2021 + + a_coeff = np.array( + [ + 5.7914 * 10**-4, + -1.9196 * 10**-6, + -4.0602 * 10**-7, + 1.0150 * 10**-8, + -9.1792 * 10**-11, + 2.9051 * 10**-13, + ] + ) + mass_power = np.linspace(0, 5, 6) + omega_at_z_0d004 = np.sum( + a_coeff * m.value_in(units.MSun) ** mass_power / m.value_in(units.MSun) ** 0.4 + ) + omega_crit = omega_at_z_0d004 / (0.09 * np.log(Z / 0.004) + 1) | 1.0 / units.s return omega_crit def copy_outer_orbit_to_inner_orbit(bs, self): if REPORT_FUNCTION_NAMES: - print('Copy_outer_orbit_to_inner_orbit') + print("Copy_outer_orbit_to_inner_orbit") if self.is_triple(): bs.semimajor_axis = self.triple.semimajor_axis @@ -172,49 +233,55 @@ def copy_outer_orbit_to_inner_orbit(bs, self): bs.argument_of_pericenter = self.triple.argument_of_pericenter bs.longitude_of_ascending_node = self.triple.longitude_of_ascending_node bs.mass_transfer_rate = self.triple.mass_transfer_rate - bs.accretion_efficiency_mass_transfer, = self.triple.accretion_efficiency_mass_transfer, - bs.accretion_efficiency_wind_child1_to_child2, = self.triple.accretion_efficiency_wind_child1_to_child2, - bs.accretion_efficiency_wind_child2_to_child1, = self.triple.accretion_efficiency_wind_child2_to_child1, - bs.specific_AM_loss_mass_transfer, = self.triple.specific_AM_loss_mass_transfer, + (bs.accretion_efficiency_mass_transfer,) = ( + self.triple.accretion_efficiency_mass_transfer, + ) + (bs.accretion_efficiency_wind_child1_to_child2,) = ( + self.triple.accretion_efficiency_wind_child1_to_child2, + ) + (bs.accretion_efficiency_wind_child2_to_child1,) = ( + self.triple.accretion_efficiency_wind_child2_to_child1, + ) + (bs.specific_AM_loss_mass_transfer,) = ( + self.triple.specific_AM_loss_mass_transfer, + ) bs.is_mt_stable = self.triple.is_mt_stable - - self.triple.semimajor_axis = 1e100|units.RSun + + self.triple.semimajor_axis = 1e100 | units.RSun self.triple.eccentricity = 0 - - - - + + def copy_outer_star_to_accretor(self): if REPORT_FUNCTION_NAMES: - print('Copy_outer_star_to_accretor') + print("Copy_outer_star_to_accretor") - if self.is_triple(): + if self.is_triple(): if self.triple.child1.is_star: tertiary_star = self.triple.child1 bs = self.triple.child2 else: - tertiary_star = self.triple.child2 + tertiary_star = self.triple.child2 bs = self.triple.child1 - if not bs.child1.is_donor: bs.child1 = tertiary_star else: bs.child2 = tertiary_star - -#------------------------- -#------------------------- +# ------------------------- + +# ------------------------- # functions for mass transfer in a binary + def perform_inner_collision(self): if self.is_triple(): if self.triple.child1.is_star: self.triple.child2 else: self.triple.child1 - + # smaller star is added to big star if bs.child1.radius >= bs.child2.radius: donor = bs.child1 @@ -222,114 +289,151 @@ def perform_inner_collision(self): else: donor = bs.child2 accretor = bs.child1 - - donor_in_stellar_code = donor.as_set().get_intersecting_subset_in(self.stellar_code.particles)[0] - accretor_in_stellar_code = accretor.as_set().get_intersecting_subset_in(self.stellar_code.particles)[0] - - #no additional mass and Jspin loss from merged object for now + + donor_in_stellar_code = donor.as_set().get_intersecting_subset_in( + self.stellar_code.particles + )[0] + accretor_in_stellar_code = accretor.as_set().get_intersecting_subset_in( + self.stellar_code.particles + )[0] + + # no additional mass and Jspin loss from merged object for now J_spin_donor_previous = self.spin_angular_momentum(donor) J_spin_accretor_previous = self.spin_angular_momentum(accretor) J_orbit = self.orbital_angular_momentum(bs) J_spin_new = J_spin_donor_previous + J_spin_accretor_previous + J_orbit - - #merger - donor_in_stellar_code.merge_with_other_star(accretor_in_stellar_code) + + # merger + donor_in_stellar_code.merge_with_other_star(accretor_in_stellar_code) self.copy_from_stellar() - - donor.moment_of_inertia_of_star = self.moment_of_inertia(donor) - - #assuming conservation of total angular momentum of the inner binary - spin_angular_frequency = J_spin_new / donor.moment_of_inertia_of_star - critical_spin_angular_frequency = np.sqrt(constants.G * donor.mass/donor.radius**3) - donor.spin_angular_frequency = min(donor.spin_angular_frequency, critical_spin_angular_frequency) + + donor.moment_of_inertia_of_star = self.moment_of_inertia(donor) + + # assuming conservation of total angular momentum of the inner binary + spin_angular_frequency = J_spin_new / donor.moment_of_inertia_of_star + critical_spin_angular_frequency = np.sqrt( + constants.G * donor.mass / donor.radius**3 + ) + donor.spin_angular_frequency = min( + donor.spin_angular_frequency, critical_spin_angular_frequency + ) self.stellar_code.particles.remove_particle(accretor) - accretor.mass = 0|units.MSun # necessary for adjust_system_after_ce_in_inner_binary - #adjust outer orbit, needs to be before the system becomes a binary - #and copy to inner orbit + accretor.mass = ( + 0 | units.MSun + ) # necessary for adjust_system_after_ce_in_inner_binary + # adjust outer orbit, needs to be before the system becomes a binary + # and copy to inner orbit # weird structure necessary for secular code -> outer orbit is redundant - adjust_system_after_ce_in_inner_binary(bs, self) + adjust_system_after_ce_in_inner_binary(bs, self) copy_outer_orbit_to_inner_orbit(bs, self) copy_outer_star_to_accretor(self) - #functions are skipped in binaries, needs to be checked if this works well - + # functions are skipped in binaries, needs to be checked if this works well + self.secular_code.parameters.ignore_tertiary = True self.secular_code.parameters.check_for_dynamical_stability = False self.secular_code.parameters.check_for_outer_collision = False self.secular_code.parameters.check_for_outer_RLOF = False - bs.bin_type = bin_type['collision'] - self.save_snapshot() # just to note that it the system has merged + bs.bin_type = bin_type["collision"] + self.save_snapshot() # just to note that it the system has merged + + # use of stopping condition in this way (similar to perform inner merger) is not necessary. + # TRES.py takes care of it + # if self.check_stopping_conditions_stellar_interaction()==False: + # print('stopping conditions stellar interaction') + # return False -#use of stopping condition in this way (similar to perform inner merger) is not necessary. -#TRES.py takes care of it -# if self.check_stopping_conditions_stellar_interaction()==False: -# print('stopping conditions stellar interaction') -# return False - - self.check_RLOF() + self.check_RLOF() if self.has_donor(): - print(self.triple.child2.child1.mass, self.triple.child2.child2.mass, self.triple.child2.semimajor_axis, self.triple.child2.eccentricity, self.triple.child2.child1.is_donor, self.triple.child2.child2.is_donor) - print(self.triple.child1.mass, self.triple.semimajor_axis, self.triple.eccentricity, self.triple.child1.is_donor) + print( + self.triple.child2.child1.mass, + self.triple.child2.child2.mass, + self.triple.child2.semimajor_axis, + self.triple.child2.eccentricity, + self.triple.child2.child1.is_donor, + self.triple.child2.child2.is_donor, + ) + print( + self.triple.child1.mass, + self.triple.semimajor_axis, + self.triple.eccentricity, + self.triple.child1.is_donor, + ) sys.exit("error in adjusting triple after collision: RLOF") - + donor.is_donor = False bs.is_mt_stable = True - bs.bin_type = bin_type['detached'] + bs.bin_type = bin_type["detached"] + + donor.spin_angular_frequency = corotating_spin_angular_frequency_binary( + bs.semimajor_axis, bs.child1.mass, bs.child2.mass + ) + + +# use of stopping condition in this way (similar to perform inner merger) is not necessary +# TRES.py takes care of it +# return True - donor.spin_angular_frequency = corotating_spin_angular_frequency_binary(bs.semimajor_axis, bs.child1.mass, bs.child2.mass) -#use of stopping condition in this way (similar to perform inner merger) is not necessary -#TRES.py takes care of it -# return True - def perform_inner_merger(bs, donor, accretor, self): if REPORT_BINARY_EVOLUTION: - print('Merger in inner binary through common envelope phase') + print("Merger in inner binary through common envelope phase") + + donor_in_stellar_code = donor.as_set().get_intersecting_subset_in( + self.stellar_code.particles + )[0] + accretor_in_stellar_code = accretor.as_set().get_intersecting_subset_in( + self.stellar_code.particles + )[0] - donor_in_stellar_code = donor.as_set().get_intersecting_subset_in(self.stellar_code.particles)[0] - accretor_in_stellar_code = accretor.as_set().get_intersecting_subset_in(self.stellar_code.particles)[0] - - #no additional mass and Jspin loss from merged object for now + # no additional mass and Jspin loss from merged object for now J_spin_donor_previous = self.spin_angular_momentum(donor) J_spin_accretor_previous = self.spin_angular_momentum(accretor) J_orbit = self.orbital_angular_momentum(bs) J_spin_new = J_spin_donor_previous + J_spin_accretor_previous + J_orbit - - #merger - donor_in_stellar_code.merge_with_other_star(accretor_in_stellar_code) + + # merger + donor_in_stellar_code.merge_with_other_star(accretor_in_stellar_code) self.copy_from_stellar() - - donor.moment_of_inertia_of_star = self.moment_of_inertia(donor) - - #assuming conservation of total angular momentum of the inner binary - spin_angular_momentum = J_spin_new / donor.moment_of_inertia_of_star - critical_spin_angular_frequency = np.sqrt(constants.G * donor.mass/donor.radius**3) - donor.spin_angular_frequency = min(donor.spin_angular_frequency, critical_spin_angular_frequency) - + + donor.moment_of_inertia_of_star = self.moment_of_inertia(donor) + + # assuming conservation of total angular momentum of the inner binary + spin_angular_momentum = J_spin_new / donor.moment_of_inertia_of_star + critical_spin_angular_frequency = np.sqrt( + constants.G * donor.mass / donor.radius**3 + ) + donor.spin_angular_frequency = min( + donor.spin_angular_frequency, critical_spin_angular_frequency + ) + self.stellar_code.particles.remove_particle(accretor) - accretor.mass = 0|units.MSun # necessary for adjust_system_after_ce_in_inner_binary - #adjust outer orbit, needs to be before the system becomes a binary - #and copy to inner orbit + accretor.mass = ( + 0 | units.MSun + ) # necessary for adjust_system_after_ce_in_inner_binary + # adjust outer orbit, needs to be before the system becomes a binary + # and copy to inner orbit # weird structure necessary for secular code -> outer orbit is redundant - adjust_system_after_ce_in_inner_binary(bs, self) + adjust_system_after_ce_in_inner_binary(bs, self) copy_outer_orbit_to_inner_orbit(bs, self) copy_outer_star_to_accretor(self) - #functions are skipped in binaries, needs to be checked if this works well - + # functions are skipped in binaries, needs to be checked if this works well + self.secular_code.parameters.ignore_tertiary = True self.secular_code.parameters.check_for_dynamical_stability = False self.secular_code.parameters.check_for_outer_collision = False self.secular_code.parameters.check_for_outer_RLOF = False - bs.bin_type = bin_type['merger'] - self.save_snapshot() # just to note that the system has merged + bs.bin_type = bin_type["merger"] + self.save_snapshot() # just to note that the system has merged - if self.check_stopping_conditions_stellar_interaction()==False: - print('stopping conditions stellar interaction') + if self.check_stopping_conditions_stellar_interaction() == False: + print("stopping conditions stellar interaction") return False - else: - return True - + else: + return True + + # print(self.secular_code.give_roche_radii(self.triple),) # print(roche_radius(self.triple.child2, self.triple.child2.child1, self), roche_radius(self.triple.child2, self.triple.child2.child2, self)) # @@ -337,367 +441,515 @@ def perform_inner_merger(bs, donor, accretor, self): # donor.spin_angular_frequency = corotating_spin_angular_frequency_binary(bs.semimajor_axis, bs.child1.mass, bs.child2.mass) - def common_envelope_efficiency(donor, accretor): return const_common_envelope_efficiency + def envelope_structure_parameter(donor): return const_envelope_structure_parameter - + + def common_envelope_efficiency_gamma(donor, accretor): return const_common_envelope_efficiency_gamma - - + # ang.mom balance: \Delta J = \gamma * J * \Delta M / M # See Eq. 5 of Nelemans VYPZ 2000, 360, 1011 A&A def common_envelope_angular_momentum_balance(bs, donor, accretor, self): if REPORT_FUNCTION_NAMES: - print('Common envelope angular momentum balance') + print("Common envelope angular momentum balance") if REPORT_BINARY_EVOLUTION: if bs.eccentricity > 0.05: - print('gamma common envelope in eccentric binary') - print('Before common envelope angular momentum balance' ) - self.print_binary(bs) + print("gamma common envelope in eccentric binary") + print("Before common envelope angular momentum balance") + self.print_binary(bs) - bs.bin_type = bin_type['common_envelope_angular_momentum_balance'] - self.save_snapshot() + bs.bin_type = bin_type["common_envelope_angular_momentum_balance"] + self.save_snapshot() gamma = common_envelope_efficiency_gamma(donor, accretor) - J_init = np.sqrt(bs.semimajor_axis) * (donor.mass * accretor.mass) / np.sqrt(donor.mass + accretor.mass) * np.sqrt(1-bs.eccentricity**2) - J_f_over_sqrt_a_new = (donor.core_mass * accretor.mass) / np.sqrt(donor.core_mass + accretor.mass) - J_lost = gamma * (donor.mass-donor.core_mass) * J_init/(donor.mass + accretor.mass) - sqrt_a_new = max(0.|units.RSun**0.5, (J_init -J_lost)/J_f_over_sqrt_a_new) + J_init = ( + np.sqrt(bs.semimajor_axis) + * (donor.mass * accretor.mass) + / np.sqrt(donor.mass + accretor.mass) + * np.sqrt(1 - bs.eccentricity**2) + ) + J_f_over_sqrt_a_new = (donor.core_mass * accretor.mass) / np.sqrt( + donor.core_mass + accretor.mass + ) + J_lost = ( + gamma * (donor.mass - donor.core_mass) * J_init / (donor.mass + accretor.mass) + ) + sqrt_a_new = max(0.0 | units.RSun**0.5, (J_init - J_lost) / J_f_over_sqrt_a_new) a_new = pow(sqrt_a_new, 2) - Rl_donor_new = roche_radius_dimensionless(donor.core_mass, accretor.mass)*a_new - Rl_accretor_new = roche_radius_dimensionless(accretor.mass, donor.core_mass)*a_new + Rl_donor_new = roche_radius_dimensionless(donor.core_mass, accretor.mass) * a_new + Rl_accretor_new = roche_radius_dimensionless(accretor.mass, donor.core_mass) * a_new if REPORT_BINARY_EVOLUTION: - print('donor:', donor.radius, donor.core_radius, Rl_donor_new) - print('accretor:', accretor.radius, accretor.core_radius, Rl_accretor_new) - + print("donor:", donor.radius, donor.core_radius, Rl_donor_new) + print("accretor:", accretor.radius, accretor.core_radius, Rl_accretor_new) + if (donor.core_radius > Rl_donor_new) or (accretor.radius > Rl_accretor_new): stopping_condition = perform_inner_merger(bs, donor, accretor, self) - if not stopping_condition: #stellar interaction - return False + if not stopping_condition: # stellar interaction + return False else: - donor_in_stellar_code = donor.as_set().get_intersecting_subset_in(self.stellar_code.particles)[0] - #reduce_mass not subtrac mass, want geen adjust_donor_radius - #check if star changes type - donor_in_stellar_code.change_mass(-1*(donor.mass-donor.core_mass+(small_numerical_error|units.MSun)), 0.|units.yr) + donor_in_stellar_code = donor.as_set().get_intersecting_subset_in( + self.stellar_code.particles + )[0] + # reduce_mass not subtrac mass, want geen adjust_donor_radius + # check if star changes type + donor_in_stellar_code.change_mass( + -1 * (donor.mass - donor.core_mass + (small_numerical_error | units.MSun)), + 0.0 | units.yr, + ) self.copy_from_stellar() - - donor.moment_of_inertia_of_star = self.moment_of_inertia(donor) - accretor.moment_of_inertia_of_star = self.moment_of_inertia(accretor) + + donor.moment_of_inertia_of_star = self.moment_of_inertia(donor) + accretor.moment_of_inertia_of_star = self.moment_of_inertia(accretor) bs.semimajor_axis = a_new bs.eccentricity = minimum_eccentricity - #set to synchronization - corotating_frequency = corotating_spin_angular_frequency_binary(a_new, donor.mass, accretor.mass) + # set to synchronization + corotating_frequency = corotating_spin_angular_frequency_binary( + a_new, donor.mass, accretor.mass + ) donor.spin_angular_frequency = corotating_frequency accretor.spin_angular_frequency = corotating_frequency - - self.check_RLOF() - if self.has_donor(): - print(self.triple.child2.child1.mass, self.triple.child2.child2.mass, self.triple.child2.child1.radius, self.triple.child2.child2.radius,self.triple.child2.semimajor_axis, self.triple.child2.eccentricity, self.triple.child2.child1.is_donor, self.triple.child2.child2.is_donor) - print(self.triple.child2.child1.core_mass, self.triple.child2.child1.mass-self.triple.child2.child1.core_mass, self.triple.child2.child1.stellar_type) - print(self.triple.child1.mass, self.triple.semimajor_axis, self.triple.eccentricity, self.triple.child1.is_donor) -# sys.exit("error in adjusting triple after gamma CE: RLOF") + self.check_RLOF() + if self.has_donor(): + print( + self.triple.child2.child1.mass, + self.triple.child2.child2.mass, + self.triple.child2.child1.radius, + self.triple.child2.child2.radius, + self.triple.child2.semimajor_axis, + self.triple.child2.eccentricity, + self.triple.child2.child1.is_donor, + self.triple.child2.child2.is_donor, + ) + print( + self.triple.child2.child1.core_mass, + self.triple.child2.child1.mass - self.triple.child2.child1.core_mass, + self.triple.child2.child1.stellar_type, + ) + print( + self.triple.child1.mass, + self.triple.semimajor_axis, + self.triple.eccentricity, + self.triple.child1.is_donor, + ) + + # sys.exit("error in adjusting triple after gamma CE: RLOF") stopping_condition = perform_inner_merger(bs, donor, accretor, self) - if not stopping_condition: #stellar interaction + if not stopping_condition: # stellar interaction return False -# adjusting of stellar system -# in previous case of merger, the adjustment is done there as mass may be lost during the merger - adjust_system_after_ce_in_inner_binary(bs, self) - + # adjusting of stellar system + # in previous case of merger, the adjustment is done there as mass may be lost during the merger + adjust_system_after_ce_in_inner_binary(bs, self) - donor.is_donor = False bs.is_mt_stable = True - bs.bin_type = bin_type['detached'] - self.instantaneous_evolution = True #skip secular evolution - + bs.bin_type = bin_type["detached"] + self.instantaneous_evolution = True # skip secular evolution + return True - -#Following Webbink 1984 + + +# Following Webbink 1984 def common_envelope_energy_balance(bs, donor, accretor, self): if REPORT_FUNCTION_NAMES: - print('Common envelope energy balance') + print("Common envelope energy balance") if REPORT_BINARY_EVOLUTION: - print('Before common envelope energy balance' ) - self.print_binary(bs) + print("Before common envelope energy balance") + self.print_binary(bs) - bs.bin_type = bin_type['common_envelope_energy_balance'] - self.save_snapshot() + bs.bin_type = bin_type["common_envelope_energy_balance"] + self.save_snapshot() - alpha = common_envelope_efficiency(donor, accretor) + alpha = common_envelope_efficiency(donor, accretor) lambda_donor = envelope_structure_parameter(donor) Rl_donor = roche_radius(bs, donor, self) donor_radius = min(donor.radius, Rl_donor) - #based on Glanz & Perets 2021 2021MNRAS.507.2659G - #eccentric CE -> end result depends on pericenter distance more than semi-major axis - pericenter_init = bs.semimajor_axis * (1-bs.eccentricity) - orb_energy_new = donor.mass * (donor.mass-donor.core_mass) / (alpha * lambda_donor * donor_radius) + donor.mass * accretor.mass/2/pericenter_init + # based on Glanz & Perets 2021 2021MNRAS.507.2659G + # eccentric CE -> end result depends on pericenter distance more than semi-major axis + pericenter_init = bs.semimajor_axis * (1 - bs.eccentricity) + orb_energy_new = ( + donor.mass + * (donor.mass - donor.core_mass) + / (alpha * lambda_donor * donor_radius) + + donor.mass * accretor.mass / 2 / pericenter_init + ) a_new = donor.core_mass * accretor.mass / 2 / orb_energy_new -# a_new = bs.semimajor_axis * (donor.core_mass/donor.mass) / (1. + (2.*(donor.mass-donor.core_mass)*bs.semimajor_axis/(alpha_lambda*donor_radius*accretor.mass))) - - Rl_donor_new = roche_radius_dimensionless(donor.core_mass, accretor.mass)*a_new - Rl_accretor_new = roche_radius_dimensionless(accretor.mass, donor.core_mass)*a_new + # a_new = bs.semimajor_axis * (donor.core_mass/donor.mass) / (1. + (2.*(donor.mass-donor.core_mass)*bs.semimajor_axis/(alpha_lambda*donor_radius*accretor.mass))) + + Rl_donor_new = roche_radius_dimensionless(donor.core_mass, accretor.mass) * a_new + Rl_accretor_new = roche_radius_dimensionless(accretor.mass, donor.core_mass) * a_new if REPORT_BINARY_EVOLUTION: - print('donor:', donor.radius, donor.core_radius, Rl_donor_new) - print('accretor:', accretor.radius, accretor.core_radius, Rl_accretor_new) - + print("donor:", donor.radius, donor.core_radius, Rl_donor_new) + print("accretor:", accretor.radius, accretor.core_radius, Rl_accretor_new) + if (donor.core_radius > Rl_donor_new) or (accretor.radius > Rl_accretor_new): stopping_condition = perform_inner_merger(bs, donor, accretor, self) - if not stopping_condition: #stellar interaction - return False + if not stopping_condition: # stellar interaction + return False else: - donor_in_stellar_code = donor.as_set().get_intersecting_subset_in(self.stellar_code.particles)[0] - #reduce_mass not subtrac mass, want geen adjust_donor_radius - #check if star changes type - donor_in_stellar_code.change_mass(-1*(donor.mass-donor.core_mass+(small_numerical_error|units.MSun)), 0.|units.yr) + donor_in_stellar_code = donor.as_set().get_intersecting_subset_in( + self.stellar_code.particles + )[0] + # reduce_mass not subtrac mass, want geen adjust_donor_radius + # check if star changes type + donor_in_stellar_code.change_mass( + -1 * (donor.mass - donor.core_mass + (small_numerical_error | units.MSun)), + 0.0 | units.yr, + ) self.copy_from_stellar() - donor.moment_of_inertia_of_star = self.moment_of_inertia(donor) - accretor.moment_of_inertia_of_star = self.moment_of_inertia(accretor) + donor.moment_of_inertia_of_star = self.moment_of_inertia(donor) + accretor.moment_of_inertia_of_star = self.moment_of_inertia(accretor) bs.semimajor_axis = a_new bs.eccentricity = minimum_eccentricity - #set to synchronization - corotating_frequency = corotating_spin_angular_frequency_binary(a_new, donor.mass, accretor.mass) + # set to synchronization + corotating_frequency = corotating_spin_angular_frequency_binary( + a_new, donor.mass, accretor.mass + ) donor.spin_angular_frequency = corotating_frequency accretor.spin_angular_frequency = corotating_frequency - - self.check_RLOF() + self.check_RLOF() if self.has_donor(): - print(self.triple.child2.child1.mass, self.triple.child2.child2.mass, self.triple.child2.semimajor_axis, self.triple.child2.eccentricity, self.triple.child2.child1.is_donor, self.triple.child2.child2.is_donor) - print(self.triple.child1.mass, self.triple.semimajor_axis, self.triple.eccentricity, self.triple.child1.is_donor) - - # sys.exit("error in adjusting triple after alpha CE: RLOF") + print( + self.triple.child2.child1.mass, + self.triple.child2.child2.mass, + self.triple.child2.semimajor_axis, + self.triple.child2.eccentricity, + self.triple.child2.child1.is_donor, + self.triple.child2.child2.is_donor, + ) + print( + self.triple.child1.mass, + self.triple.semimajor_axis, + self.triple.eccentricity, + self.triple.child1.is_donor, + ) + + # sys.exit("error in adjusting triple after alpha CE: RLOF") stopping_condition = perform_inner_merger(bs, donor, accretor, self) - if not stopping_condition: #stellar interaction - return False + if not stopping_condition: # stellar interaction + return False + + # adjusting of stellar system + # in previous case of merger, the adjustment is done there as mass may be lost during the merger + adjust_system_after_ce_in_inner_binary(bs, self) -# adjusting of stellar system -# in previous case of merger, the adjustment is done there as mass may be lost during the merger - adjust_system_after_ce_in_inner_binary(bs, self) - donor.is_donor = False bs.is_mt_stable = True - bs.bin_type = bin_type['detached'] - self.instantaneous_evolution = True #skip secular evolution + bs.bin_type = bin_type["detached"] + self.instantaneous_evolution = True # skip secular evolution return True + # See appendix of Nelemans YPZV 2001, 365, 491 A&A def double_common_envelope_energy_balance(bs, donor, accretor, self): if REPORT_FUNCTION_NAMES: - print('Double common envelope energy balance') + print("Double common envelope energy balance") if REPORT_BINARY_EVOLUTION: - print('Before double common envelope energy balance' ) - self.print_binary(bs) + print("Before double common envelope energy balance") + self.print_binary(bs) - bs.bin_type = bin_type['double_common_envelope'] - self.save_snapshot() + bs.bin_type = bin_type["double_common_envelope"] + self.save_snapshot() alpha = common_envelope_efficiency(donor, accretor) - lambda_donor = envelope_structure_parameter(donor) + lambda_donor = envelope_structure_parameter(donor) lambda_accretor = envelope_structure_parameter(accretor) Rl_donor = roche_radius(bs, donor, self) donor_radius = min(donor.radius, Rl_donor) accretor_radius = accretor.radius - - - #based on Glanz & Perets 2021 2021MNRAS.507.2659G - #eccentric CE -> end result depends on pericenter distance more than semi-major axis - pericenter_init = bs.semimajor_axis * (1-bs.eccentricity) - orb_energy_new = donor.mass * (donor.mass-donor.core_mass) / (alpha * lambda_donor * donor_radius) + accretor.mass * (accretor.mass-accretor.core_mass) / (alpha * lambda_accretor * accretor_radius) + donor.mass * accretor.mass/2/pericenter_init + + # based on Glanz & Perets 2021 2021MNRAS.507.2659G + # eccentric CE -> end result depends on pericenter distance more than semi-major axis + pericenter_init = bs.semimajor_axis * (1 - bs.eccentricity) + orb_energy_new = ( + donor.mass + * (donor.mass - donor.core_mass) + / (alpha * lambda_donor * donor_radius) + + accretor.mass + * (accretor.mass - accretor.core_mass) + / (alpha * lambda_accretor * accretor_radius) + + donor.mass * accretor.mass / 2 / pericenter_init + ) a_new = donor.core_mass * accretor.core_mass / 2 / orb_energy_new - Rl_donor_new = roche_radius_dimensionless(donor.core_mass, accretor.core_mass)*a_new - Rl_accretor_new = roche_radius_dimensionless(accretor.core_mass, donor.core_mass)*a_new + Rl_donor_new = ( + roche_radius_dimensionless(donor.core_mass, accretor.core_mass) * a_new + ) + Rl_accretor_new = ( + roche_radius_dimensionless(accretor.core_mass, donor.core_mass) * a_new + ) if REPORT_BINARY_EVOLUTION: - print('donor:', donor.radius, donor.core_radius, Rl_donor_new) - print('accretor:', accretor.radius, accretor.core_radius, Rl_accretor_new) - + print("donor:", donor.radius, donor.core_radius, Rl_donor_new) + print("accretor:", accretor.radius, accretor.core_radius, Rl_accretor_new) + if (donor.core_radius > Rl_donor_new) or (accretor.core_radius > Rl_accretor_new): stopping_condition = perform_inner_merger(bs, donor, accretor, self) - if not stopping_condition: #stellar interaction - return False + if not stopping_condition: # stellar interaction + return False else: - #reduce_mass not subtrac mass, want geen adjust_donor_radius - #check if star changes type - - donor_in_stellar_code = donor.as_set().get_intersecting_subset_in(self.stellar_code.particles)[0] - donor_in_stellar_code.change_mass(-1*(donor.mass-donor.core_mass+(small_numerical_error|units.MSun)), 0.|units.yr) - accretor_in_stellar_code = accretor.as_set().get_intersecting_subset_in(self.stellar_code.particles)[0] - accretor_in_stellar_code.change_mass(-1*(accretor.mass-accretor.core_mass), 0.|units.yr) + # reduce_mass not subtrac mass, want geen adjust_donor_radius + # check if star changes type + + donor_in_stellar_code = donor.as_set().get_intersecting_subset_in( + self.stellar_code.particles + )[0] + donor_in_stellar_code.change_mass( + -1 * (donor.mass - donor.core_mass + (small_numerical_error | units.MSun)), + 0.0 | units.yr, + ) + accretor_in_stellar_code = accretor.as_set().get_intersecting_subset_in( + self.stellar_code.particles + )[0] + accretor_in_stellar_code.change_mass( + -1 * (accretor.mass - accretor.core_mass), 0.0 | units.yr + ) self.copy_from_stellar() - - donor.moment_of_inertia_of_star = self.moment_of_inertia(donor) - accretor.moment_of_inertia_of_star = self.moment_of_inertia(accretor) + donor.moment_of_inertia_of_star = self.moment_of_inertia(donor) + accretor.moment_of_inertia_of_star = self.moment_of_inertia(accretor) bs.semimajor_axis = a_new bs.eccentricity = minimum_eccentricity - #set to synchronization - corotating_frequency = corotating_spin_angular_frequency_binary(a_new, donor.mass, accretor.mass) + # set to synchronization + corotating_frequency = corotating_spin_angular_frequency_binary( + a_new, donor.mass, accretor.mass + ) donor.spin_angular_frequency = corotating_frequency accretor.spin_angular_frequency = corotating_frequency - self.check_RLOF() + self.check_RLOF() if self.has_donor(): - print(self.triple.child2.child1.mass, self.triple.child2.child2.mass, self.triple.child2.semimajor_axis, self.triple.child2.eccentricity, self.triple.child2.child1.is_donor, self.triple.child2.child2.is_donor) - print(self.triple.child1.mass, self.triple.semimajor_axis, self.triple.eccentricity, self.triple.child1.is_donor) - - # sys.exit("error in adjusting triple after double CE: RLOF") + print( + self.triple.child2.child1.mass, + self.triple.child2.child2.mass, + self.triple.child2.semimajor_axis, + self.triple.child2.eccentricity, + self.triple.child2.child1.is_donor, + self.triple.child2.child2.is_donor, + ) + print( + self.triple.child1.mass, + self.triple.semimajor_axis, + self.triple.eccentricity, + self.triple.child1.is_donor, + ) + + # sys.exit("error in adjusting triple after double CE: RLOF") stopping_condition = perform_inner_merger(bs, donor, accretor, self) - if not stopping_condition: #stellar interaction - return False + if not stopping_condition: # stellar interaction + return False -# adjusting of stellar system -# in previous case of merger, the adjustment is done there as mass may be lost during the merger - adjust_system_after_ce_in_inner_binary(bs, self) + # adjusting of stellar system + # in previous case of merger, the adjustment is done there as mass may be lost during the merger + adjust_system_after_ce_in_inner_binary(bs, self) donor.is_donor = False bs.is_mt_stable = True - bs.bin_type = bin_type['detached'] - self.instantaneous_evolution = True #skip secular evolution + bs.bin_type = bin_type["detached"] + self.instantaneous_evolution = True # skip secular evolution return True + def common_envelope_phase(bs, donor, accretor, self): stopping_condition = True - + if REPORT_FUNCTION_NAMES: - print('Common envelope phase', self.which_common_envelope) - print('donor:', donor.stellar_type) - print('accretor:', accretor.stellar_type) - - if donor.stellar_type not in stellar_types_giants and accretor.stellar_type not in stellar_types_giants: -# possible options: MS+MS, MS+remnant, remnant+remnant, -# HeMS+HeMS, HeMS+MS, HeMS+remnant - bs.bin_type = bin_type['common_envelope'] - self.save_snapshot() + print("Common envelope phase", self.which_common_envelope) + print("donor:", donor.stellar_type) + print("accretor:", accretor.stellar_type) + + if ( + donor.stellar_type not in stellar_types_giants + and accretor.stellar_type not in stellar_types_giants + ): + # possible options: MS+MS, MS+remnant, remnant+remnant, + # HeMS+HeMS, HeMS+MS, HeMS+remnant + bs.bin_type = bin_type["common_envelope"] + self.save_snapshot() stopping_condition = perform_inner_merger(bs, donor, accretor, self) - if not stopping_condition: #stellar interaction - return False + if not stopping_condition: # stellar interaction + return False - self.check_RLOF() + self.check_RLOF() if self.has_donor(): - print(self.triple.child2.child1.mass, self.triple.child2.child2.mass, self.triple.child2.semimajor_axis, self.triple.child2.eccentricity, self.triple.child2.child1.is_donor, self.triple.child2.child2.is_donor) - print(self.triple.child1.mass, self.triple.semimajor_axis, self.triple.eccentricity, self.triple.child1.is_donor) - print(self.triple.child2.child1.radius, self.triple.child2.child2.radius,self.triple.child1.radius) + print( + self.triple.child2.child1.mass, + self.triple.child2.child2.mass, + self.triple.child2.semimajor_axis, + self.triple.child2.eccentricity, + self.triple.child2.child1.is_donor, + self.triple.child2.child2.is_donor, + ) + print( + self.triple.child1.mass, + self.triple.semimajor_axis, + self.triple.eccentricity, + self.triple.child1.is_donor, + ) + print( + self.triple.child2.child1.radius, + self.triple.child2.child2.radius, + self.triple.child1.radius, + ) print(self.secular_code.give_roche_radii(self.triple)) - print('binary Roche lobe radii:', roche_radius(bs, bs.child1, self), roche_radius(bs, bs.child2, self)) + print( + "binary Roche lobe radii:", + roche_radius(bs, bs.child1, self), + roche_radius(bs, bs.child2, self), + ) -# sys.exit("error in adjusting system after CE: RLOF") + # sys.exit("error in adjusting system after CE: RLOF") stopping_condition = perform_inner_merger(bs, donor, accretor, self) - if not stopping_condition: #stellar interaction - return False - + if not stopping_condition: # stellar interaction + return False + donor.is_donor = False bs.is_mt_stable = True - bs.bin_type = bin_type['detached'] - self.instantaneous_evolution = True #skip secular evolution + bs.bin_type = bin_type["detached"] + self.instantaneous_evolution = True # skip secular evolution return True - - if self.which_common_envelope == 0: - if donor.stellar_type in stellar_types_giants and accretor.stellar_type in stellar_types_giants: - stopping_condition = double_common_envelope_energy_balance(bs, donor, accretor, self) + if ( + donor.stellar_type in stellar_types_giants + and accretor.stellar_type in stellar_types_giants + ): + stopping_condition = double_common_envelope_energy_balance( + bs, donor, accretor, self + ) else: - stopping_condition = common_envelope_energy_balance(bs, donor, accretor, self) + stopping_condition = common_envelope_energy_balance( + bs, donor, accretor, self + ) elif self.which_common_envelope == 1: - if donor.stellar_type in stellar_types_giants and accretor.stellar_type in stellar_types_giants: - stopping_condition = double_common_envelope_energy_balance(bs, donor, accretor, self) + if ( + donor.stellar_type in stellar_types_giants + and accretor.stellar_type in stellar_types_giants + ): + stopping_condition = double_common_envelope_energy_balance( + bs, donor, accretor, self + ) else: - stopping_condition = common_envelope_angular_momentum_balance(bs, donor, accretor, self) + stopping_condition = common_envelope_angular_momentum_balance( + bs, donor, accretor, self + ) elif self.which_common_envelope == 2: Js_d = self.spin_angular_momentum(donor) - Js_a = self.spin_angular_momentum(accretor) + Js_a = self.spin_angular_momentum(accretor) Jb = self.orbital_angular_momentum(bs) Js = max(Js_d, Js_a) -# print("Darwin Riemann instability? donor/accretor:", Js_d, Js_a, Jb, Jb/3.) - if donor.stellar_type in stellar_types_giants and accretor.stellar_type in stellar_types_giants: - #giant+giant - stopping_condition = double_common_envelope_energy_balance(bs, donor, accretor, self) - elif donor.stellar_type in stellar_types_compact_objects or accretor.stellar_type in stellar_types_compact_objects: - #giant+remnant - stopping_condition = common_envelope_energy_balance(bs, donor, accretor, self) - elif Js >= Jb/3. : - #darwin riemann instability - stopping_condition = common_envelope_energy_balance(bs, donor, accretor, self) + # print("Darwin Riemann instability? donor/accretor:", Js_d, Js_a, Jb, Jb/3.) + if ( + donor.stellar_type in stellar_types_giants + and accretor.stellar_type in stellar_types_giants + ): + # giant+giant + stopping_condition = double_common_envelope_energy_balance( + bs, donor, accretor, self + ) + elif ( + donor.stellar_type in stellar_types_compact_objects + or accretor.stellar_type in stellar_types_compact_objects + ): + # giant+remnant + stopping_condition = common_envelope_energy_balance( + bs, donor, accretor, self + ) + elif Js >= Jb / 3.0: + # darwin riemann instability + stopping_condition = common_envelope_energy_balance( + bs, donor, accretor, self + ) else: - #giant+normal(non-giant, non-remnant) - stopping_condition = common_envelope_angular_momentum_balance(bs, donor, accretor, self) + # giant+normal(non-giant, non-remnant) + stopping_condition = common_envelope_angular_momentum_balance( + bs, donor, accretor, self + ) return stopping_condition - + def adiabatic_expansion_due_to_mass_loss(a_i, Md_f, Md_i, Ma_f, Ma_i): - d_Md = Md_f - Md_i #negative mass loss rate - d_Ma = Ma_f - Ma_i #positive mass accretion rate + d_Md = Md_f - Md_i # negative mass loss rate + d_Ma = Ma_f - Ma_i # positive mass accretion rate Mt_f = Md_f + Ma_f Mt_i = Md_i + Ma_i - if d_Md < 0|units.MSun and d_Ma >= 0|units.MSun: + if d_Md < 0 | units.MSun and d_Ma >= 0 | units.MSun: eta = d_Ma / d_Md - a_f = a_i * ((Md_f/Md_i)**eta * (Ma_f/Ma_i))**-2 * Mt_i/Mt_f + a_f = a_i * ((Md_f / Md_i) ** eta * (Ma_f / Ma_i)) ** -2 * Mt_i / Mt_f return a_f return a_i - - + + def adjust_system_after_ce_in_inner_binary(bs, self): - # Assumption: Unstable mass transfer (common-envelope phase) in the inner binary, affects the outer binary as a wind. + # Assumption: Unstable mass transfer (common-envelope phase) in the inner binary, affects the outer binary as a wind. # Instanteneous effect if REPORT_FUNCTION_NAMES: - print('Adjust system after ce in inner binary') + print("Adjust system after ce in inner binary") if self.is_triple(): M_com_after_ce = self.get_mass(bs) M_com_before_ce = bs.previous_mass - + if self.triple.child1.is_star: tertiary_star = self.triple.child1 else: - tertiary_star = self.triple.child2 + tertiary_star = self.triple.child2 # accretion_efficiency - M_accretor_before_ce = tertiary_star.mass - M_accretor_after_ce = tertiary_star.mass - - a_new = adiabatic_expansion_due_to_mass_loss(self.triple.semimajor_axis, M_com_after_ce, M_com_before_ce, M_accretor_after_ce, M_accretor_before_ce) + M_accretor_before_ce = tertiary_star.mass + M_accretor_after_ce = tertiary_star.mass + + a_new = adiabatic_expansion_due_to_mass_loss( + self.triple.semimajor_axis, + M_com_after_ce, + M_com_before_ce, + M_accretor_after_ce, + M_accretor_before_ce, + ) self.triple.semimajor_axis = a_new + + # print('outer orbit', a_new) - -# nice but difficult to update self.triple + +# nice but difficult to update self.triple # system = bs # while True: -# try: +# try: # system = system.parent # if not system.child1.is_star and system.child2.is_star: -# system = adjust_triple_after_ce_in_inner_binary(system, system.child1, system.child2, self) +# system = adjust_triple_after_ce_in_inner_binary(system, system.child1, system.child2, self) # elif not system.child2.is_star and system.child1.is_star: -# system = adjust_triple_after_ce_in_inner_binary(system, system.child2, system.child1, self) +# system = adjust_triple_after_ce_in_inner_binary(system, system.child2, system.child1, self) # else: # print('adjust_system_after_ce_in_inner_binary: type of system unknown') # exit(2) -# +# # except AttributeError: # #when there is no parent # break @@ -705,15 +957,15 @@ def adjust_system_after_ce_in_inner_binary(bs, self): def stable_mass_transfer(bs, donor, accretor, self): - # orbital evolution is being taken into account in secular_code + # orbital evolution is being taken into account in secular_code if REPORT_FUNCTION_NAMES: - print('Stable mass transfer') + print("Stable mass transfer") - if bs.bin_type != bin_type['stable_mass_transfer']: - bs.bin_type = bin_type['stable_mass_transfer'] - self.save_snapshot() + if bs.bin_type != bin_type["stable_mass_transfer"]: + bs.bin_type = bin_type["stable_mass_transfer"] + self.save_snapshot() else: - bs.bin_type = bin_type['stable_mass_transfer'] + bs.bin_type = bin_type["stable_mass_transfer"] self.secular_code.parameters.check_for_inner_RLOF = False self.secular_code.parameters.include_spin_radius_mass_coupling_terms_star1 = False @@ -721,209 +973,240 @@ def stable_mass_transfer(bs, donor, accretor, self): Md = donor.mass Ma = accretor.mass - + dt = self.triple.time - self.previous_time dm_desired = bs.mass_transfer_rate * dt if REPORT_FUNCTION_NAMES: print(bs.mass_transfer_rate, dt, dm_desired) - donor_in_stellar_code = donor.as_set().get_intersecting_subset_in(self.stellar_code.particles)[0] - donor_in_stellar_code.change_mass(dm_desired+(small_numerical_error|units.MSun), dt) - + donor_in_stellar_code = donor.as_set().get_intersecting_subset_in( + self.stellar_code.particles + )[0] + donor_in_stellar_code.change_mass( + dm_desired + (small_numerical_error | units.MSun), dt + ) + # dm != dm_desired e.g. when the envelope of the star becomes empty dm = donor_in_stellar_code.mass - Md - bs.part_dt_mt = 1. - if dm - dm_desired > numerical_error|units.MSun: -# print('WARNING:the envelope is empty, mass transfer rate should be lower or dt should be smaller... ') - bs.part_dt_mt = dm/dm_desired - + bs.part_dt_mt = 1.0 + if dm - dm_desired > numerical_error | units.MSun: + # print('WARNING:the envelope is empty, mass transfer rate should be lower or dt should be smaller... ') + bs.part_dt_mt = dm / dm_desired + # there is an implicit assumption in change_mass that the accreted mass is of solar composition (hydrogen) - accretor_in_stellar_code = accretor.as_set().get_intersecting_subset_in(self.stellar_code.particles)[0] -# accretor_in_stellar_code.change_mass(dm, dt) - # for now, only conservative mass transfer - accretor_in_stellar_code.change_mass(-1.*dm, -1.*dt) - #if you want seba to determine the accretion efficiency, use - #accretor_in_stellar_code.change_mass(-1.*dm, dt) - #note doesnt work perfectly, as seba is oblivious to the roche lobe radius - - - #to adjust radius to mass loss and increase + accretor_in_stellar_code = accretor.as_set().get_intersecting_subset_in( + self.stellar_code.particles + )[0] + # accretor_in_stellar_code.change_mass(dm, dt) + # for now, only conservative mass transfer + accretor_in_stellar_code.change_mass(-1.0 * dm, -1.0 * dt) + # if you want seba to determine the accretion efficiency, use + # accretor_in_stellar_code.change_mass(-1.*dm, dt) + # note doesnt work perfectly, as seba is oblivious to the roche lobe radius + + # to adjust radius to mass loss and increase self.stellar_code.evolve_model(self.triple.time) self.copy_from_stellar() self.update_stellar_parameters() - + Md_new = donor.mass Ma_new = accretor.mass - accretion_efficiency = (Ma_new-Ma)/(Md-Md_new) - if abs(accretion_efficiency - 1.0) > numerical_error and abs(Md-Md_new - -1.*(Ma-Ma_new)) > numerical_error |units.MSun: + accretion_efficiency = (Ma_new - Ma) / (Md - Md_new) + if ( + abs(accretion_efficiency - 1.0) > numerical_error + and abs(Md - Md_new - -1.0 * (Ma - Ma_new)) > numerical_error | units.MSun + ): self.save_snapshot() - print('stable_mass_transfer: non conservative mass transfer') + print("stable_mass_transfer: non conservative mass transfer") print(Md, Ma, donor.previous_mass, accretor.previous_mass) - print(Md_new, Ma_new, Md-Md_new, Ma-Ma_new, accretion_efficiency) + print(Md_new, Ma_new, Md - Md_new, Ma - Ma_new, accretion_efficiency) print(donor.stellar_type, accretor.stellar_type) - sys.exit('error in stable mass transfer') - + sys.exit("error in stable mass transfer") + bs.accretion_efficiency_mass_transfer = accretion_efficiency - corotation_spin = corotating_spin_angular_frequency_binary(bs.semimajor_axis, donor.mass, accretor.mass) + corotation_spin = corotating_spin_angular_frequency_binary( + bs.semimajor_axis, donor.mass, accretor.mass + ) donor.spin_angular_frequency = corotation_spin accretor.spin_angular_frequency = corotation_spin - def semi_detached(bs, donor, accretor, self): -#only for binaries (consisting of two stars) + # only for binaries (consisting of two stars) if REPORT_FUNCTION_NAMES: - print('Semi-detached') - print(bs.semimajor_axis, donor.mass, accretor.mass, donor.stellar_type, accretor.stellar_type, bs.is_mt_stable) - + print("Semi-detached") + print( + bs.semimajor_axis, + donor.mass, + accretor.mass, + donor.stellar_type, + accretor.stellar_type, + bs.is_mt_stable, + ) - stopping_condition = True + stopping_condition = True if bs.is_mt_stable: stable_mass_transfer(bs, donor, accretor, self) - #adjusting triple is done in secular evolution code - else: + # adjusting triple is done in secular evolution code + else: stopping_condition = common_envelope_phase(bs, donor, accretor, self) return stopping_condition - - #possible problem if companion or tertiary accretes significantly from this + + # possible problem if companion or tertiary accretes significantly from this + + # self.update_previous_stellar_parameters() #previous_mass, previous_radius for safety check -#------------------------- -#functions for contact mass transfer in a multiple / triple +# ------------------------- +# functions for contact mass transfer in a multiple / triple + -#change parameters assuming fully conservative mass transfer +# change parameters assuming fully conservative mass transfer def perform_mass_equalisation_for_contact(bs, donor, accretor, self): if REPORT_FUNCTION_NAMES: - print('perform_mass_equalisation_for_contact') + print("perform_mass_equalisation_for_contact") if REPORT_BINARY_EVOLUTION: - print('Start of stable mass transfer of contact systems' ) + print("Start of stable mass transfer of contact systems") - if donor.mass != accretor.mass: - # if abs(donor.mass - accretor.mass)> 1e-4|units.MSun: #could be better. see if problems arise - new_mass = 0.5*(donor.mass + accretor.mass) - bs.semimajor_axis = bs.semimajor_axis * (donor.mass * accretor.mass / new_mass ** 2) ** 2 + if donor.mass != accretor.mass: + # if abs(donor.mass - accretor.mass)> 1e-4|units.MSun: #could be better. see if problems arise + new_mass = 0.5 * (donor.mass + accretor.mass) + bs.semimajor_axis = ( + bs.semimajor_axis * (donor.mass * accretor.mass / new_mass**2) ** 2 + ) delta_mass_donor = new_mass - donor.mass delta_mass_accretor = new_mass - accretor.mass - donor_in_stellar_code = donor.as_set().get_intersecting_subset_in(self.stellar_code.particles)[0] - accretor_in_stellar_code = accretor.as_set().get_intersecting_subset_in(self.stellar_code.particles)[0] - - donor_in_stellar_code.change_mass(delta_mass_donor, -1.0|units.yr) - accretor_in_stellar_code.change_mass(delta_mass_accretor, -1.0|units.yr) - self.stellar_code.evolve_model(minimum_time_step) #to get updates radii, not just inflation of stars due to accretion - self.copy_from_stellar() - self.update_stellar_parameters() #makes secular code use update values: mass equalisation happens instantaneously - - #set to synchronization + donor_in_stellar_code = donor.as_set().get_intersecting_subset_in( + self.stellar_code.particles + )[0] + accretor_in_stellar_code = accretor.as_set().get_intersecting_subset_in( + self.stellar_code.particles + )[0] + + donor_in_stellar_code.change_mass(delta_mass_donor, -1.0 | units.yr) + accretor_in_stellar_code.change_mass(delta_mass_accretor, -1.0 | units.yr) + self.stellar_code.evolve_model( + minimum_time_step + ) # to get updates radii, not just inflation of stars due to accretion + self.copy_from_stellar() + self.update_stellar_parameters() # makes secular code use update values: mass equalisation happens instantaneously + + # set to synchronization if self.include_CHE: - corotating_frequency = corotating_spin_angular_frequency_binary(bs.semimajor_axis, donor.mass, accretor.mass) + corotating_frequency = corotating_spin_angular_frequency_binary( + bs.semimajor_axis, donor.mass, accretor.mass + ) donor.spin_angular_frequency = corotating_frequency accretor.spin_angular_frequency = corotating_frequency - donor.rotation_period = (2*np.pi/donor.spin_angular_frequency) - accretor.rotation_period = (2*np.pi/accretor.spin_angular_frequency) - self.channel_to_stellar.copy_attributes(['rotation_period']) #only defined when include_CHE - - self.secular_code.parameters.include_inner_RLOF_terms = False - self.secular_code.parameters.include_outer_RLOF_terms = False + donor.rotation_period = 2 * np.pi / donor.spin_angular_frequency + accretor.rotation_period = 2 * np.pi / accretor.spin_angular_frequency + self.channel_to_stellar.copy_attributes( + ["rotation_period"] + ) # only defined when include_CHE + self.secular_code.parameters.include_inner_RLOF_terms = False + self.secular_code.parameters.include_outer_RLOF_terms = False def contact_system(bs, star1, star2, self): - #if this implementation changes, then also change the is_mt_stable + # if this implementation changes, then also change the is_mt_stable if REPORT_FUNCTION_NAMES: print("Contact system") - bs.bin_type = bin_type['contact'] - self.save_snapshot() - self.check_RLOF() #@andris: is this necessary? + bs.bin_type = bin_type["contact"] + self.save_snapshot() + self.check_RLOF() # @andris: is this necessary? - #for now no W Ursae Majoris evolution - #so for now contact binaries merge in common_envelope_phase, and MS-MS contact binaries will have mass equalisation - if bs.is_mt_stable: # happens when star1 & star2 are both on MS + # for now no W Ursae Majoris evolution + # so for now contact binaries merge in common_envelope_phase, and MS-MS contact binaries will have mass equalisation + if bs.is_mt_stable: # happens when star1 & star2 are both on MS perform_mass_equalisation_for_contact(bs, bs.child1, bs.child2, self) - stopping_condition = True + stopping_condition = True else: if star1.mass >= star2.mass: stopping_condition = common_envelope_phase(bs, star1, star2, self) else: stopping_condition = common_envelope_phase(bs, star2, star1, self) - return stopping_condition + return stopping_condition + +# ------------------------- +# functions for mass transfer in a multiple / triple -#------------------------- -#functions for mass transfer in a multiple / triple def triple_stable_mass_transfer(bs, donor, accretor, self): # mass transfer of both inner and outer orbit is not yet considered here - - # orbital evolution is being taken into account in secular_code + + # orbital evolution is being taken into account in secular_code if REPORT_FUNCTION_NAMES: - print('Triple stable mass transfer') + print("Triple stable mass transfer") - if bs.bin_type != bin_type['stable_mass_transfer']: - bs.bin_type = bin_type['stable_mass_transfer'] - self.save_snapshot() + if bs.bin_type != bin_type["stable_mass_transfer"]: + bs.bin_type = bin_type["stable_mass_transfer"] + self.save_snapshot() else: - bs.bin_type = bin_type['stable_mass_transfer'] - - #implementation is missing + bs.bin_type = bin_type["stable_mass_transfer"] + + # implementation is missing + def triple_common_envelope_phase(bs, donor, accretor, self): # mass transfer of both inner and outer orbit is not yet considered here - - # orbital evolution is being taken into account in secular_code + + # orbital evolution is being taken into account in secular_code if REPORT_FUNCTION_NAMES: - print('Triple common envelope') + print("Triple common envelope") - bs.bin_type = bin_type['common_envelope'] - self.save_snapshot() - - #implementation is missing + bs.bin_type = bin_type["common_envelope"] + self.save_snapshot() -#when the tertiary star transfers mass to the inner binary + # implementation is missing + + +# when the tertiary star transfers mass to the inner binary def outer_mass_transfer(bs, donor, accretor, self): -#only for stellar systems consisting of a star and a binary + # only for stellar systems consisting of a star and a binary if REPORT_FUNCTION_NAMES: - print('Triple mass transfer') + print("Triple mass transfer") bs.semimajor_axis, donor.mass, self.get_mass(accretor), donor.stellar_type - if bs.is_mt_stable: triple_stable_mass_transfer(bs, donor, accretor, self) - - # possible the outer binary needs part_dt_mt as well. - #adjusting triple is done in secular evolution code - else: + + # possible the outer binary needs part_dt_mt as well. + # adjusting triple is done in secular evolution code + else: triple_common_envelope_phase(bs, donor, accretor, self) + # stopping condition 0:False, 1:True, -1: calculate through outer mass transfer - effect on inner & outer orbit is taken care off here. + return -1 - #stopping condition 0:False, 1:True, -1: calculate through outer mass transfer - effect on inner & outer orbit is taken care off here. - return -1 -#------------------------- +# ------------------------- -#------------------------- -#Functions for detached evolution +# ------------------------- +# Functions for detached evolution ## Calculates stellar wind velocoty. ## Steller wind velocity is 2.5 times stellar escape velocity -#def wind_velocity(star): +# def wind_velocity(star): # v_esc2 = constants.G * star.mass / star.radius # return 2.5*np.sqrt(v_esc2) -#} +# } # # ## Bondi, H., and Hoyle, F., 1944, MNRAS 104, 273 (wind accretion. ## Livio, M., Warner, B., 1984, The Observatory 104, 152. -#def accretion_efficiency_from_stellar_wind(accretor, donor): -#velocity needs to be determined -> velocity average? +# def accretion_efficiency_from_stellar_wind(accretor, donor): +# velocity needs to be determined -> velocity average? # why is BH dependent on ecc as 1/np.sqrt(1-e**2) # alpha_wind = 0.5 # v_wind = wind_velocity(donor) # acc_radius = (constants.G*accretor.mass)**2/v_wind**4 -# +# # wind_acc = alpha_wind/np.sqrt(1-bs.eccentricity**2) / bs.semimajor_axis**2 # v_factor = 1/((1+(velocity/v_wind)**2)**3./2.) # mass_fraction = acc_radius*wind_acc*v_factor @@ -933,111 +1216,111 @@ def outer_mass_transfer(bs, donor, accretor, self): # - def detached(bs, self): - # orbital evolution is being taken into account in secular_code + # orbital evolution is being taken into account in secular_code if REPORT_FUNCTION_NAMES: - print('Detached') + print("Detached") - if bs.bin_type == bin_type['detached'] or bs.bin_type == bin_type['unknown']: - bs.bin_type = bin_type['detached'] + if bs.bin_type == bin_type["detached"] or bs.bin_type == bin_type["unknown"]: + bs.bin_type = bin_type["detached"] else: - bs.bin_type = bin_type['detached'] - self.save_snapshot() - + bs.bin_type = bin_type["detached"] + self.save_snapshot() + # wind mass loss is done by stellar_code # wind accretion here: # update accretion efficiency of wind mass loss if self.is_binary(bs): - + bs.accretion_efficiency_wind_child1_to_child2 = 0.0 bs.accretion_efficiency_wind_child2_to_child1 = 0.0 -# child1_in_stellar_code = bs.child1.as_set().get_intersecting_subset_in(self.stellar_code.particles)[0] -# child2_in_stellar_code = bs.child2.as_set().get_intersecting_subset_in(self.stellar_code.particles)[0] -# -# dt = self.triple.time - self.previous_time -# dm_child1_to_child2 = -1 * child1.wind_mass_loss_rate * bs.accretion_efficiency_wind_child1_to_child2 * dt -# child2_in_stellar_code.change_mass(dm_child1_to_child2, -1*dt) -# dm_child12to_child1 = -1 * child2.wind_mass_loss_rate * bs.accretion_efficiency_wind_child2_to_child1 * dt -# child1_in_stellar_code.change_mass(dm_child2_to_child1, -1*dt) -# check if this indeed is accreted conservatively - + # child1_in_stellar_code = bs.child1.as_set().get_intersecting_subset_in(self.stellar_code.particles)[0] + # child2_in_stellar_code = bs.child2.as_set().get_intersecting_subset_in(self.stellar_code.particles)[0] + # + # dt = self.triple.time - self.previous_time + # dm_child1_to_child2 = -1 * child1.wind_mass_loss_rate * bs.accretion_efficiency_wind_child1_to_child2 * dt + # child2_in_stellar_code.change_mass(dm_child1_to_child2, -1*dt) + # dm_child12to_child1 = -1 * child2.wind_mass_loss_rate * bs.accretion_efficiency_wind_child2_to_child1 * dt + # child1_in_stellar_code.change_mass(dm_child2_to_child1, -1*dt) + # check if this indeed is accreted conservatively elif bs.child1.is_star and self.is_binary(bs.child2): - #Assumption: an inner binary is not effected by wind from an outer star + # Assumption: an inner binary is not effected by wind from an outer star bs.accretion_efficiency_wind_child1_to_child2 = 0.0 bs.accretion_efficiency_wind_child2_to_child1 = 0.0 - -# child1_in_stellar_code = bs.child1.as_set().get_intersecting_subset_in(self.stellar_code.particles)[0] -# dt = self.triple.time - self.previous_time - - #effect of wind from bs.child2.child1 onto bs.child1 -# mtr_w_in1_1 = bs.child2.child1.wind_mass_loss_rate * (1-bs.child2.accretion_efficiency_wind_child1_to_child2) -# beta_w_in1_1 = 0.0 -# dm_in1_1 = -1 * mtr_w_in1_1 * beta_w_in1_1 * dt -# - #effect of wind from bs.child2.child2 onto bs.child1 -# mtr_w_in2_1 = bs.child2.child2.wind_mass_loss_rate * (1-bs.child2.accretion_efficiency_wind_child2_to_child1) -# beta_w_in2_1 = 0.0 -# dm_in2_1 = -1 * mtr_w_in2_1 * beta_w_in2_1 * dt -# -# dm = dm_in1_1 + dm_in2_1 -# mtr = mtr_w_in1_1 + mtr_w_in2_1) - - - #effect of mass transfer in the binary bs.child2 onto bs.child1 -# if bs.child2.child1.is_donor and bs.child2.child2.is_donor: -# print('contact binary in detached...') -# exit(1) -# elif bs.child2.child1.is_donor or bs.child2.child2.is_donor: -# #Assumption: -# #Stable mass transfer in the inner binary, affects the outer binary as a wind. -# mtr_rlof_in_1 = bs.child2.mass_transfer_rate * (1-bs.child2.accretion_efficiency_mass_transfer) -# beta_rlof_in_1 = 0.0 -# dm_rlof_in_1 = -1 * mtr_rlof_in_1 * beta_rlof_in_1 * dt -# dm += dm_rlof_in_1 -# mtr += mtr_rlof_in_1 - -# bs.accretion_efficiency_wind_child2_to_child1 = dm / ( mtr* -1 * dt) - -# child1_in_stellar_code.change_mass(dm, dt) -# check if this indeed is accreted conservatively + + # child1_in_stellar_code = bs.child1.as_set().get_intersecting_subset_in(self.stellar_code.particles)[0] + # dt = self.triple.time - self.previous_time + + # effect of wind from bs.child2.child1 onto bs.child1 + # mtr_w_in1_1 = bs.child2.child1.wind_mass_loss_rate * (1-bs.child2.accretion_efficiency_wind_child1_to_child2) + # beta_w_in1_1 = 0.0 + # dm_in1_1 = -1 * mtr_w_in1_1 * beta_w_in1_1 * dt + # + # effect of wind from bs.child2.child2 onto bs.child1 + # mtr_w_in2_1 = bs.child2.child2.wind_mass_loss_rate * (1-bs.child2.accretion_efficiency_wind_child2_to_child1) + # beta_w_in2_1 = 0.0 + # dm_in2_1 = -1 * mtr_w_in2_1 * beta_w_in2_1 * dt + # + # dm = dm_in1_1 + dm_in2_1 + # mtr = mtr_w_in1_1 + mtr_w_in2_1) + + # effect of mass transfer in the binary bs.child2 onto bs.child1 + # if bs.child2.child1.is_donor and bs.child2.child2.is_donor: + # print('contact binary in detached...') + # exit(1) + # elif bs.child2.child1.is_donor or bs.child2.child2.is_donor: + # #Assumption: + # #Stable mass transfer in the inner binary, affects the outer binary as a wind. + # mtr_rlof_in_1 = bs.child2.mass_transfer_rate * (1-bs.child2.accretion_efficiency_mass_transfer) + # beta_rlof_in_1 = 0.0 + # dm_rlof_in_1 = -1 * mtr_rlof_in_1 * beta_rlof_in_1 * dt + # dm += dm_rlof_in_1 + # mtr += mtr_rlof_in_1 + + # bs.accretion_efficiency_wind_child2_to_child1 = dm / ( mtr* -1 * dt) + + # child1_in_stellar_code.change_mass(dm, dt) + # check if this indeed is accreted conservatively else: self.save_snapshot() - print('detached: type of system unknown') - print( bs.child1.is_star, bs.child2.is_star) - sys.exit('error in detached') - - #reset parameters after mass transfer + print("detached: type of system unknown") + print(bs.child1.is_star, bs.child2.is_star) + sys.exit("error in detached") + + # reset parameters after mass transfer + + # bs.mass_transfer_rate = 0.0 | units.MSun/units.yr # return bs -#------------------------- +# ------------------------- + -#------------------------- +# ------------------------- def perform_stellar_interaction(bs, self): - if REPORT_FUNCTION_NAMES: - print('Perform stellar interaction') - - stopping_condition = True - if not bs.is_star and bs.child1.is_star: + if REPORT_FUNCTION_NAMES: + print("Perform stellar interaction") + + stopping_condition = True + if not bs.is_star and bs.child1.is_star: if REPORT_BINARY_EVOLUTION: Rl1 = roche_radius(bs, bs.child1, self) print("Check for RLOF:", bs.child1.mass, bs.child1.previous_mass) print("Check for RLOF:", Rl1, bs.child1.radius) - + if bs.child2.is_star: if REPORT_BINARY_EVOLUTION: Rl2 = roche_radius(bs, bs.child2, self) print("Check for RLOF:", bs.child2.mass, bs.child2.previous_mass) print("Check for RLOF:", Rl2, bs.child2.radius) - -# if bs.child1.is_donor or bs.child2.is_donor: -# print("start mt") -# exit(0) + + # if bs.child1.is_donor or bs.child2.is_donor: + # print("start mt") + # exit(0) if bs.child1.is_donor and bs.child2.is_donor: stopping_condition = contact_system(bs, bs.child1, bs.child2, self) @@ -1047,85 +1330,105 @@ def perform_stellar_interaction(bs, self): stopping_condition = semi_detached(bs, bs.child2, bs.child1, self) else: detached(bs, self) - + elif not bs.child2.is_star: if REPORT_BINARY_EVOLUTION: print(self.get_mass(bs), bs.child1.mass, self.get_mass(bs.child2)) - + if bs.child1.is_donor: if bs.child2.child1.is_donor or bs.child2.child2.is_donor: - stopping_condition = outer_mass_transfer(bs, bs.child1, bs.child2, self) + stopping_condition = outer_mass_transfer( + bs, bs.child1, bs.child2, self + ) else: detached(bs, self) - + else: print(bs.is_star, bs.child1.is_star, bs.child2.is_star) - sys.exit('error in perform stellar interaction, system type unknown') - - else: + sys.exit("error in perform stellar interaction, system type unknown") + + else: print(bs.is_star, bs.child1.is_star, bs.child1.is_donor) - sys.exit('error in perform stellar interaction, system type unknown') - - return stopping_condition - -#------------------------- - -#------------------------- -#functions for the stability of mass transfer + sys.exit("error in perform stellar interaction, system type unknown") + + return stopping_condition + + +# ------------------------- + + +# ------------------------- +# functions for the stability of mass transfer def q_crit(self, donor, companion): - #following Hurley, Tout, Pols 2002 - if donor.stellar_type in [9]|units.stellar_type: -# if donor.stellar_type in [8,9]|units.stellar_type: + # following Hurley, Tout, Pols 2002 + if donor.stellar_type in [9] | units.stellar_type: + # if donor.stellar_type in [8,9]|units.stellar_type: return 0.784 - elif donor.stellar_type in [3,4,5,6]|units.stellar_type: - x=0.3 - return (1.67-x+2*(donor.core_mass/donor.mass)**5)/2.13 - elif donor.stellar_type == 0|units.stellar_type: + elif donor.stellar_type in [3, 4, 5, 6] | units.stellar_type: + x = 0.3 + return (1.67 - x + 2 * (donor.core_mass / donor.mass) ** 5) / 2.13 + elif donor.stellar_type == 0 | units.stellar_type: return 0.695 - elif donor.stellar_type == 1|units.stellar_type: - return 1./0.625 #following claeys et al. 2014 based on de mink et al 2007 - elif donor.stellar_type in stellar_types_compact_objects:#eventhough ns & bh shouldn't be donors... - return 0.25 #0.628 - elif donor.stellar_type in [18,19]|units.stellar_type:#planet or brown dwarf. - #metzger et al 2012,425,2778, - return 1. * (donor.radius/self.get_size(companion))**3 - else: #stellar type 2, and 8 - return 3 # high for hg? - - + elif donor.stellar_type == 1 | units.stellar_type: + return 1.0 / 0.625 # following claeys et al. 2014 based on de mink et al 2007 + elif ( + donor.stellar_type in stellar_types_compact_objects + ): # eventhough ns & bh shouldn't be donors... + return 0.25 # 0.628 + elif donor.stellar_type in [18, 19] | units.stellar_type: # planet or brown dwarf. + # metzger et al 2012,425,2778, + return 1.0 * (donor.radius / self.get_size(companion)) ** 3 + else: # stellar type 2, and 8 + return 3 # high for hg? + def mass_transfer_stability(binary, self): if REPORT_FUNCTION_NAMES: - print('Mass transfer stability') + print("Mass transfer stability") if self.is_binary(binary): Js_1 = self.spin_angular_momentum(binary.child1) - Js_2 = self.spin_angular_momentum(binary.child2) + Js_2 = self.spin_angular_momentum(binary.child2) Jb = self.orbital_angular_momentum(binary) if REPORT_MASS_TRANSFER_STABILITY: print("Mass transfer stability: Binary ") - print(binary.semimajor_axis, binary.child1.mass, binary.child2.mass, binary.child1.stellar_type, binary.child2.stellar_type) - print(binary.child1.spin_angular_frequency, binary.child2.spin_angular_frequency) - print(Js_1, Js_2, Jb, Jb/3. ) - + print( + binary.semimajor_axis, + binary.child1.mass, + binary.child2.mass, + binary.child1.stellar_type, + binary.child2.stellar_type, + ) + print( + binary.child1.spin_angular_frequency, + binary.child2.spin_angular_frequency, + ) + print(Js_1, Js_2, Jb, Jb / 3.0) + Js = max(Js_1, Js_2) - if Js >= Jb/3. : + if Js >= Jb / 3.0: if REPORT_MASS_TRANSFER_STABILITY: - print("Mass transfer stability: Darwin Riemann instability", Js_1, Js_2, Jb, Jb/3.) - mt1 = -1.* binary.child1.mass / dynamic_timescale(binary.child1) - mt2 = -1.* binary.child2.mass / dynamic_timescale(binary.child2) - binary.mass_transfer_rate = min(mt1, mt2) # minimum because mt<0 + print( + "Mass transfer stability: Darwin Riemann instability", + Js_1, + Js_2, + Jb, + Jb / 3.0, + ) + mt1 = -1.0 * binary.child1.mass / dynamic_timescale(binary.child1) + mt2 = -1.0 * binary.child2.mass / dynamic_timescale(binary.child2) + binary.mass_transfer_rate = min(mt1, mt2) # minimum because mt<0 binary.is_mt_stable = False - + elif binary.child1.is_donor and binary.child2.is_donor: if binary.child1.is_OLOF_donor and binary.child2.is_OLOF_donor: if REPORT_MASS_TRANSFER_STABILITY: print("Mass transfer stability: Unstable OLOF contact") - mt1 = -1.* binary.child1.mass / dynamic_timescale(binary.child1) - mt2 = -1.* binary.child2.mass / dynamic_timescale(binary.child2) - binary.mass_transfer_rate = min(mt1, mt2) # minimum because mt<0 + mt1 = -1.0 * binary.child1.mass / dynamic_timescale(binary.child1) + mt2 = -1.0 * binary.child2.mass / dynamic_timescale(binary.child2) + binary.mass_transfer_rate = min(mt1, mt2) # minimum because mt<0 binary.is_mt_stable = False - #already included in next elif + mass transfer rate doesn't matter for olof + # already included in next elif + mass transfer rate doesn't matter for olof # elif binary.child1.is_OLOF_donor and binary.child1.stellar_type <= 1|units.stellar_type: # if REPORT_MASS_TRANSFER_STABILITY: # print("Mass transfer stability: Stable OLOF") @@ -1135,50 +1438,89 @@ def mass_transfer_stability(binary, self): # if REPORT_MASS_TRANSFER_STABILITY: # print("Mass transfer stability: Stable OLOF") # binary.mass_transfer_rate = -1.* binary.child2.mass / nuclear_evolution_timescale(binary.child2) - # binary.is_mt_stable = True - elif binary.child1.stellar_type <= 1|units.stellar_type and binary.child2.stellar_type <= 1|units.stellar_type: + # binary.is_mt_stable = True + elif ( + binary.child1.stellar_type <= 1 | units.stellar_type + and binary.child2.stellar_type <= 1 | units.stellar_type + ): if REPORT_MASS_TRANSFER_STABILITY: print("Mass transfer stability: stable case A contact") - mt1 = -1.* binary.child1.mass / nuclear_evolution_timescale(binary.child1) - mt2 = -1.* binary.child2.mass / nuclear_evolution_timescale(binary.child2) - binary.mass_transfer_rate = min(mt1, mt2) # minimum because mt<0 + mt1 = ( + -1.0 + * binary.child1.mass + / nuclear_evolution_timescale(binary.child1) + ) + mt2 = ( + -1.0 + * binary.child2.mass + / nuclear_evolution_timescale(binary.child2) + ) + binary.mass_transfer_rate = min(mt1, mt2) # minimum because mt<0 binary.is_mt_stable = False else: if REPORT_MASS_TRANSFER_STABILITY: print("Mass transfer stability: Unstable contact") - mt1 = -1.* binary.child1.mass / dynamic_timescale(binary.child1) - mt2 = -1.* binary.child2.mass / dynamic_timescale(binary.child2) - binary.mass_transfer_rate = min(mt1, mt2) # minimum because mt<0 + mt1 = -1.0 * binary.child1.mass / dynamic_timescale(binary.child1) + mt2 = -1.0 * binary.child2.mass / dynamic_timescale(binary.child2) + binary.mass_transfer_rate = min(mt1, mt2) # minimum because mt<0 binary.is_mt_stable = False - elif binary.child1.is_donor and binary.child1.mass > binary.child2.mass*q_crit(self, binary.child1, binary.child2): + elif ( + binary.child1.is_donor + and binary.child1.mass + > binary.child2.mass * q_crit(self, binary.child1, binary.child2) + ): if REPORT_MASS_TRANSFER_STABILITY: print("Mass transfer stability: Mdonor1>Macc*q_crit ") - binary.mass_transfer_rate = -1.* binary.child1.mass / dynamic_timescale(binary.child1) + binary.mass_transfer_rate = ( + -1.0 * binary.child1.mass / dynamic_timescale(binary.child1) + ) binary.is_mt_stable = False - elif binary.child2.is_donor and binary.child2.mass > binary.child1.mass*q_crit(self, binary.child2, binary.child1): + elif ( + binary.child2.is_donor + and binary.child2.mass + > binary.child1.mass * q_crit(self, binary.child2, binary.child1) + ): if REPORT_MASS_TRANSFER_STABILITY: print("Mass transfer stability: Mdonor2>Macc*q_crit ") - binary.mass_transfer_rate= -1.* binary.child2.mass / dynamic_timescale(binary.child2) + binary.mass_transfer_rate = ( + -1.0 * binary.child2.mass / dynamic_timescale(binary.child2) + ) binary.is_mt_stable = False - + elif binary.child1.is_donor: if REPORT_MASS_TRANSFER_STABILITY: print("Mass transfer stability: Donor1 stable ") - binary.mass_transfer_rate = -1.* binary.child1.mass / mass_transfer_timescale(binary, binary.child1) + binary.mass_transfer_rate = ( + -1.0 + * binary.child1.mass + / mass_transfer_timescale(binary, binary.child1) + ) binary.is_mt_stable = True elif binary.child2.is_donor: if REPORT_MASS_TRANSFER_STABILITY: print("Mass transfer stability: Donor2 stable") - binary.mass_transfer_rate = -1.* binary.child2.mass / mass_transfer_timescale(binary, binary.child2) + binary.mass_transfer_rate = ( + -1.0 + * binary.child2.mass + / mass_transfer_timescale(binary, binary.child2) + ) binary.is_mt_stable = True - - else: + + else: if REPORT_MASS_TRANSFER_STABILITY: print("Mass transfer stability: Detached") - #detached system - mt1 = -1.* binary.child1.mass / mass_transfer_timescale(binary, binary.child1) - mt2 = -1.* binary.child2.mass / mass_transfer_timescale(binary, binary.child2) - binary.mass_transfer_rate = min(mt1, mt2) # minimum because mt<0 + # detached system + mt1 = ( + -1.0 + * binary.child1.mass + / mass_transfer_timescale(binary, binary.child1) + ) + mt2 = ( + -1.0 + * binary.child2.mass + / mass_transfer_timescale(binary, binary.child2) + ) + binary.mass_transfer_rate = min(mt1, mt2) # minimum because mt<0 binary.is_mt_stable = True else: @@ -1188,169 +1530,257 @@ def mass_transfer_stability(binary, self): elif binary.child2.is_star and not binary.child1.is_star: star = binary.child2 companion = binary.child1 - else: + else: print(binary.is_star, binary.child1.is_star, binary.child2.is_star) - sys.exit('error in Mass transfer stability: type of system unknown') + sys.exit("error in Mass transfer stability: type of system unknown") - if REPORT_MASS_TRANSFER_STABILITY: print("Mass transfer stability: Binary ") - print(binary.semimajor_axis, self.get_mass(companion), star.mass, star.stellar_type) - + print( + binary.semimajor_axis, + self.get_mass(companion), + star.mass, + star.stellar_type, + ) + Js = self.spin_angular_momentum(star) Jb = self.orbital_angular_momentum(binary) - - if Js >= Jb/3. : + + if Js >= Jb / 3.0: if REPORT_MASS_TRANSFER_STABILITY: - print("Mass transfer stability: Darwin Riemann instability: ", Js, Jb, Jb/3.) - binary.mass_transfer_rate = -1.* star.mass / dynamic_timescale(star) - binary.is_mt_stable = False - - elif star.is_donor and star.mass > self.get_mass(companion)*q_crit(self, star, companion): + print( + "Mass transfer stability: Darwin Riemann instability: ", + Js, + Jb, + Jb / 3.0, + ) + binary.mass_transfer_rate = -1.0 * star.mass / dynamic_timescale(star) + binary.is_mt_stable = False + + elif star.is_donor and star.mass > self.get_mass(companion) * q_crit( + self, star, companion + ): if REPORT_MASS_TRANSFER_STABILITY: print("Mass transfer stability: Mdonor1>Macc*q_crit") - binary.mass_transfer_rate = -1.* star.mass / dynamic_timescale(star) + binary.mass_transfer_rate = -1.0 * star.mass / dynamic_timescale(star) binary.is_mt_stable = False - - + elif star.is_donor: if REPORT_MASS_TRANSFER_STABILITY: print("Mass transfer stability: Donor1 stable ") - binary.mass_transfer_rate = -1.* star.mass / mass_transfer_timescale(binary, star) + binary.mass_transfer_rate = ( + -1.0 * star.mass / mass_transfer_timescale(binary, star) + ) binary.is_mt_stable = True - - else: + + else: if REPORT_MASS_TRANSFER_STABILITY: print("Mass transfer stability: Detached") - #detached system - binary.mass_transfer_rate = -1.* star.mass / mass_transfer_timescale(binary, star) + # detached system + binary.mass_transfer_rate = ( + -1.0 * star.mass / mass_transfer_timescale(binary, star) + ) binary.is_mt_stable = True - - - - + + def mass_transfer_timescale(binary, star): if REPORT_FUNCTION_NAMES: - print('Mass transfer timescale') - + print("Mass transfer timescale") + if not star.is_star: - sys.exit('error in mass transfer timescale: type of system unknown, donor star is not a star') - - #For now thermal timescale donor + sys.exit( + "error in mass transfer timescale: type of system unknown, donor star is not a star" + ) + + # For now thermal timescale donor mtt = kelvin_helmholds_timescale(star) -# mtt = nuclear_evolution_timescale(star) + # mtt = nuclear_evolution_timescale(star) return mtt -#------------------------- + + +# ------------------------- # Mass loss recipes for the energy limited photoevaporation of planets. - + + # X-ray luminosity fraction as prescripted by Wright 2011, based on the Rossby number. def Rx_wright11(mass, p_rot): - Rx_sat = 10**(-3.13) + Rx_sat = 10 ** (-3.13) Ro_sat = 0.16 - tau_conv = 10**(1.16 - 1.49* np.log(mass.value_in(units.MSun)) - 0.54*(np.log(mass.value_in(units.MSun)))**2) - Ro = p_rot/tau_conv + tau_conv = 10 ** ( + 1.16 + - 1.49 * np.log(mass.value_in(units.MSun)) + - 0.54 * (np.log(mass.value_in(units.MSun))) ** 2 + ) + Ro = p_rot / tau_conv if Ro > Ro_sat: B = -2.70 - R_X = Rx_sat * (Ro / Ro_sat)**B + R_X = Rx_sat * (Ro / Ro_sat) ** B else: R_X = Rx_sat return R_X + # compute the specific flux of a BB, in erg/s /m3 (/sterad) def blackbody(wavel, T): - h = constants.h.value_in( units.erg * units.s ) - c = constants.c.value_in( units.m / units.s ) - KB = constants.kB.value_in( units.erg / units.K ) - B_l = (2* h * c**2 / wavel**5) / (np.exp( h*c/(wavel*KB*T), dtype=np.float128) - 1) + h = constants.h.value_in(units.erg * units.s) + c = constants.c.value_in(units.m / units.s) + KB = constants.kB.value_in(units.erg / units.K) + B_l = (2 * h * c**2 / wavel**5) / ( + np.exp(h * c / (wavel * KB * T), dtype=np.float128) - 1 + ) return B_l - - + + # Compute the high energy luminosity from the bolometric one. def xuv_luminosity(star): - L_bol = star.luminosity.value_in(units.erg/units.s) - - #silvia: right now WDs+NS, should it just be wds? include bhs? - if star.stellar_type.value in [10,11,12]: # we have a WD, we integrate a Black Body from 1 nm to 91.2 nm - F_xuv = integrate.quad(blackbody, 1e-09, 9.12e-08, args=(star.temperature.value_in(units.K)))[0] - L_XUV = 4*np.pi**2 * star.radius.value_in(units.m)**2 * F_xuv + L_bol = star.luminosity.value_in(units.erg / units.s) + + # silvia: right now WDs+NS, should it just be wds? include bhs? + if star.stellar_type.value in [ + 10, + 11, + 12, + ]: # we have a WD, we integrate a Black Body from 1 nm to 91.2 nm + F_xuv = integrate.quad( + blackbody, 1e-09, 9.12e-08, args=(star.temperature.value_in(units.K)) + )[0] + L_XUV = 4 * np.pi**2 * star.radius.value_in(units.m) ** 2 * F_xuv # print('M WD:', star.mass, '\t T WD:', star.temperature) - return L_XUV # erg/s + return L_XUV # erg/s elif star.stellar_type in stellar_types_planetary_objects: - return 0; - elif star.stellar_type in stellar_types_SN_remnants: #NS, BH or massless SN - return 0; - else: - if (star.mass <= 2|units.MSun): - p_rot_star = 2*np.pi / star.spin_angular_frequency.value_in(1/units.s) - L_X = L_bol * Rx_wright11(star.mass, p_rot_star) # Rossby number approach, Wright 2011 - L_EUV = 10**4.8 * L_X**0.86 # Sanz-Forcada 2011 - elif 2|units.MSun < star.mass <= 3|units.MSun: - if star.stellar_type.value in [1,2,7,8]: #ms & hg : radiative envelope - L_X = 10**(-3.5) * L_bol # Flaccomio 2003 - elif star.stellar_type.value in [3,4,5,6,9]: # during giant phases, rossby approach again, having convective envelopes - p_rot_star = 2*np.pi / star.spin_angular_frequency.value_in(1/units.s) + return 0 + elif star.stellar_type in stellar_types_SN_remnants: # NS, BH or massless SN + return 0 + else: + if star.mass <= 2 | units.MSun: + p_rot_star = 2 * np.pi / star.spin_angular_frequency.value_in(1 / units.s) + L_X = L_bol * Rx_wright11( + star.mass, p_rot_star + ) # Rossby number approach, Wright 2011 + L_EUV = 10**4.8 * L_X**0.86 # Sanz-Forcada 2011 + elif 2 | units.MSun < star.mass <= 3 | units.MSun: + if star.stellar_type.value in [1, 2, 7, 8]: # ms & hg : radiative envelope + L_X = 10 ** (-3.5) * L_bol # Flaccomio 2003 + elif star.stellar_type.value in [ + 3, + 4, + 5, + 6, + 9, + ]: # during giant phases, rossby approach again, having convective envelopes + p_rot_star = ( + 2 * np.pi / star.spin_angular_frequency.value_in(1 / units.s) + ) L_X = L_bol * Rx_wright11(star.mass, p_rot_star) - else: - sys.exit('stellar type unknown in xuv_luminosity') - L_EUV = 10**4.8 * L_X**0.86 # Sanz-Forcada 2011 + else: + sys.exit("stellar type unknown in xuv_luminosity") + L_EUV = 10**4.8 * L_X**0.86 # Sanz-Forcada 2011 - elif 3|units.MSun < star.mass < 10|units.MSun: + elif 3 | units.MSun < star.mass < 10 | units.MSun: L_X = 1e-06 * L_bol # 10**31 # erg/s #Flaccomio 2003 - L_EUV = L_X # actually EUV should be stronger than X emission in this mass range + L_EUV = L_X # actually EUV should be stronger than X emission in this mass range else: # Star mass out of implemented range for evaporation: default factor employed L_X = 1e-06 * L_bol L_EUV = 1e-06 * L_bol - - return (L_X + L_EUV ) #|units.erg/units.s # erg/s - - + + return L_X + L_EUV # |units.erg/units.s # erg/s + + # Compute instantaneous flux at time t from given star, for a planet in circular orbit. # lum input has to be erg/s -def flux_inst(t, r_plan, a_st_i, P_plan, P_binary, lum, star_number, i_orb ): - phi = 2*np.pi * t / P_plan # planet's phase angle (inclined) - st_ang = 2*np.pi* t / P_binary + star_number * np.pi # star phase angle (on plane) - d_z2 = ( r_plan * np.sin(phi) * np.sin(i_orb) )**2 - d_p2 = ( r_plan *np.cos(phi) - a_st_i *np.cos(st_ang) )**2 + ( r_plan *np.sin(phi)*np.cos(i_orb) - a_st_i *np.sin(st_ang) )**2 +def flux_inst(t, r_plan, a_st_i, P_plan, P_binary, lum, star_number, i_orb): + phi = 2 * np.pi * t / P_plan # planet's phase angle (inclined) + st_ang = ( + 2 * np.pi * t / P_binary + star_number * np.pi + ) # star phase angle (on plane) + d_z2 = (r_plan * np.sin(phi) * np.sin(i_orb)) ** 2 + d_p2 = (r_plan * np.cos(phi) - a_st_i * np.cos(st_ang)) ** 2 + ( + r_plan * np.sin(phi) * np.cos(i_orb) - a_st_i * np.sin(st_ang) + ) ** 2 distance_sq = d_p2 + d_z2 - return lum/distance_sq - - -def mass_lost_due_to_evaporation_tertiary(stellar_system, dt, outer_planet, inner_binary, self): + return lum / distance_sq + + +def mass_lost_due_to_evaporation_tertiary( + stellar_system, dt, outer_planet, inner_binary, self +): if REPORT_FUNCTION_NAMES: print("Mass lost due to evaporation tertiary") - + e_pl = stellar_system.eccentricity - a_pl = stellar_system.semimajor_axis + a_pl = stellar_system.semimajor_axis P_pl = self.orbital_period(stellar_system) i_orbits = stellar_system.relative_inclination # time-averaged circular radius of elliptical orbits - r_pl = a_pl * ( 1 + 0.5* e_pl**2 ) + r_pl = a_pl * (1 + 0.5 * e_pl**2) a_bin = inner_binary.semimajor_axis P_bin = self.orbital_period(inner_binary) - M_bin = self.get_mass(inner_binary) - xi = roche_radius_dimensionless(outer_planet.mass, M_bin) * a_pl / outer_planet.radius - #Erkaev (2007) escape factor - K_Erk = 1 - 1.5/xi + 0.5* xi**(-3) + M_bin = self.get_mass(inner_binary) + xi = ( + roche_radius_dimensionless(outer_planet.mass, M_bin) + * a_pl + / outer_planet.radius + ) + # Erkaev (2007) escape factor + K_Erk = 1 - 1.5 / xi + 0.5 * xi ** (-3) # compute the high-energy flux average from the two stars - t_start = 0. - #average on one orbital period of the outer planet (~ 5 P_binary) - t_end = P_pl.value_in(units.Myr) + t_start = 0.0 + # average on one orbital period of the outer planet (~ 5 P_binary) + t_end = P_pl.value_in(units.Myr) L_xuv1_erg_s = xuv_luminosity(inner_binary.child1) - a_st_1 = a_bin/(1+inner_binary.child1.mass/inner_binary.child2.mass) - F1 = integrate.quad(flux_inst, t_start, t_end, args=(r_pl.value_in(units.RSun), a_st_1.value_in(units.RSun), P_pl.value_in(units.Myr), P_bin.value_in(units.Myr), L_xuv1_erg_s, 0, i_orbits), limit=100, full_output=1)[0] + a_st_1 = a_bin / (1 + inner_binary.child1.mass / inner_binary.child2.mass) + F1 = integrate.quad( + flux_inst, + t_start, + t_end, + args=( + r_pl.value_in(units.RSun), + a_st_1.value_in(units.RSun), + P_pl.value_in(units.Myr), + P_bin.value_in(units.Myr), + L_xuv1_erg_s, + 0, + i_orbits, + ), + limit=100, + full_output=1, + )[0] L_xuv2_erg_s = xuv_luminosity(inner_binary.child2) - a_st_2 = a_bin/(1+inner_binary.child2.mass/inner_binary.child1.mass) - F2 = integrate.quad(flux_inst, t_start, t_end, args=(r_pl.value_in(units.RSun), a_st_2.value_in(units.RSun), P_pl.value_in(units.Myr), P_bin.value_in(units.Myr), L_xuv2_erg_s, 1, i_orbits), limit=100, full_output=1)[0] - - Flux_XUV = (F1+F2)/(4*np.pi* (t_end-t_start) ) | (units.erg/units.s / units.RSun**2) - eta = 0.2 # evaporation efficiency parameter - M_dot = eta * np.pi * (outer_planet.radius)**3 * Flux_XUV / ( constants.G * outer_planet.mass * K_Erk ) + a_st_2 = a_bin / (1 + inner_binary.child2.mass / inner_binary.child1.mass) + F2 = integrate.quad( + flux_inst, + t_start, + t_end, + args=( + r_pl.value_in(units.RSun), + a_st_2.value_in(units.RSun), + P_pl.value_in(units.Myr), + P_bin.value_in(units.Myr), + L_xuv2_erg_s, + 1, + i_orbits, + ), + limit=100, + full_output=1, + )[0] + + Flux_XUV = (F1 + F2) / (4 * np.pi * (t_end - t_start)) | ( + units.erg / units.s / units.RSun**2 + ) + eta = 0.2 # evaporation efficiency parameter + M_dot = ( + eta + * np.pi + * (outer_planet.radius) ** 3 + * Flux_XUV + / (constants.G * outer_planet.mass * K_Erk) + ) mass_lost = M_dot * dt return mass_lost @@ -1360,19 +1790,24 @@ def mass_lost_due_to_evaporation_in_binary(stellar_system, dt, planet, star, sel print("Mass lost due to evaporation binary") e_pl = stellar_system.eccentricity - a_pl = stellar_system.semimajor_axis + a_pl = stellar_system.semimajor_axis P_pl = self.orbital_period(stellar_system) i_orbits = stellar_system.relative_inclination # time-averaged circular radius of elliptical orbits - r_pl = a_pl * ( 1 + 0.5* e_pl**2 ) + r_pl = a_pl * (1 + 0.5 * e_pl**2) xi = roche_radius_dimensionless(planet.mass, star.mass) * a_pl / planet.radius - #Erkaev (2007) escape factor - K_Erk = 1 - 1.5/xi + 0.5* xi**(-3) - Flux_XUV = star.luminosity / r_pl**2 - - eta = 0.2 # evaporation efficiency parameter - M_dot = eta * np.pi * (planet.radius)**3 * Flux_XUV / ( constants.G * planet.mass * K_Erk ) + # Erkaev (2007) escape factor + K_Erk = 1 - 1.5 / xi + 0.5 * xi ** (-3) + Flux_XUV = star.luminosity / r_pl**2 + + eta = 0.2 # evaporation efficiency parameter + M_dot = ( + eta + * np.pi + * (planet.radius) ** 3 + * Flux_XUV + / (constants.G * planet.mass * K_Erk) + ) mass_lost = M_dot * dt return mass_lost - From 89436b46907507da56a293b2adce887510dabbdb Mon Sep 17 00:00:00 2001 From: Steven Rieder Date: Mon, 4 Nov 2024 13:42:39 +0100 Subject: [PATCH 12/30] refactor options.py --- src/tres/options.py | 70 +++++++++++++++++++++++---------------------- 1 file changed, 36 insertions(+), 34 deletions(-) diff --git a/src/tres/options.py b/src/tres/options.py index 3ec0b2f..890818e 100644 --- a/src/tres/options.py +++ b/src/tres/options.py @@ -1,13 +1,13 @@ import numpy as np from amuse.units import units -#-------------------------------------------------------------------------------------------------------------------- +# -------------------------------------------------------------------------------------------------------------------- # TRES general settings REPORT_USER_WARNINGS = True REPORT_DEBUG = False -REPORT_DT = False +REPORT_DT = False REPORT_SN_EVOLUTION = False -REPORT_TRIPLE_EVOLUTION = False +REPORT_TRIPLE_EVOLUTION = False MAKE_PLOTS = False REPORT_BINARY_EVOLUTION = False @@ -18,48 +18,50 @@ GET_AMC_FROM_STELLAR_CODE = False no_stellar_evolution = False -#-------------------------------------------------------------------------------------------------------------------- -#TRES constants -time_step_factor_stable_mt = 0.01 #1% mass loss during mass transfer +# -------------------------------------------------------------------------------------------------------------------- +# TRES constants +time_step_factor_stable_mt = 0.01 # 1% mass loss during mass transfer # lowering this to 0.005 makes the code twice as slow time_step_factor_ecc = 0.01 -#Rl_fraction = 0.8 +# Rl_fraction = 0.8 # 0.01 -> error in the semi-major axis of about 0.5% -maximum_wind_mass_loss_factor = 0.01 +maximum_wind_mass_loss_factor = 0.01 error_dm = 0.05 -#maximum_radius_change_factor = 0.005 -error_dr = 0.05 #0.01 -minimum_time_step = 1.e-9 |units.Myr +# maximum_radius_change_factor = 0.005 +error_dr = 0.05 # 0.01 +minimum_time_step = 1.0e-9 | units.Myr -max_mass = 100 |units.MSun -min_mass = 0.08 |units.MSun # for primary stars +max_mass = 100 | units.MSun +min_mass = 0.08 | units.MSun # for primary stars -maximum_time_step_factor = 100. -maximum_time_step_factor_after_stable_mt = 5. +maximum_time_step_factor = 100.0 +maximum_time_step_factor_after_stable_mt = 5.0 time_step_factor_find_RLOF = 0.5 -#Rl_fraction = 0.9#1.0-10.*error_dr # ratio or star radius over Roche lobe at which time step is decreased - # radius grows maximally by error_dr -time_step_factor_kozai = 0.025 # 0.2*0.1, 0.2-> for error in kozai timescale, 0.1-> 10 steps per cycle -kozai_type_factor = 10. -maximum_time_step = np.inf|units.Myr +# Rl_fraction = 0.9#1.0-10.*error_dr # ratio or star radius over Roche lobe at which time step is decreased +# radius grows maximally by error_dr +time_step_factor_kozai = ( + 0.025 # 0.2*0.1, 0.2-> for error in kozai timescale, 0.1-> 10 steps per cycle +) +kozai_type_factor = 10.0 +maximum_time_step = np.inf | units.Myr -kanonical_neutron_star_mass = 1.4|units.MSun -fall_back_mass = 41 |units.MSun +kanonical_neutron_star_mass = 1.4 | units.MSun +fall_back_mass = 41 | units.MSun -#-------------------------------------------------------------------------------------------------------------------- -#TPS general settings +# -------------------------------------------------------------------------------------------------------------------- +# TPS general settings REPORT_TPS = False REPORT_USER_WARNINGS_TPS = False -EXCLUDE_SSO = True #in order to not simulate systems with exoplanet or brown dwarf secondaries and tertiaries +EXCLUDE_SSO = True # in order to not simulate systems with exoplanet or brown dwarf secondaries and tertiaries -#-------------------------------------------------------------------------------------------------------------------- -#TPS constants -precision = 1.e-10 -absolute_max_mass = 100 |units.MSun +# -------------------------------------------------------------------------------------------------------------------- +# TPS constants +precision = 1.0e-10 +absolute_max_mass = 100 | units.MSun # for secondaries and tertiaries -if EXCLUDE_SSO: - absolute_min_mass = 0.0075|units.MSun -else: - absolute_min_mass = 0.2|units.MJupiter +if EXCLUDE_SSO: + absolute_min_mass = 0.0075 | units.MSun +else: + absolute_min_mass = 0.2 | units.MJupiter -#-------------------------------------------------------------------------------------------------------------------- \ No newline at end of file +# -------------------------------------------------------------------------------------------------------------------- From 1a0f6e202d026b0a4c89aa9e6eb6a056b2e497b5 Mon Sep 17 00:00:00 2001 From: Steven Rieder Date: Mon, 4 Nov 2024 13:43:28 +0100 Subject: [PATCH 13/30] Refactor plotting.py; use CamelCase for classes --- src/tres/plotting.py | 1159 +++++++++++++++++++++--------------------- 1 file changed, 582 insertions(+), 577 deletions(-) diff --git a/src/tres/plotting.py b/src/tres/plotting.py index d8663f9..04d2b31 100644 --- a/src/tres/plotting.py +++ b/src/tres/plotting.py @@ -1,12 +1,15 @@ +import numpy as np import matplotlib.pyplot as plt -import amuse.plot as aplt + +# import amuse.plot as aplt from amuse.units import units -import numpy as np -class plot_data_container(): + +class PlotDataContainer: def __init__(self): return + def plot_function(triple, dir_plots): times_array_Myr = triple.plot_data.times_array.value_in(units.Myr) t_max_Myr = max(times_array_Myr) @@ -35,650 +38,654 @@ def plot_function(triple, dir_plots): RL2_array = triple.plot_data.RL2_array RL3_array = triple.plot_data.RL3_array delta_e_in_array = triple.plot_data.delta_e_in_array - - f = open(triple.file_name[:-4]+'.txt','w') - f.write('#' + str(t_max_Myr) + '\n') + + f = open(triple.file_name[:-4] + ".txt", "w") + f.write("#" + str(t_max_Myr) + "\n") for i_p in range(len(times_array_Myr)): - f.write(str(times_array_Myr[i_p]) + '\t') - f.write(str(m1_array[i_p] ) + '\t') - f.write(str(m2_array[i_p] ) + '\t') - f.write(str(m3_array[i_p] ) + '\t') - f.write(str(spin1_array[i_p] ) + '\t') - f.write(str(spin2_array[i_p] ) + '\t') - f.write(str(spin3_array[i_p] ) + '\t') - f.write(str(r1_array[i_p] ) + '\t') - f.write(str(r2_array[i_p] ) + '\t') - f.write(str(r3_array[i_p] ) + '\t') - f.write(str(RL1_array[i_p] ) + '\t') - f.write(str(RL2_array[i_p] ) + '\t') - f.write(str(RL3_array[i_p] ) + '\t') - f.write(str(moi1_array[i_p] ) + '\t') - f.write(str(moi2_array[i_p] ) + '\t') - f.write(str(moi3_array[i_p] ) + '\t') - f.write(str(i_relative_array[i_p] ) + '\t') - f.write(str(a_in_array_AU[i_p] ) + '\t') - f.write(str(g_in_array[i_p] ) + '\t') - f.write(str(e_in_array[i_p] ) + '\t') - f.write(str(o_in_array[i_p] ) + '\t') - f.write(str(a_out_array_AU[i_p] ) + '\t') - f.write(str(g_out_array[i_p] ) + '\t') - f.write(str(e_out_array[i_p] ) + '\t') - f.write(str(o_out_array[i_p] ) + '\t') - f.write(str(delta_e_in_array[i_p] ) + '\t') - f.write('\n') + f.write(str(times_array_Myr[i_p]) + "\t") + f.write(str(m1_array[i_p]) + "\t") + f.write(str(m2_array[i_p]) + "\t") + f.write(str(m3_array[i_p]) + "\t") + f.write(str(spin1_array[i_p]) + "\t") + f.write(str(spin2_array[i_p]) + "\t") + f.write(str(spin3_array[i_p]) + "\t") + f.write(str(r1_array[i_p]) + "\t") + f.write(str(r2_array[i_p]) + "\t") + f.write(str(r3_array[i_p]) + "\t") + f.write(str(RL1_array[i_p]) + "\t") + f.write(str(RL2_array[i_p]) + "\t") + f.write(str(RL3_array[i_p]) + "\t") + f.write(str(moi1_array[i_p]) + "\t") + f.write(str(moi2_array[i_p]) + "\t") + f.write(str(moi3_array[i_p]) + "\t") + f.write(str(i_relative_array[i_p]) + "\t") + f.write(str(a_in_array_AU[i_p]) + "\t") + f.write(str(g_in_array[i_p]) + "\t") + f.write(str(e_in_array[i_p]) + "\t") + f.write(str(o_in_array[i_p]) + "\t") + f.write(str(a_out_array_AU[i_p]) + "\t") + f.write(str(g_out_array[i_p]) + "\t") + f.write(str(e_out_array[i_p]) + "\t") + f.write(str(o_out_array[i_p]) + "\t") + f.write(str(delta_e_in_array[i_p]) + "\t") + f.write("\n") f.close() - -# for i_s in range(len(times_array_Myr)): -# print(times_array_Myr[i_s], end = ' ') -# print( a_in_array_AU[i_s], end = ' ') -# print( g_in_array[i_s], end = ' ') -# print( e_in_array[i_s], end = ' ') -# print( i_relative_array[i_s], end = ' ') -# print( o_in_array[i_s], end = ' ') -# print( a_out_array_AU[i_s], end = ' ') -# print( g_out_array[i_s], end = ' ') -# print( e_out_array[i_s], end = ' ') -# print( o_out_array[i_s], end = ' ') -# print( m1_array[i_s], end = ' ') -# print( m2_array[i_s], end = ' ') -# print( m3_array[i_s], end = ' ') -# print( spin1_array[i_s], end = ' ') -# print( spin2_array[i_s], end = ' ') -# print( spin3_array[i_s], end = ' ') -# print( r1_array[i_s], end = ' ') -# print( r2_array[i_s], end = ' ') -# print( r3_array[i_s], end = ' ') -# print( RL1_array[i_s], end = ' ') -# print( RL2_array[i_s], end = ' ') -# print( RL3_array[i_s], end = ' ') -# print( moi1_array[i_s], end = ' ') -# print( moi2_array[i_s], end = ' ') -# print( moi3_array[i_s], end = ' ') -# print( delta_e_in_array[i_s]) - - - - ### plots to test secular code ### - import amuse.plot as aplt - import matplotlib.pyplot as plt - plt.rcParams.update({'font.size': 16}) - -# generic_name = '_M'+str(m1_array[0]) + '_m'+str(m2_array[0]) +'_n'+str(m3_array[0]) + '_a'+str(a_in_array_AU[0]) + '_A'+str(a_out_array_AU[0]) + '_e'+str(e_in_array[0]) + '_E'+str(e_out_array[0]) + '_i'+str(i_relative_array[0]/np.pi*180.0) + '_g'+str(g_in_array[0]) + '_G'+str(g_out_array[0]) + '_o'+str(o_in_array[0]) + '_O'+str(o_out_array[0]) + '_t'+str(t_max_Myr) + '_maxdr'+str(triple.maximum_radius_change_factor)+'_edr'+str(error_dr) - generic_name = '' - - figure = plt.figure(figsize=(10,13), tight_layout=True) - N_subplots = 4 - - plot_e = figure.add_subplot(N_subplots,1,1) - plot_i_relative = figure.add_subplot(N_subplots,1,2) - plot_a_in = figure.add_subplot(N_subplots,1,3) - plot_a_out = figure.add_subplot(N_subplots,1,4) - - plot_e.plot(times_array_Myr,e_in_array, label= '$e_\mathrm{in}$') - plot_e.plot(times_array_Myr,e_out_array, label= '$e_\mathrm{out}$') - plot_e.set_xlim(0,t_max_Myr) - plot_e.set_xlabel('$t/\mathrm{Myr}$') - plot_e.set_ylabel('$e$') - plot_e.legend(loc=0) - - plot_i_relative.plot(times_array_Myr,i_relative_array*180.0/np.pi) - plot_i_relative.set_xlim(0,t_max_Myr) - plot_i_relative.set_ylim(0.9*min(i_relative_array*180.0/np.pi),1.1*max(i_relative_array*180.0/np.pi)) - plot_i_relative.set_xlabel('$t/\mathrm{Myr}$') - plot_i_relative.set_ylabel('$i_\mathrm{relative} ({}^\circ)$') - - plot_a_in.plot(times_array_Myr,a_in_array_AU) - plot_a_in.set_xlabel('$t/\mathrm{Myr}$') - plot_a_in.set_ylabel('$a_\mathrm{in}$') - - plot_a_out.plot(times_array_Myr,a_out_array_AU) - plot_a_out.set_xlabel('$t/\mathrm{Myr}$') - plot_a_out.set_ylabel('$a_\mathrm{out}$') - - figure.subplots_adjust(left=0.2, right=0.85, top=0.8, bottom=0.15) - plt.savefig(dir_plots+'TRES'+generic_name+'.pdf') -# plt.show() - plt.close() - + # for i_s in range(len(times_array_Myr)): + # print(times_array_Myr[i_s], end = ' ') + # print( a_in_array_AU[i_s], end = ' ') + # print( g_in_array[i_s], end = ' ') + # print( e_in_array[i_s], end = ' ') + # print( i_relative_array[i_s], end = ' ') + # print( o_in_array[i_s], end = ' ') + # print( a_out_array_AU[i_s], end = ' ') + # print( g_out_array[i_s], end = ' ') + # print( e_out_array[i_s], end = ' ') + # print( o_out_array[i_s], end = ' ') + # print( m1_array[i_s], end = ' ') + # print( m2_array[i_s], end = ' ') + # print( m3_array[i_s], end = ' ') + # print( spin1_array[i_s], end = ' ') + # print( spin2_array[i_s], end = ' ') + # print( spin3_array[i_s], end = ' ') + # print( r1_array[i_s], end = ' ') + # print( r2_array[i_s], end = ' ') + # print( r3_array[i_s], end = ' ') + # print( RL1_array[i_s], end = ' ') + # print( RL2_array[i_s], end = ' ') + # print( RL3_array[i_s], end = ' ') + # print( moi1_array[i_s], end = ' ') + # print( moi2_array[i_s], end = ' ') + # print( moi3_array[i_s], end = ' ') + # print( delta_e_in_array[i_s]) + + # plots to test secular code ### + + plt.rcParams.update({"font.size": 16}) + + # generic_name = '_M'+str(m1_array[0]) + '_m'+str(m2_array[0]) +'_n'+str(m3_array[0]) + '_a'+str(a_in_array_AU[0]) + '_A'+str(a_out_array_AU[0]) + '_e'+str(e_in_array[0]) + '_E'+str(e_out_array[0]) + '_i'+str(i_relative_array[0]/np.pi*180.0) + '_g'+str(g_in_array[0]) + '_G'+str(g_out_array[0]) + '_o'+str(o_in_array[0]) + '_O'+str(o_out_array[0]) + '_t'+str(t_max_Myr) + '_maxdr'+str(triple.maximum_radius_change_factor)+'_edr'+str(error_dr) + generic_name = "" + + figure = plt.figure(figsize=(10, 13), tight_layout=True) + n_subplots = 4 + + plot_e = figure.add_subplot(n_subplots, 1, 1) + plot_i_relative = figure.add_subplot(n_subplots, 1, 2) + plot_a_in = figure.add_subplot(n_subplots, 1, 3) + plot_a_out = figure.add_subplot(n_subplots, 1, 4) + + plot_e.plot(times_array_Myr, e_in_array, label=r"$e_\mathrm{in}$") + plot_e.plot(times_array_Myr, e_out_array, label=r"$e_\mathrm{out}$") + plot_e.set_xlim(0, t_max_Myr) + plot_e.set_xlabel(r"$t/\mathrm{Myr}$") + plot_e.set_ylabel("$e$") + plot_e.legend(loc=0) + plot_i_relative.plot(times_array_Myr, i_relative_array * 180.0 / np.pi) + plot_i_relative.set_xlim(0, t_max_Myr) + plot_i_relative.set_ylim( + 0.9 * min(i_relative_array * 180.0 / np.pi), + 1.1 * max(i_relative_array * 180.0 / np.pi), + ) + plot_i_relative.set_xlabel(r"$t/\mathrm{Myr}$") + plot_i_relative.set_ylabel(r"$i_\mathrm{relative} ({}^\circ)$") - figure = plt.figure(figsize=(10,13), tight_layout=True) - N_subplots = 4 - - plot_e_in = figure.add_subplot(N_subplots,1,1) - plot_e_out = figure.add_subplot(N_subplots,1,2) - plot_i_relative = figure.add_subplot(N_subplots,1,3) - plot_a_in = figure.add_subplot(N_subplots,1,4) - - plot_e_in.plot(times_array_Myr,e_in_array, label= '$e_\mathrm{in}$') - plot_e_in.set_xlim(0,t_max_Myr) - plot_e_in.set_xlabel('$t/\mathrm{Myr}$') - plot_e_in.set_ylabel('$e$') - plot_e_in.legend(loc=0) + plot_a_in.plot(times_array_Myr, a_in_array_AU) + plot_a_in.set_xlabel(r"$t/\mathrm{Myr}$") + plot_a_in.set_ylabel(r"$a_\mathrm{in}$") - plot_e_out.plot(times_array_Myr,e_out_array, label= '$e_\mathrm{out}$') - plot_e_out.set_xlim(0,t_max_Myr) - plot_e_out.set_xlabel('$t/\mathrm{Myr}$') - plot_e_out.set_ylabel('$e$') - plot_e_out.legend(loc=0) + plot_a_out.plot(times_array_Myr, a_out_array_AU) + plot_a_out.set_xlabel(r"$t/\mathrm{Myr}$") + plot_a_out.set_ylabel(r"$a_\mathrm{out}$") - - plot_i_relative.plot(times_array_Myr,i_relative_array*180.0/np.pi) - plot_i_relative.set_xlim(0,t_max_Myr) - plot_i_relative.set_ylim(0.9*min(i_relative_array*180.0/np.pi),1.1*max(i_relative_array*180.0/np.pi)) - plot_i_relative.set_xlabel('$t/\mathrm{Myr}$') - plot_i_relative.set_ylabel('$i_\mathrm{relative} ({}^\circ)$') - - plot_a_in.plot(times_array_Myr,a_in_array_AU) - plot_a_in.set_xlabel('$t/\mathrm{Myr}$') - plot_a_in.set_ylabel('$a_\mathrm{in}$') - - figure.subplots_adjust(left=0.2, right=0.85, top=0.8, bottom=0.15) - plt.savefig(dir_plots+'TRES2'+generic_name+'.pdf') -# plt.show() + plt.savefig(dir_plots + "TRES" + generic_name + ".pdf") + # plt.show() plt.close() + figure = plt.figure(figsize=(10, 13), tight_layout=True) + n_subplots = 4 + plot_e_in = figure.add_subplot(n_subplots, 1, 1) + plot_e_out = figure.add_subplot(n_subplots, 1, 2) + plot_i_relative = figure.add_subplot(n_subplots, 1, 3) + plot_a_in = figure.add_subplot(n_subplots, 1, 4) + plot_e_in.plot(times_array_Myr, e_in_array, label=r"$e_\mathrm{in}$") + plot_e_in.set_xlim(0, t_max_Myr) + plot_e_in.set_xlabel(r"$t/\mathrm{Myr}$") + plot_e_in.set_ylabel("$e$") + plot_e_in.legend(loc=0) + plot_e_out.plot(times_array_Myr, e_out_array, label=r"$e_\mathrm{out}$") + plot_e_out.set_xlim(0, t_max_Myr) + plot_e_out.set_xlabel(r"$t/\mathrm{Myr}$") + plot_e_out.set_ylabel("$e$") + plot_e_out.legend(loc=0) - figure = plt.figure(figsize=(10,13), tight_layout=True) - N_subplots = 4 - - plot_e_in = figure.add_subplot(N_subplots,1,1) - plot_i_relative = figure.add_subplot(N_subplots,1,2) - plot_e_in_g_in = figure.add_subplot(N_subplots,1,3) - plot_a_in = figure.add_subplot(N_subplots,1,4) - - - plot_e_in.plot(times_array_Myr,e_in_array) - plot_e_in.set_xlim(0,t_max_Myr) - plot_e_in.set_xlabel('$t/\mathrm{Myr}$') - plot_e_in.set_ylabel('$e_\mathrm{in}$') - - plot_i_relative.plot(times_array_Myr,i_relative_array*180.0/np.pi) - plot_i_relative.set_xlim(0,t_max_Myr) - plot_i_relative.set_ylim(0.9*min(i_relative_array*180.0/np.pi),1.1*max(i_relative_array*180.0/np.pi)) - plot_i_relative.set_xlabel('$t/\mathrm{Myr}$') - plot_i_relative.set_ylabel('$i_\mathrm{relative} ({}^\circ)$') + plot_i_relative.plot(times_array_Myr, i_relative_array * 180.0 / np.pi) + plot_i_relative.set_xlim(0, t_max_Myr) + plot_i_relative.set_ylim( + 0.9 * min(i_relative_array * 180.0 / np.pi), + 1.1 * max(i_relative_array * 180.0 / np.pi), + ) + plot_i_relative.set_xlabel(r"$t/\mathrm{Myr}$") + plot_i_relative.set_ylabel(r"$i_\mathrm{relative} ({}^\circ)$") - plot_e_in_g_in.plot(np.cos(g_in_array),e_in_array) - plot_e_in_g_in.set_xlabel('$\cos(g_\mathrm{in})$') - plot_e_in_g_in.set_ylabel('$e_\mathrm{in}$') + plot_a_in.plot(times_array_Myr, a_in_array_AU) + plot_a_in.set_xlabel(r"$t/\mathrm{Myr}$") + plot_a_in.set_ylabel(r"$a_\mathrm{in}$") - plot_a_in.plot(times_array_Myr,a_in_array_AU) - plot_a_in.set_xlabel('$t/\mathrm{Myr}$') - plot_a_in.set_ylabel('$a_\mathrm{in}$') figure.subplots_adjust(left=0.2, right=0.85, top=0.8, bottom=0.15) - - plt.savefig(dir_plots+'TRES_inner_orbit'+generic_name+'.pdf') -# plt.show() + plt.savefig(dir_plots + "TRES2" + generic_name + ".pdf") + # plt.show() plt.close() + figure = plt.figure(figsize=(10, 13), tight_layout=True) + n_subplots = 4 + + plot_e_in = figure.add_subplot(n_subplots, 1, 1) + plot_i_relative = figure.add_subplot(n_subplots, 1, 2) + plot_e_in_g_in = figure.add_subplot(n_subplots, 1, 3) + plot_a_in = figure.add_subplot(n_subplots, 1, 4) + + plot_e_in.plot(times_array_Myr, e_in_array) + plot_e_in.set_xlim(0, t_max_Myr) + plot_e_in.set_xlabel(r"$t/\mathrm{Myr}$") + plot_e_in.set_ylabel(r"$e_\mathrm{in}$") + + plot_i_relative.plot(times_array_Myr, i_relative_array * 180.0 / np.pi) + plot_i_relative.set_xlim(0, t_max_Myr) + plot_i_relative.set_ylim( + 0.9 * min(i_relative_array * 180.0 / np.pi), + 1.1 * max(i_relative_array * 180.0 / np.pi), + ) + plot_i_relative.set_xlabel(r"$t/\mathrm{Myr}$") + plot_i_relative.set_ylabel(r"$i_\mathrm{relative} ({}^\circ)$") + + plot_e_in_g_in.plot(np.cos(g_in_array), e_in_array) + plot_e_in_g_in.set_xlabel(r"$\cos(g_\mathrm{in})$") + plot_e_in_g_in.set_ylabel(r"$e_\mathrm{in}$") + + plot_a_in.plot(times_array_Myr, a_in_array_AU) + plot_a_in.set_xlabel(r"$t/\mathrm{Myr}$") + plot_a_in.set_ylabel(r"$a_\mathrm{in}$") + figure.subplots_adjust(left=0.2, right=0.85, top=0.8, bottom=0.15) - dyn_inst = 2.8 / (1-e_out_array) * (1-0.3*i_relative_array/np.pi) * ((1+m3_array/(m1_array+m2_array))*(1+e_out_array)/(np.sqrt(1-e_out_array)))**0.4 / (a_out_array_AU/a_in_array_AU) - oct = (m1_array-m2_array)/(m1_array+m2_array) * a_in_array_AU/a_out_array_AU * e_out_array/(1-e_out_array**2) - semiseq = (5.*np.pi* m3_array/(m1_array+m2_array) * (a_in_array_AU/a_out_array_AU/(1-e_out_array))**3)/ np.sqrt(1-e_in_array) + plt.savefig(dir_plots + "TRES_inner_orbit" + generic_name + ".pdf") + # plt.show() + plt.close() - plt.semilogy(times_array_Myr, dyn_inst, '.') - plt.semilogy(times_array_Myr, oct, '.') - plt.semilogy(times_array_Myr, semiseq, '.') - plt.xlabel('t (Myr)') - plt.ylabel('stability,oct and semiseq') + dyn_inst = ( + 2.8 + / (1 - e_out_array) + * (1 - 0.3 * i_relative_array / np.pi) + * ( + (1 + m3_array / (m1_array + m2_array)) + * (1 + e_out_array) + / (np.sqrt(1 - e_out_array)) + ) + ** 0.4 + / (a_out_array_AU / a_in_array_AU) + ) + octupole = ( + (m1_array - m2_array) + / (m1_array + m2_array) + * a_in_array_AU + / a_out_array_AU + * e_out_array + / (1 - e_out_array**2) + ) + semiseq = ( + 5.0 + * np.pi + * m3_array + / (m1_array + m2_array) + * (a_in_array_AU / a_out_array_AU / (1 - e_out_array)) ** 3 + ) / np.sqrt(1 - e_in_array) + + plt.semilogy(times_array_Myr, dyn_inst, ".") + plt.semilogy(times_array_Myr, octupole, ".") + plt.semilogy(times_array_Myr, semiseq, ".") + plt.xlabel("t (Myr)") + plt.ylabel("stability, oct and semiseq") plt.legend(loc=0) - plt.savefig(dir_plots+'dyn_time'+generic_name+'.pdf') -# plt.show() + plt.savefig(dir_plots + "dyn_time" + generic_name + ".pdf") + # plt.show() plt.close() - plt.plot(times_array_Myr,e_in_array) - plt.plot(times_array_Myr,e_in_array, '.') - plt.xlim(0,t_max_Myr) - plt.xlabel('$t/\mathrm{Myr}$') - plt.ylabel('$e_\mathrm{in}$') - plt.savefig(dir_plots+'e_in_time'+generic_name+'.pdf') -# plt.show() + plt.plot(times_array_Myr, e_in_array) + plt.plot(times_array_Myr, e_in_array, ".") + plt.xlim(0, t_max_Myr) + plt.xlabel(r"$t/\mathrm{Myr}$") + plt.ylabel(r"$e_\mathrm{in}$") + plt.savefig(dir_plots + "e_in_time" + generic_name + ".pdf") + # plt.show() plt.close() - - plt.plot(times_array_Myr,e_in_array) - plt.plot(times_array_Myr,e_in_array, '.') - plt.plot(times_array_Myr,e_out_array) - plt.plot(times_array_Myr,e_out_array, '.') - plt.xlim(0,t_max_Myr) - plt.xlabel('$t/\mathrm{Myr}$') - plt.ylabel('$e_\mathrm{in}$') - plt.savefig(dir_plots+'e_time'+generic_name+'.pdf') -# plt.show() - plt.close() - - plt.plot(times_array_Myr,g_in_array) - plt.plot(times_array_Myr,g_in_array, '.') - plt.plot(times_array_Myr,g_out_array) - plt.plot(times_array_Myr,g_out_array, '.') - plt.xlim(0,t_max_Myr) - plt.xlabel('$t/\mathrm{Myr}$') - plt.ylabel('$g_\mathrm{in}$') - plt.savefig(dir_plots+'g_time'+generic_name+'.pdf') -# plt.show() - plt.close() - - - plt.plot(e_in_array,(g_in_array%np.pi)/np.pi*180) - plt.plot(e_in_array,(g_in_array%np.pi)/np.pi*180, '.') -# plt.plot(e_out_array,g_out_array) -# plt.plot(e_out_array,g_out_array, '.') -# plt.xlim(0,1) - plt.xlabel('$e_\mathrm{in}$') - plt.ylabel('$g_\mathrm{in}$') - plt.savefig(dir_plots+'g_e_inner'+generic_name+'.pdf') -# plt.show() + plt.plot(times_array_Myr, e_in_array) + plt.plot(times_array_Myr, e_in_array, ".") + plt.plot(times_array_Myr, e_out_array) + plt.plot(times_array_Myr, e_out_array, ".") + plt.xlim(0, t_max_Myr) + plt.xlabel(r"$t/\mathrm{Myr}$") + plt.ylabel(r"$e_\mathrm{in}$") + plt.savefig(dir_plots + "e_time" + generic_name + ".pdf") + # plt.show() plt.close() - - - plt.plot(times_array_Myr,o_in_array) - plt.plot(times_array_Myr,o_in_array, '.') - plt.plot(times_array_Myr,o_out_array) - plt.plot(times_array_Myr,o_out_array, '.') - plt.xlim(0,t_max_Myr) - plt.xlabel('$t/\mathrm{Myr}$') - plt.ylabel('$o_\mathrm{in}$') - plt.savefig(dir_plots+'o_time'+generic_name+'.pdf') -# plt.show() + plt.plot(times_array_Myr, g_in_array) + plt.plot(times_array_Myr, g_in_array, ".") + plt.plot(times_array_Myr, g_out_array) + plt.plot(times_array_Myr, g_out_array, ".") + plt.xlim(0, t_max_Myr) + plt.xlabel(r"$t/\mathrm{Myr}$") + plt.ylabel(r"$g_\mathrm{in}$") + plt.savefig(dir_plots + "g_time" + generic_name + ".pdf") + # plt.show() plt.close() - -# a_in_final_theory = a_in_array_AU[0] * (m1_array[0] * m2_array[0] / m1_array / m2_array)**2 #stable mt - a_in_final_theory = a_in_array_AU[0] * (m1_array[0] + m2_array[0]) / (m1_array + m2_array)#wind - plt.plot(times_array_Myr,a_in_array_AU) - plt.plot(times_array_Myr,a_in_array_AU, '.') - plt.plot(times_array_Myr,a_in_final_theory) - plt.plot(times_array_Myr,a_in_final_theory, '.') - - plt.xlabel('$t/\mathrm{Myr}$') - plt.ylabel('$a_\mathrm{in}$') - plt.savefig(dir_plots+'semi_in_time'+generic_name+'.pdf') -# plt.show() + plt.plot(e_in_array, (g_in_array % np.pi) / np.pi * 180) + plt.plot(e_in_array, (g_in_array % np.pi) / np.pi * 180, ".") + # plt.plot(e_out_array,g_out_array) + # plt.plot(e_out_array,g_out_array, '.') + # plt.xlim(0,1) + plt.xlabel(r"$e_\mathrm{in}$") + plt.ylabel(r"$g_\mathrm{in}$") + plt.savefig(dir_plots + "g_e_inner" + generic_name + ".pdf") + # plt.show() plt.close() - - - constants = 6283728.92847 # constants.G #in au and solar mass per Myr - corot_spin_inner = 1./np.sqrt(a_in_array_AU**3/(m1_array+m2_array))*constants - corot_spin_outer = 1./np.sqrt(a_out_array_AU**3/(m1_array+m2_array+m3_array))*constants - RSun_in_AU = 0.00464913034382 - critical_rot_1 = constants*np.sqrt(m1_array/(RSun_in_AU*r1_array)**3) - critical_rot_2 = constants*np.sqrt(m2_array/(RSun_in_AU*r2_array)**3) - critical_rot_3 = constants*np.sqrt(m3_array/(RSun_in_AU*r3_array)**3) - - plt.plot(times_array_Myr,spin1_array, 'b-') - plt.plot(times_array_Myr,spin1_array, 'b.') - plt.plot(times_array_Myr,spin2_array, 'g-') - plt.plot(times_array_Myr,spin2_array, 'g.') - plt.plot(times_array_Myr,spin3_array, 'r-') - plt.plot(times_array_Myr,spin3_array, 'r.') - - plt.plot(times_array_Myr,corot_spin_inner, 'c-') - plt.plot(times_array_Myr,corot_spin_inner, 'c,') - plt.plot(times_array_Myr,corot_spin_outer, 'm-') - plt.plot(times_array_Myr,corot_spin_outer, 'm,') - - plt.plot(times_array_Myr,critical_rot_1, 'y-') - plt.plot(times_array_Myr,critical_rot_1, 'y,') - plt.plot(times_array_Myr,critical_rot_2, 'k-') - plt.plot(times_array_Myr,critical_rot_2, 'k,') - plt.plot(times_array_Myr,critical_rot_3, 'k-') - plt.plot(times_array_Myr,critical_rot_3, 'ko') - - - plt.xlabel('$t/\mathrm{Myr}$') - plt.ylabel('$spin$') - plt.savefig(dir_plots+'spin_time'+generic_name+'.pdf') -# plt.show() + plt.plot(times_array_Myr, o_in_array) + plt.plot(times_array_Myr, o_in_array, ".") + plt.plot(times_array_Myr, o_out_array) + plt.plot(times_array_Myr, o_out_array, ".") + plt.xlim(0, t_max_Myr) + plt.xlabel(r"$t/\mathrm{Myr}$") + plt.ylabel(r"$o_\mathrm{in}$") + plt.savefig(dir_plots + "o_time" + generic_name + ".pdf") + # plt.show() plt.close() + # a_in_final_theory = a_in_array_AU[0] * (m1_array[0] * m2_array[0] / m1_array / m2_array)**2 #stable mt + a_in_final_theory = ( + a_in_array_AU[0] * (m1_array[0] + m2_array[0]) / (m1_array + m2_array) + ) # wind + plt.plot(times_array_Myr, a_in_array_AU) + plt.plot(times_array_Myr, a_in_array_AU, ".") + plt.plot(times_array_Myr, a_in_final_theory) + plt.plot(times_array_Myr, a_in_final_theory, ".") + + plt.xlabel(r"$t/\mathrm{Myr}$") + plt.ylabel(r"$a_\mathrm{in}$") + plt.savefig(dir_plots + "semi_in_time" + generic_name + ".pdf") + # plt.show() + plt.close() + constants = 6283728.92847 # constants.G #in au and solar mass per Myr + corot_spin_inner = ( + 1.0 / np.sqrt(a_in_array_AU**3 / (m1_array + m2_array)) * constants + ) + corot_spin_outer = ( + 1.0 / np.sqrt(a_out_array_AU**3 / (m1_array + m2_array + m3_array)) * constants + ) + # FIXME SR: needs to be done with units! + # RSun_in_AU = 0.00464913034382 + rsun_in_au = (1 | units.RSun).value_in(units.au) + critical_rot_1 = constants * np.sqrt(m1_array / (rsun_in_au * r1_array) ** 3) + critical_rot_2 = constants * np.sqrt(m2_array / (rsun_in_au * r2_array) ** 3) + critical_rot_3 = constants * np.sqrt(m3_array / (rsun_in_au * r3_array) ** 3) + + plt.plot(times_array_Myr, spin1_array, "b-") + plt.plot(times_array_Myr, spin1_array, "b.") + plt.plot(times_array_Myr, spin2_array, "g-") + plt.plot(times_array_Myr, spin2_array, "g.") + plt.plot(times_array_Myr, spin3_array, "r-") + plt.plot(times_array_Myr, spin3_array, "r.") + + plt.plot(times_array_Myr, corot_spin_inner, "c-") + plt.plot(times_array_Myr, corot_spin_inner, "c,") + plt.plot(times_array_Myr, corot_spin_outer, "m-") + plt.plot(times_array_Myr, corot_spin_outer, "m,") + + plt.plot(times_array_Myr, critical_rot_1, "y-") + plt.plot(times_array_Myr, critical_rot_1, "y,") + plt.plot(times_array_Myr, critical_rot_2, "k-") + plt.plot(times_array_Myr, critical_rot_2, "k,") + plt.plot(times_array_Myr, critical_rot_3, "k-") + plt.plot(times_array_Myr, critical_rot_3, "ko") + + plt.xlabel(r"$t/\mathrm{Myr}$") + plt.ylabel(r"$spin$") + plt.savefig(dir_plots + "spin_time" + generic_name + ".pdf") + # plt.show() + plt.close() -# ms = 1|units.MSun -# rs = 1|units.AU -# J2 = ms**3 * rs * constants.G -# J = np.sqrt(J2) -# print(J) #2.9071938904e+11 [RSun**2 * MSun * Myr**-1] - -# rs = 1|units.RSun -# print(J) #19822565357. [RSun**2 * MSun * Myr**-1] - - constants_Jorb = 2.9071938904e+11 #[RSun**2 * MSun * Myr**-1] - J_orb2 = m1_array**2 * m2_array**2 / (m1_array+m2_array) * a_in_array_AU * ( 1-e_in_array**2) - J_orb = np.sqrt(J_orb2)*constants_Jorb - - J_spin1 = spin1_array * moi1_array - J_spin2 = spin2_array * moi2_array - J_spin3 = spin3_array * moi3_array + # ms = 1|units.MSun + # rs = 1|units.AU + # J2 = ms**3 * rs * constants.G + # J = np.sqrt(J2) + # print(J) #2.9071938904e+11 [RSun**2 * MSun * Myr**-1] + + # rs = 1|units.RSun + # print(J) #19822565357. [RSun**2 * MSun * Myr**-1] + + constants_Jorb = 2.9071938904e11 # [RSun**2 * MSun * Myr**-1] + J_orb2 = ( + m1_array**2 + * m2_array**2 + / (m1_array + m2_array) + * a_in_array_AU + * (1 - e_in_array**2) + ) + J_orb = np.sqrt(J_orb2) * constants_Jorb + + J_spin1 = spin1_array * moi1_array + J_spin2 = spin2_array * moi2_array + J_spin3 = spin3_array * moi3_array plt.plot(times_array_Myr, J_orb) - plt.plot(times_array_Myr,J_orb, '.') - plt.xlabel('$t/\mathrm{Myr}$') - plt.ylabel('$J orbit$') - plt.savefig(dir_plots+'Jorbit_time'+generic_name+'.pdf') -# plt.show() + plt.plot(times_array_Myr, J_orb, ".") + plt.xlabel(r"$t/\mathrm{Myr}$") + plt.ylabel(r"$J orbit$") + plt.savefig(dir_plots + "Jorbit_time" + generic_name + ".pdf") + # plt.show() plt.close() - plt.plot(times_array_Myr,J_spin1) - plt.plot(times_array_Myr,J_spin1, '.') - plt.plot(times_array_Myr,J_spin2) - plt.plot(times_array_Myr,J_spin2, '.') - plt.plot(times_array_Myr,J_spin3) - plt.plot(times_array_Myr,J_spin3, '.') - plt.xlabel('$t/\mathrm{Myr}$') - plt.ylabel('$J spin$') - plt.savefig(dir_plots+'Jspin_time'+generic_name+'.pdf') -# plt.show() + plt.plot(times_array_Myr, J_spin1) + plt.plot(times_array_Myr, J_spin1, ".") + plt.plot(times_array_Myr, J_spin2) + plt.plot(times_array_Myr, J_spin2, ".") + plt.plot(times_array_Myr, J_spin3) + plt.plot(times_array_Myr, J_spin3, ".") + plt.xlabel(r"$t/\mathrm{Myr}$") + plt.ylabel(r"$J spin$") + plt.savefig(dir_plots + "Jspin_time" + generic_name + ".pdf") + # plt.show() plt.close() - plt.plot(times_array_Myr, J_orb) - plt.plot(times_array_Myr,J_orb, '.') - plt.plot(times_array_Myr,J_spin1) - plt.plot(times_array_Myr,J_spin1, '.') - plt.plot(times_array_Myr,J_spin2) - plt.plot(times_array_Myr,J_spin2, '.') - plt.plot(times_array_Myr,J_spin3) - plt.plot(times_array_Myr,J_spin3, '.') - plt.xlabel('$t/\mathrm{Myr}$') - plt.ylabel('$J spin$') - plt.savefig(dir_plots+'Js_time'+generic_name+'.pdf') -# plt.show() + plt.plot(times_array_Myr, J_orb, ".") + plt.plot(times_array_Myr, J_spin1) + plt.plot(times_array_Myr, J_spin1, ".") + plt.plot(times_array_Myr, J_spin2) + plt.plot(times_array_Myr, J_spin2, ".") + plt.plot(times_array_Myr, J_spin3) + plt.plot(times_array_Myr, J_spin3, ".") + plt.xlabel(r"$t/\mathrm{Myr}$") + plt.ylabel(r"$J spin$") + plt.savefig(dir_plots + "Js_time" + generic_name + ".pdf") + # plt.show() plt.close() - plt.semilogy(times_array_Myr,moi1_array) - plt.semilogy(times_array_Myr,moi1_array, '.') - plt.semilogy(times_array_Myr,moi2_array) - plt.semilogy(times_array_Myr,moi2_array, '.') - plt.semilogy(times_array_Myr,moi3_array) - plt.semilogy(times_array_Myr,moi3_array, '.') - plt.xlabel('$t/\mathrm{Myr}$') - plt.ylabel('$moi$') - plt.savefig(dir_plots+'moment_of_inertia_time'+generic_name+'.pdf') -# plt.show() + plt.semilogy(times_array_Myr, moi1_array) + plt.semilogy(times_array_Myr, moi1_array, ".") + plt.semilogy(times_array_Myr, moi2_array) + plt.semilogy(times_array_Myr, moi2_array, ".") + plt.semilogy(times_array_Myr, moi3_array) + plt.semilogy(times_array_Myr, moi3_array, ".") + plt.xlabel(r"$t/\mathrm{Myr}$") + plt.ylabel(r"$moi$") + plt.savefig(dir_plots + "moment_of_inertia_time" + generic_name + ".pdf") + # plt.show() plt.close() - - - plt.semilogy(times_array_Myr,r1_array) - plt.semilogy(times_array_Myr,r1_array, '.') - plt.semilogy(times_array_Myr,r2_array) - plt.semilogy(times_array_Myr,r2_array, '.') - plt.semilogy(times_array_Myr,r3_array) - plt.semilogy(times_array_Myr,r3_array, '.') - plt.xlabel('$t/\mathrm{Myr}$') - plt.ylabel('$radius$') - plt.savefig(dir_plots+'radius_time'+generic_name+'.pdf') -# plt.show() + plt.semilogy(times_array_Myr, r1_array) + plt.semilogy(times_array_Myr, r1_array, ".") + plt.semilogy(times_array_Myr, r2_array) + plt.semilogy(times_array_Myr, r2_array, ".") + plt.semilogy(times_array_Myr, r3_array) + plt.semilogy(times_array_Myr, r3_array, ".") + plt.xlabel(r"$t/\mathrm{Myr}$") + plt.ylabel(r"$radius$") + plt.savefig(dir_plots + "radius_time" + generic_name + ".pdf") + # plt.show() plt.close() - - dr1_array =r1_array[1:]-r1_array[:-1] - dr2_array =r2_array[1:]-r2_array[:-1] - dr3_array =r3_array[1:]-r3_array[:-1] + + dr1_array = r1_array[1:] - r1_array[:-1] + dr2_array = r2_array[1:] - r2_array[:-1] + dr3_array = r3_array[1:] - r3_array[:-1] dt_array = times_array_Myr[1:] - times_array_Myr[:-1] - plt.semilogy(times_array_Myr[1:], dr1_array/dt_array) - plt.semilogy(times_array_Myr[1:], dr1_array/dt_array, 'b.') - plt.semilogy(times_array_Myr[1:], dr1_array/dt_array*-1., 'b*') - plt.semilogy(times_array_Myr[1:], dr2_array/dt_array) - plt.semilogy(times_array_Myr[1:], dr2_array/dt_array, 'g.') - plt.semilogy(times_array_Myr[1:], dr2_array/dt_array*-1., 'g*') - plt.semilogy(times_array_Myr[1:], dr3_array/dt_array) - plt.semilogy(times_array_Myr[1:], dr3_array/dt_array, 'r.') - plt.semilogy(times_array_Myr[1:], dr3_array/dt_array*-1., 'r*') - plt.xlabel('$t/\mathrm{Myr}$') - plt.ylabel('$dr/dt$') - plt.savefig(dir_plots+'drdt_time'+generic_name+'.pdf') -# plt.show() + plt.semilogy(times_array_Myr[1:], dr1_array / dt_array) + plt.semilogy(times_array_Myr[1:], dr1_array / dt_array, "b.") + plt.semilogy(times_array_Myr[1:], dr1_array / dt_array * -1.0, "b*") + plt.semilogy(times_array_Myr[1:], dr2_array / dt_array) + plt.semilogy(times_array_Myr[1:], dr2_array / dt_array, "g.") + plt.semilogy(times_array_Myr[1:], dr2_array / dt_array * -1.0, "g*") + plt.semilogy(times_array_Myr[1:], dr3_array / dt_array) + plt.semilogy(times_array_Myr[1:], dr3_array / dt_array, "r.") + plt.semilogy(times_array_Myr[1:], dr3_array / dt_array * -1.0, "r*") + plt.xlabel(r"$t/\mathrm{Myr}$") + plt.ylabel(r"$dr/dt$") + plt.savefig(dir_plots + "drdt_time" + generic_name + ".pdf") + # plt.show() plt.close() - - - - plt.semilogy(times_array_Myr[1:], dr1_array/r1_array[1:]) - plt.semilogy(times_array_Myr[1:], dr1_array/r1_array[1:], 'b.') - plt.semilogy(times_array_Myr[1:], -1.*dr1_array/r1_array[1:], 'b*') - plt.semilogy(times_array_Myr[1:], dr2_array/r2_array[1:]) - plt.semilogy(times_array_Myr[1:], dr2_array/r2_array[1:], 'g.') - plt.semilogy(times_array_Myr[1:], -1.*dr2_array/r2_array[1:], 'g*') - plt.semilogy(times_array_Myr[1:], dr3_array/r3_array[1:]) - plt.semilogy(times_array_Myr[1:], dr3_array/r3_array[1:], 'r.') - plt.semilogy(times_array_Myr[1:], -1.*dr3_array/r3_array[1:], 'r*') - plt.xlabel('$t/\mathrm{Myr}$') - plt.ylabel('$dr/r$') - plt.savefig(dir_plots+'dr_time'+generic_name+'.pdf') -# plt.show() + plt.semilogy(times_array_Myr[1:], dr1_array / r1_array[1:]) + plt.semilogy(times_array_Myr[1:], dr1_array / r1_array[1:], "b.") + plt.semilogy(times_array_Myr[1:], -1.0 * dr1_array / r1_array[1:], "b*") + plt.semilogy(times_array_Myr[1:], dr2_array / r2_array[1:]) + plt.semilogy(times_array_Myr[1:], dr2_array / r2_array[1:], "g.") + plt.semilogy(times_array_Myr[1:], -1.0 * dr2_array / r2_array[1:], "g*") + plt.semilogy(times_array_Myr[1:], dr3_array / r3_array[1:]) + plt.semilogy(times_array_Myr[1:], dr3_array / r3_array[1:], "r.") + plt.semilogy(times_array_Myr[1:], -1.0 * dr3_array / r3_array[1:], "r*") + plt.xlabel(r"$t/\mathrm{Myr}$") + plt.ylabel(r"$dr/r$") + plt.savefig(dir_plots + "dr_time" + generic_name + ".pdf") + # plt.show() plt.close() + dm1_array = m1_array[:-1] - m1_array[1:] + dm2_array = m2_array[:-1] - m2_array[1:] + dm3_array = m3_array[:-1] - m3_array[1:] - - dm1_array =m1_array[:-1]-m1_array[1:] - dm2_array =m2_array[:-1]-m2_array[1:] - dm3_array =m3_array[:-1]-m3_array[1:] - plt.plot(times_array_Myr[1:], m1_array[1:]) - plt.plot(times_array_Myr[1:], m1_array[1:], '.') + plt.plot(times_array_Myr[1:], m1_array[1:], ".") plt.plot(times_array_Myr[1:], m2_array[1:]) - plt.plot(times_array_Myr[1:], m2_array[1:], '.') + plt.plot(times_array_Myr[1:], m2_array[1:], ".") plt.plot(times_array_Myr[1:], m3_array[1:]) - plt.plot(times_array_Myr[1:], m3_array[1:], '.') - plt.xlabel('$t/\mathrm{Myr}$') - plt.ylabel('$mass$') - plt.savefig(dir_plots+'mass_time'+generic_name+'.pdf') -# plt.show() + plt.plot(times_array_Myr[1:], m3_array[1:], ".") + plt.xlabel(r"$t/\mathrm{Myr}$") + plt.ylabel(r"$mass$") + plt.savefig(dir_plots + "mass_time" + generic_name + ".pdf") + # plt.show() plt.close() + # plt.semilogy(times_array_Myr[1:], dm1_array/dt_array) + # plt.semilogy(times_array_Myr[1:], dm1_array/dt_array, '.') + # plt.semilogy(times_array_Myr[1:], dm2_array/dt_array) + # plt.semilogy(times_array_Myr[1:], dm2_array/dt_array, '.') + # plt.semilogy(times_array_Myr[1:], dm3_array/dt_array) + # plt.semilogy(times_array_Myr[1:], dm3_array/dt_array, '.') + # plt.xlabel('$t/\mathrm{Myr}$') + # plt.ylabel('$dm/dt$') + # plt.savefig(dir_plots+'dmdt_time'+generic_name+'.pdf') + # plt.show() + # plt.close() + + # + # plt.semilogy(times_array_Myr[1:], dm1_array/m1_array[1:]) + # plt.semilogy(times_array_Myr[1:], dm1_array/m1_array[1:], '.') + # plt.semilogy(times_array_Myr[1:], dm2_array/m2_array[1:]) + # plt.semilogy(times_array_Myr[1:], dm2_array/m2_array[1:], '.') + # plt.semilogy(times_array_Myr[1:], dm3_array/m3_array[1:]) + # plt.semilogy(times_array_Myr[1:], dm3_array/m3_array[1:], '.') + # plt.xlabel('$t/\mathrm{Myr}$') + # plt.ylabel('$dm/m$') + # plt.savefig(dir_plots+'dm_time'+generic_name+'.pdf') + # plt.show() + # plt.close() -# plt.semilogy(times_array_Myr[1:], dm1_array/dt_array) -# plt.semilogy(times_array_Myr[1:], dm1_array/dt_array, '.') -# plt.semilogy(times_array_Myr[1:], dm2_array/dt_array) -# plt.semilogy(times_array_Myr[1:], dm2_array/dt_array, '.') -# plt.semilogy(times_array_Myr[1:], dm3_array/dt_array) -# plt.semilogy(times_array_Myr[1:], dm3_array/dt_array, '.') -# plt.xlabel('$t/\mathrm{Myr}$') -# plt.ylabel('$dm/dt$') -# plt.savefig(dir_plots+'dmdt_time'+generic_name+'.pdf') -# plt.show() -# plt.close() - -# -# plt.semilogy(times_array_Myr[1:], dm1_array/m1_array[1:]) -# plt.semilogy(times_array_Myr[1:], dm1_array/m1_array[1:], '.') -# plt.semilogy(times_array_Myr[1:], dm2_array/m2_array[1:]) -# plt.semilogy(times_array_Myr[1:], dm2_array/m2_array[1:], '.') -# plt.semilogy(times_array_Myr[1:], dm3_array/m3_array[1:]) -# plt.semilogy(times_array_Myr[1:], dm3_array/m3_array[1:], '.') -# plt.xlabel('$t/\mathrm{Myr}$') -# plt.ylabel('$dm/m$') -# plt.savefig(dir_plots+'dm_time'+generic_name+'.pdf') -# plt.show() -# plt.close() - - plt.semilogy(times_array_Myr[1:], dt_array) - plt.semilogy(times_array_Myr[1:], dt_array, '.') + plt.semilogy(times_array_Myr[1:], dt_array, ".") plt.semilogy(times_array_Myr[1:], dt_array) - plt.semilogy(times_array_Myr[1:], dt_array, '.') + plt.semilogy(times_array_Myr[1:], dt_array, ".") plt.semilogy(times_array_Myr[1:], dt_array) - plt.semilogy(times_array_Myr[1:], dt_array, '.') - plt.xlabel('$t/\mathrm{Myr}$') - plt.ylabel('$dt$') - plt.savefig(dir_plots+'dt_time'+generic_name+'.pdf') -# plt.show() + plt.semilogy(times_array_Myr[1:], dt_array, ".") + plt.xlabel(r"$t/\mathrm{Myr}$") + plt.ylabel(r"$dt$") + plt.savefig(dir_plots + "dt_time" + generic_name + ".pdf") + # plt.show() plt.close() - - RL1_frac = r1_array/RL1_array - RL2_frac = r2_array/RL2_array - RL3_frac = r3_array/RL3_array - plt.plot(times_array_Myr,RL1_frac) - plt.plot(times_array_Myr,RL1_frac, '.', label='Primary') - plt.plot(times_array_Myr,RL2_frac) - plt.plot(times_array_Myr,RL2_frac, '.', label='Secondary') - plt.plot(times_array_Myr,RL3_frac) - plt.plot(times_array_Myr,RL3_frac, '.', label='Tertiary') - plt.xlabel('$t/\mathrm{Myr}$') - plt.ylabel('r/RL') + RL1_frac = r1_array / RL1_array + RL2_frac = r2_array / RL2_array + RL3_frac = r3_array / RL3_array + plt.plot(times_array_Myr, RL1_frac) + plt.plot(times_array_Myr, RL1_frac, ".", label="Primary") + plt.plot(times_array_Myr, RL2_frac) + plt.plot(times_array_Myr, RL2_frac, ".", label="Secondary") + plt.plot(times_array_Myr, RL3_frac) + plt.plot(times_array_Myr, RL3_frac, ".", label="Tertiary") + plt.xlabel(r"$t/\mathrm{Myr}$") + plt.ylabel(r"r/RL") plt.legend(fontsize=12) - plt.savefig(dir_plots+'rl_frac_time'+generic_name+'.pdf') -# plt.show() + plt.savefig(dir_plots + "rl_frac_time" + generic_name + ".pdf") + # plt.show() plt.close() - - - plt.plot(times_array_Myr,delta_e_in_array) - plt.plot(times_array_Myr,delta_e_in_array, '.') - plt.xlabel('$t/\mathrm{Myr}$') - plt.ylabel('$\Delta e_{\mathrm{in}}$') - plt.savefig(dir_plots+'delta_e_in_time'+generic_name+'.pdf') -# plt.show() - plt.close() - - -# wind a = ai * Mti/Mt -# Mtot = m1_array+m2_array -# plt.plot(times_array_Myr,a_in_array_AU) -# plt.plot(times_array_Myr,a_in_array_AU, '.') -# plt.plot(times_array_Myr, a_in_array_AU[0]*Mtot[0]/Mtot) -# plt.plot(times_array_Myr, a_in_array_AU[0]*Mtot[0]/Mtot, '.') -# plt.plot(times_array_Myr[1:], a_in_array_AU[:-1]*Mtot[:-1]/Mtot[1:]) -# plt.plot(times_array_Myr[1:], a_in_array_AU[:-1]*Mtot[:-1]/Mtot[1:], '.') -# plt.xlabel('$t/\mathrm{Myr}$') -# plt.ylabel('$a_\mathrm{in}$') -# plt.savefig(dir_plots+'semi_inner_wind'+generic_name+'.pdf') -# plt.show() -# plt.close() -# -# plt.plot(times_array_Myr, a_in_array_AU[0]*Mtot[0]/Mtot/a_in_array_AU) -# plt.plot(times_array_Myr, a_in_array_AU[0]*Mtot[0]/Mtot/a_in_array_AU, '.') -# plt.ylabel('$relative error a_\mathrm{in}$') -# plt.xlabel('$t/\mathrm{Myr}$') -# plt.savefig(dir_plots+'semi_inner_rel_wind'+generic_name+'.pdf') -# plt.show() -# plt.close() - - -# cons mt a = ai * (m1i*m2i*/m1/m2)**2 -# plt.plot(times_array_Myr,a_in_array_AU, 'b-') -# plt.plot(times_array_Myr,a_in_array_AU, 'b.') -# plt.plot(times_array_Myr, a_in_array_AU[0]*(m1_array[0]*m2_array[0]/m1_array/m2_array)**2, 'g-') -# plt.plot(times_array_Myr, a_in_array_AU[0]*(m1_array[0]*m2_array[0]/m1_array/m2_array)**2, 'g.') -# plt.plot(times_array_Myr[1:], a_in_array_AU[:-1]*(m1_array[:-1]*m2_array[:-1]/m1_array[1:]/m2_array[1:])**2, 'r-') -# plt.plot(times_array_Myr[1:], a_in_array_AU[:-1]*(m1_array[:-1]*m2_array[:-1]/m1_array[1:]/m2_array[1:])**2, 'r.') -# plt.xlabel('$t/\mathrm{Myr}$') -# plt.ylabel('$a_\mathrm{in}$') -# plt.savefig(dir_plots+'semi_inner_cons_mt'+generic_name+'.pdf') -# plt.show() -# plt.close() -# -# plt.plot(times_array_Myr, a_in_array_AU[0]*(m1_array[0]*m2_array[0]/m1_array/m2_array)**2/a_in_array_AU) -# plt.plot(times_array_Myr, a_in_array_AU[0]*(m1_array[0]*m2_array[0]/m1_array/m2_array)**2/a_in_array_AU, '.') -# plt.ylabel('$relative error a_\mathrm{in}$') -# plt.xlabel('$t/\mathrm{Myr}$') -# plt.savefig(dir_plots+'semi_inner_rel_cons_mt'+generic_name+'.pdf') -# plt.show() -# plt.close() - - - -# dm = (m1_array[1:] - m1_array[:-1] ) -# dt = (times_array_Myr[1:] - times_array_Myr[:-1]) -# dmdt = (m1_array[1:] - m1_array[:-1] )/(times_array_Myr[1:] - times_array_Myr[:-1]) - -# plt.plot(dmdt, a_in_array_AU[0]*Mtot[0]/Mtot[1:]/a_in_array_AU[1:]) -# plt.plot(dmdt, a_in_array_AU[0]*Mtot[0]/Mtot[1:]/a_in_array_AU[1:], '.') -# plt.show() -# plt.close() -# -# plt.plot(dm, a_in_array_AU[0]*Mtot[0]/Mtot[1:]/a_in_array_AU[1:]) -# plt.plot(dm, a_in_array_AU[0]*Mtot[0]/Mtot[1:]/a_in_array_AU[1:], '.') -# plt.show() -# plt.close() -# -# plt.plot(dt, a_in_array_AU[0]*Mtot[0]/Mtot[1:]/a_in_array_AU[1:]) -# plt.plot(dt, a_in_array_AU[0]*Mtot[0]/Mtot[1:]/a_in_array_AU[1:], '.') -# plt.show() -# plt.close() -# - - - - - -# plt.plot(times_array_Myr, g_in_array*180.0/np.pi%360) -# plt.xlim(0, t_max_Myr) -# plt.xlabel('$t/\mathrm{Myr}$') -# plt.ylabel('$g_\mathrm{in}$') -# plt.show() -# plt.close() - -# plt.plot(times_array_Myr, np.cos(g_in_array)) -# plt.xlim(0, t_max_Myr) -# plt.xlabel('$t/\mathrm{Myr}$') -# plt.ylabel('$\cos(g_\mathrm{in})$') -# plt.show() -# plt.close() -# -# -# plt.plot(times_array_Myr, o_in_array*180.0/np.pi%360) -# plt.xlim(0, t_max_Myr) -# plt.xlabel('$t/\mathrm{Myr}$') -# plt.ylabel('$o_\mathrm{in}$') -# plt.show() -# plt.close() -# plt.plot(times_array_Myr, np.cos(o_in_array)) -# plt.xlim(0, t_max_Myr) -# plt.xlabel('$t/\mathrm{Myr}$') -# plt.ylabel('$\cos(o_\mathrm{in})$') -# plt.show() -# plt.close() - - - #outer binary - figure = plt.figure(figsize=(10,13)) - N_subplots = 4 - - plot_e_out = figure.add_subplot(N_subplots,1,1) - plot_i_relative2 = figure.add_subplot(N_subplots,1,2) - plot_e_out_g_out = figure.add_subplot(N_subplots,1,3) - plot_a_out = figure.add_subplot(N_subplots,1,4) - -# times_array_Myr = triple.plot_data.times_array.value_in(units.Myr) -# t_max_Myr = max(times_array_Myr) -# i_relative_array = triple.plot_data.i_relative_array - - plot_e_out.plot(times_array_Myr,e_out_array) - plot_e_out.set_xlim(0,t_max_Myr) - plot_e_out.set_xlabel('$t/\mathrm{Myr}$') - plot_e_out.set_ylabel('$e_\mathrm{out}$') - - plot_i_relative2.plot(times_array_Myr,i_relative_array*180.0/np.pi) - plot_i_relative2.set_xlim(0,t_max_Myr) - plot_i_relative2.set_ylim(0.9*min(i_relative_array*180.0/np.pi),1.1*max(i_relative_array*180.0/np.pi)) - plot_i_relative2.set_xlabel('$t/\mathrm{Myr}$') - plot_i_relative2.set_ylabel('$i_\mathrm{relative} ({}^\circ)$') - - plot_e_out_g_out.plot(np.cos(g_out_array),e_out_array) - plot_e_out_g_out.set_xlabel('$\cos(g_\mathrm{out})$') - plot_e_out_g_out.set_ylabel('$e_\mathrm{out}$') + plt.plot(times_array_Myr, delta_e_in_array) + plt.plot(times_array_Myr, delta_e_in_array, ".") + plt.xlabel(r"$t/\mathrm{Myr}$") + plt.ylabel(r"$\Delta e_{\mathrm{in}}$") + plt.savefig(dir_plots + "delta_e_in_time" + generic_name + ".pdf") + # plt.show() + plt.close() - plot_a_out.plot(times_array_Myr,a_out_array_AU) - plot_a_out.set_xlabel('$t/\mathrm{Myr}$') - plot_a_out.set_ylabel('$a_\mathrm{out}$') + # wind a = ai * Mti/Mt + # Mtot = m1_array+m2_array + # plt.plot(times_array_Myr,a_in_array_AU) + # plt.plot(times_array_Myr,a_in_array_AU, '.') + # plt.plot(times_array_Myr, a_in_array_AU[0]*Mtot[0]/Mtot) + # plt.plot(times_array_Myr, a_in_array_AU[0]*Mtot[0]/Mtot, '.') + # plt.plot(times_array_Myr[1:], a_in_array_AU[:-1]*Mtot[:-1]/Mtot[1:]) + # plt.plot(times_array_Myr[1:], a_in_array_AU[:-1]*Mtot[:-1]/Mtot[1:], '.') + # plt.xlabel('$t/\mathrm{Myr}$') + # plt.ylabel('$a_\mathrm{in}$') + # plt.savefig(dir_plots+'semi_inner_wind'+generic_name+'.pdf') + # plt.show() + # plt.close() + # + # plt.plot(times_array_Myr, a_in_array_AU[0]*Mtot[0]/Mtot/a_in_array_AU) + # plt.plot(times_array_Myr, a_in_array_AU[0]*Mtot[0]/Mtot/a_in_array_AU, '.') + # plt.ylabel('$relative error a_\mathrm{in}$') + # plt.xlabel('$t/\mathrm{Myr}$') + # plt.savefig(dir_plots+'semi_inner_rel_wind'+generic_name+'.pdf') + # plt.show() + # plt.close() + + # cons mt a = ai * (m1i*m2i*/m1/m2)**2 + # plt.plot(times_array_Myr,a_in_array_AU, 'b-') + # plt.plot(times_array_Myr,a_in_array_AU, 'b.') + # plt.plot(times_array_Myr, a_in_array_AU[0]*(m1_array[0]*m2_array[0]/m1_array/m2_array)**2, 'g-') + # plt.plot(times_array_Myr, a_in_array_AU[0]*(m1_array[0]*m2_array[0]/m1_array/m2_array)**2, 'g.') + # plt.plot(times_array_Myr[1:], a_in_array_AU[:-1]*(m1_array[:-1]*m2_array[:-1]/m1_array[1:]/m2_array[1:])**2, 'r-') + # plt.plot(times_array_Myr[1:], a_in_array_AU[:-1]*(m1_array[:-1]*m2_array[:-1]/m1_array[1:]/m2_array[1:])**2, 'r.') + # plt.xlabel('$t/\mathrm{Myr}$') + # plt.ylabel('$a_\mathrm{in}$') + # plt.savefig(dir_plots+'semi_inner_cons_mt'+generic_name+'.pdf') + # plt.show() + # plt.close() + # + # plt.plot(times_array_Myr, a_in_array_AU[0]*(m1_array[0]*m2_array[0]/m1_array/m2_array)**2/a_in_array_AU) + # plt.plot(times_array_Myr, a_in_array_AU[0]*(m1_array[0]*m2_array[0]/m1_array/m2_array)**2/a_in_array_AU, '.') + # plt.ylabel('$relative error a_\mathrm{in}$') + # plt.xlabel('$t/\mathrm{Myr}$') + # plt.savefig(dir_plots+'semi_inner_rel_cons_mt'+generic_name+'.pdf') + # plt.show() + # plt.close() + + # dm = (m1_array[1:] - m1_array[:-1] ) + # dt = (times_array_Myr[1:] - times_array_Myr[:-1]) + # dmdt = (m1_array[1:] - m1_array[:-1] )/(times_array_Myr[1:] - times_array_Myr[:-1]) + + # plt.plot(dmdt, a_in_array_AU[0]*Mtot[0]/Mtot[1:]/a_in_array_AU[1:]) + # plt.plot(dmdt, a_in_array_AU[0]*Mtot[0]/Mtot[1:]/a_in_array_AU[1:], '.') + # plt.show() + # plt.close() + # + # plt.plot(dm, a_in_array_AU[0]*Mtot[0]/Mtot[1:]/a_in_array_AU[1:]) + # plt.plot(dm, a_in_array_AU[0]*Mtot[0]/Mtot[1:]/a_in_array_AU[1:], '.') + # plt.show() + # plt.close() + # + # plt.plot(dt, a_in_array_AU[0]*Mtot[0]/Mtot[1:]/a_in_array_AU[1:]) + # plt.plot(dt, a_in_array_AU[0]*Mtot[0]/Mtot[1:]/a_in_array_AU[1:], '.') + # plt.show() + # plt.close() + # + + # plt.plot(times_array_Myr, g_in_array*180.0/np.pi%360) + # plt.xlim(0, t_max_Myr) + # plt.xlabel('$t/\mathrm{Myr}$') + # plt.ylabel('$g_\mathrm{in}$') + # plt.show() + # plt.close() + + # plt.plot(times_array_Myr, np.cos(g_in_array)) + # plt.xlim(0, t_max_Myr) + # plt.xlabel('$t/\mathrm{Myr}$') + # plt.ylabel('$\cos(g_\mathrm{in})$') + # plt.show() + # plt.close() + # + # + # plt.plot(times_array_Myr, o_in_array*180.0/np.pi%360) + # plt.xlim(0, t_max_Myr) + # plt.xlabel('$t/\mathrm{Myr}$') + # plt.ylabel('$o_\mathrm{in}$') + # plt.show() + # plt.close() + + # plt.plot(times_array_Myr, np.cos(o_in_array)) + # plt.xlim(0, t_max_Myr) + # plt.xlabel('$t/\mathrm{Myr}$') + # plt.ylabel('$\cos(o_\mathrm{in})$') + # plt.show() + # plt.close() + + # outer binary + figure = plt.figure(figsize=(10, 13)) + n_subplots = 4 + + plot_e_out = figure.add_subplot(n_subplots, 1, 1) + plot_i_relative2 = figure.add_subplot(n_subplots, 1, 2) + plot_e_out_g_out = figure.add_subplot(n_subplots, 1, 3) + plot_a_out = figure.add_subplot(n_subplots, 1, 4) + + # times_array_Myr = triple.plot_data.times_array.value_in(units.Myr) + # t_max_Myr = max(times_array_Myr) + # i_relative_array = triple.plot_data.i_relative_array + + plot_e_out.plot(times_array_Myr, e_out_array) + plot_e_out.set_xlim(0, t_max_Myr) + plot_e_out.set_xlabel(r"$t/\mathrm{Myr}$") + plot_e_out.set_ylabel(r"$e_\mathrm{out}$") + + plot_i_relative2.plot(times_array_Myr, i_relative_array * 180.0 / np.pi) + plot_i_relative2.set_xlim(0, t_max_Myr) + plot_i_relative2.set_ylim( + 0.9 * min(i_relative_array * 180.0 / np.pi), + 1.1 * max(i_relative_array * 180.0 / np.pi), + ) + plot_i_relative2.set_xlabel(r"$t/\mathrm{Myr}$") + plot_i_relative2.set_ylabel(r"$i_\mathrm{relative} ({}^\circ)$") + + plot_e_out_g_out.plot(np.cos(g_out_array), e_out_array) + plot_e_out_g_out.set_xlabel(r"$\cos(g_\mathrm{out})$") + plot_e_out_g_out.set_ylabel(r"$e_\mathrm{out}$") + + plot_a_out.plot(times_array_Myr, a_out_array_AU) + plot_a_out.set_xlabel(r"$t/\mathrm{Myr}$") + plot_a_out.set_ylabel(r"$a_\mathrm{out}$") figure.subplots_adjust(left=0.2, right=0.85, top=0.8, bottom=0.15) - plt.savefig(dir_plots+'TRES_outer_orbit'+generic_name+'.pdf') -# plt.show() + plt.savefig(dir_plots + "TRES_outer_orbit" + generic_name + ".pdf") + # plt.show() plt.close() - # plt.plot(times_array_Myr,e_out_array) # plt.xlim(0,t_max_Myr) # plt.xlabel('$t/\mathrm{Myr}$') @@ -688,7 +695,7 @@ def plot_function(triple, dir_plots): # plt.close() -# Mtott = m1_array+m2_array+m3_array +# Mtott = m1_array+m2_array+m3_array # plt.plot(times_array_Myr,a_out_array_AU) # plt.plot(times_array_Myr,a_out_array_AU, '.') # plt.plot(times_array_Myr, a_out_array_AU[0]*Mtott[0]/Mtott) @@ -750,7 +757,6 @@ def plot_function(triple, dir_plots): # plt.close() - # plt.plot(np.cos(g_out_array), e_in_array) # plt.xlabel('$\cos(g_\mathrm{out})$') # plt.ylabel('$e_\mathrm{in}$') @@ -802,5 +808,4 @@ def plot_function(triple, dir_plots): # plt.ylabel('$M/\mathrm{MSun}$') # plt.show() # plt.close() -# - \ No newline at end of file +# From a9674431699d49f9c2a8a70e56b8b302aded5142 Mon Sep 17 00:00:00 2001 From: Steven Rieder Date: Mon, 4 Nov 2024 13:43:49 +0100 Subject: [PATCH 14/30] refactor rdc_TRES scripts --- src/tres/rdc_TRES.py | 6 +- src/tres/rdc_TRES_csv.py | 1088 +++++++++++++++++++++++--------------- 2 files changed, 652 insertions(+), 442 deletions(-) diff --git a/src/tres/rdc_TRES.py b/src/tres/rdc_TRES.py index 0e44f42..ba4bc3d 100644 --- a/src/tres/rdc_TRES.py +++ b/src/tres/rdc_TRES.py @@ -1,10 +1,10 @@ +import io +import sys +import numpy as np from amuse.units import units, constants from amuse.io import write_set_to_file from amuse.io import read_set_from_file from amuse.support.console import set_printing_strategy -import numpy as np -import io -import sys minimum_time_step = 1.0e-9 | units.Myr diff --git a/src/tres/rdc_TRES_csv.py b/src/tres/rdc_TRES_csv.py index 62f15e5..eb89469 100644 --- a/src/tres/rdc_TRES_csv.py +++ b/src/tres/rdc_TRES_csv.py @@ -3,485 +3,695 @@ from amuse.io import read_set_from_file from amuse.support.console import set_printing_strategy import numpy as np -import io +import io import sys -import pandas as pd #only necessary when saving as csv -import os - -minimum_time_step = 1.e-9 |units.Myr - -star_type = { 'all': -1, - 'lm_ms': 0, - 'ms': 1, - 'hg': 2, - 'rgb': 3, - 'cheb': 4, - 'eagb': 5, - 'tpagb': 6, - 'agb':[5,6], - 'hems':7, - 'hehg':8, - 'hergb':9, - 'heg':[8,9], - 'hewd': 10, - 'cowd': 11, - 'onewd': 12, - 'wd': [10,11,12], - 'ns': 13, - 'bh': 14, - 'sn': 15, - 'unknown': 16, - 'prems': 17, - 'planet': 18, - 'bd': 19, - } - -bin_type = { 'all': -1, - 'unknown': 0, - 'merger': 1, - 'disintegrated': 2, - 'dynamical_instability': 3, - 'detached': 4, - 'contact': 5, - 'collision': 6, - 'semisecular': 7, - 'rlof': 8, #only used for stopping conditions - 'olof': 9, #only used for stopping conditions - 'stable_mass_transfer': 10, - 'common_envelope': 11, - 'common_envelope_energy_balance': 12, - 'common_envelope_angular_momentum_balance': 13, - 'double_common_envelope': 14, - } - -tr_type = { 'all': -1, - 'hierarchical': 0, - 'dynamical_instability': 1, - 'semisecular_regime': 2, - 'error_flag_secular': 3, - } - -lib_print_style = { 0: "No printing", #default - 1: "Printing", - 2: "Readable format", - 3: "Full particle" - } - -lib_parameter_style = { 0: "Full", # - 1: "TRES standard; selected parameters", #default - 2: "User specified selected parameters", - } - - - +import pandas as pd # only necessary when saving as csv +import os + +minimum_time_step = 1.0e-9 | units.Myr + +star_type = { + "all": -1, + "lm_ms": 0, + "ms": 1, + "hg": 2, + "rgb": 3, + "cheb": 4, + "eagb": 5, + "tpagb": 6, + "agb": [5, 6], + "hems": 7, + "hehg": 8, + "hergb": 9, + "heg": [8, 9], + "hewd": 10, + "cowd": 11, + "onewd": 12, + "wd": [10, 11, 12], + "ns": 13, + "bh": 14, + "sn": 15, + "unknown": 16, + "prems": 17, + "planet": 18, + "bd": 19, +} + +bin_type = { + "all": -1, + "unknown": 0, + "merger": 1, + "disintegrated": 2, + "dynamical_instability": 3, + "detached": 4, + "contact": 5, + "collision": 6, + "semisecular": 7, + "rlof": 8, # only used for stopping conditions + "olof": 9, # only used for stopping conditions + "stable_mass_transfer": 10, + "common_envelope": 11, + "common_envelope_energy_balance": 12, + "common_envelope_angular_momentum_balance": 13, + "double_common_envelope": 14, +} + +tr_type = { + "all": -1, + "hierarchical": 0, + "dynamical_instability": 1, + "semisecular_regime": 2, + "error_flag_secular": 3, +} + +lib_print_style = { + 0: "No printing", # default + 1: "Printing", + 2: "Readable format", + 3: "Full particle", +} + +lib_parameter_style = { + 0: "Full", # + 1: "TRES standard; selected parameters", # default + 2: "User specified selected parameters", +} + def print_particle(particle): - if particle.is_star: - print(particle) - else: - print(particle) - print_particle(particle.child1) - print_particle(particle.child2) - - - -def create_snapshot_for_dict(triple, parameter_style): - if parameter_style==0: #all available parameters - snapshot_props = { - 'system_ID': triple[0].number, - 'time_Myr': (triple[0].time).value_in(units.Myr), - 'incl': triple[0].relative_inclination, - 'dynamical_instabiity': int(triple[0].dynamical_instability), - 'kozai_type': triple[0].kozai_type, - 'error_flag_secular': triple[0].error_flag_secular, - 'CPU_time': triple[0].CPU_time, - 'delta_e_in': triple[0].delta_e_in, - 'max_delta_e_in': triple[0].max_delta_e_in, - - 'outer_bin_type': bin_type[triple[0].bin_type], - 'outer_mt_Stable': int(triple[0].is_mt_stable), - 'outer_semi_RSun': (triple[0].semimajor_axis).value_in(units.RSun), - 'outer_ecc': triple[0].eccentricity, - 'outer_aop': triple[0].argument_of_pericenter, - 'outer_loan': triple[0].longitude_of_ascending_node, - #'TripleMDotMSunYr': (triple[0].mass_transfer_rate).value_in(units.MSun/units.yr), - - 'inner_bin_type': bin_type[triple[0].child2.bin_type], - 'inner_mt_stable': int(triple[0].child2.is_mt_stable), - 'inner_semi_RSun': triple[0].child2.semimajor_axis.value_in(units.RSun), - 'inner_ecc': triple[0].child2.eccentricity, - 'inner_aop': triple[0].child2.argument_of_pericenter, - 'inner_loan': triple[0].child2.longitude_of_ascending_node, - - 'star1_is_donor': int(triple[0].child2.child1.is_donor), -# 'star1_is_OLOF': int(triple[0].child2.child1.is_OLOF), - 'star1_stellar_type': triple[0].child2.child1.stellar_type.value_in(units.stellar_type), - 'star1_mass_MSun': triple[0].child2.child1.mass.value_in(units.MSun), - 'star1_spin_Myr_inv': triple[0].child2.child1.spin_angular_frequency.value_in(1./units.Myr), - 'star1_rad_RSun': triple[0].child2.child1.radius.value_in(units.RSun), - 'star1_coremass_MSun': triple[0].child2.child1.core_mass.value_in(units.MSun), - 'star1_previous_mass_MSun': triple[0].child2.child1.previous_mass.value_in(units.MSun), - 'star1_luminosity_LSun': triple[0].child2.child1.luminosity.value_in(units.LSun), - 'star1_temperature_K': triple[0].child2.child1.temperature.value_in(units.K), - - 'star2_is_donor': int(triple[0].child2.child2.is_donor), -# 'star2_is_OLOF': int(triple[0].child2.child2.is_OLOF), - 'star2_stellar_type': triple[0].child2.child2.stellar_type.value_in(units.stellar_type), - 'star2_mass_MSun': triple[0].child2.child2.mass.value_in(units.MSun), - 'star2_spin_Myr_inv': triple[0].child2.child2.spin_angular_frequency.value_in(1./units.Myr), - 'star2_rad_RSun': triple[0].child2.child2.radius.value_in(units.RSun), - 'star2_coremass_MSun': triple[0].child2.child2.core_mass.value_in(units.MSun), - 'star2_previous_mass_MSun': triple[0].child2.child2.previous_mass.value_in(units.MSun), - 'star2_luminosity_LSun': triple[0].child2.child2.luminosity.value_in(units.LSun), - 'star2_temperature_K': triple[0].child2.child2.temperature.value_in(units.K), - - 'star3_is_donor': int(triple[0].child1.is_donor), -# 'star3_is_OLOF': int(triple[0].child1.is_OLOF), - 'star3_stellar_type': triple[0].child1.stellar_type.value_in(units.stellar_type), - 'star3_mass_MSun': triple[0].child1.mass.value_in(units.MSun), - 'star3_spin_Myr_inv': triple[0].child1.spin_angular_frequency.value_in(1./units.Myr), - 'star3_rad_RSun': triple[0].child1.radius.value_in(units.RSun), - 'star3_coremass_MSun': triple[0].child1.core_mass.value_in(units.MSun), - 'star3_previous_mass_MSun': triple[0].child1.previous_mass.value_in(units.MSun), - 'star3_luminosity_LSun': triple[0].child1.luminosity.value_in(units.LSun), - 'star3_temperature_K': triple[0].child1.temperature.value_in(units.K), - - } - - elif parameter_style==2: - #User selected parameters - select by commenting / uncommenting lines - snapshot_props = { - 'system_ID': triple[0].number, - 'time_Myr': (triple[0].time).value_in(units.Myr), - 'incl': triple[0].relative_inclination, - 'dynamical_instabiity': int(triple[0].dynamical_instability), - 'kozai_type': triple[0].kozai_type, - 'error_flag_secular': triple[0].error_flag_secular, - 'CPU_time': triple[0].CPU_time, -# 'delta_e_in': triple[0].delta_e_in, -# 'max_delta_e_in': triple[0].max_delta_e_in, - - 'outer_bin_type': bin_type[triple[0].bin_type], -# 'outer_mt_Stable': int(triple[0].is_mt_stable), - 'outer_semi_RSun': (triple[0].semimajor_axis).value_in(units.RSun), - 'outer_ecc': triple[0].eccentricity, - 'outer_aop': triple[0].argument_of_pericenter, - 'outer_loan': triple[0].longitude_of_ascending_node, - #'TripleMDotMSunYr': (triple[0].mass_transfer_rate).value_in(units.MSun/units.yr), - - 'inner_bin_type': bin_type[triple[0].child2.bin_type], -# 'inner_mt_stable': int(triple[0].child2.is_mt_stable), - 'inner_semi_RSun': triple[0].child2.semimajor_axis.value_in(units.RSun), - 'inner_ecc': triple[0].child2.eccentricity, - 'inner_aop': triple[0].child2.argument_of_pericenter, - 'inner_loan': triple[0].child2.longitude_of_ascending_node, - - 'star1_is_donor': int(triple[0].child2.child1.is_donor), -# 'star1_is_OLOF': int(triple[0].child2.child1.is_OLOF), - 'star1_stellar_type': triple[0].child2.child1.stellar_type.value_in(units.stellar_type), - 'star1_mass_MSun': triple[0].child2.child1.mass.value_in(units.MSun), - 'star1_spin_Myr_inv': triple[0].child2.child1.spin_angular_frequency.value_in(1./units.Myr), - 'star1_rad_RSun': triple[0].child2.child1.radius.value_in(units.RSun), - 'star1_coremass_MSun': triple[0].child2.child1.core_mass.value_in(units.MSun), -# 'star1_previous_mass_MSun': triple[0].child2.child1.previous_mass.value_in(units.MSun), -# 'star1_luminosity_LSun': triple[0].child2.child1.luminosity.value_in(units.LSun), -# 'star1_temperature_K': triple[0].child2.child1.temperature.value_in(units.K), - - 'star2_is_donor': int(triple[0].child2.child2.is_donor), -# 'star2_is_OLOF': int(triple[0].child2.child2.is_OLOF), - 'star2_stellar_type': triple[0].child2.child2.stellar_type.value_in(units.stellar_type), - 'star2_mass_MSun': triple[0].child2.child2.mass.value_in(units.MSun), - 'star2_spin_Myr_inv': triple[0].child2.child2.spin_angular_frequency.value_in(1./units.Myr), - 'star2_rad_RSun': triple[0].child2.child2.radius.value_in(units.RSun), - 'star2_coremass_MSun': triple[0].child2.child2.core_mass.value_in(units.MSun), -# 'star2_previous_mass_MSun': triple[0].child2.child2.previous_mass.value_in(units.MSun), -# 'star2_luminosity_LSun': triple[0].child2.child2.luminosity.value_in(units.LSun), -# 'star2_temperature_K': triple[0].child2.child2.temperature.value_in(units.K), - - 'star3_is_donor': int(triple[0].child1.is_donor), -# 'star3_is_OLOF': int(triple[0].child1.is_OLOF), - 'star3_stellar_type': triple[0].child1.stellar_type.value_in(units.stellar_type), - 'star3_mass_MSun': triple[0].child1.mass.value_in(units.MSun), - 'star3_spin_Myr_inv': triple[0].child1.spin_angular_frequency.value_in(1./units.Myr), - 'star3_rad_RSun': triple[0].child1.radius.value_in(units.RSun), - 'star3_coremass_MSun': triple[0].child1.core_mass.value_in(units.MSun), -# 'star3_previous_mass_MSun': triple[0].child1.previous_mass.value_in(units.MSun), -# 'star3_luminosity_LSun': triple[0].child1.luminosity.value_in(units.LSun), -# 'star3_temperature_K': triple[0].child1.temperature.value_in(units.K), - - } - else: #lib_parameter_style[parameter_style]==1: #selected parameters - snapshot_props = { - 'system_ID': triple[0].number, - 'time_Myr': (triple[0].time).value_in(units.Myr), - 'incl': triple[0].relative_inclination, - 'dynamical_instabiity': int(triple[0].dynamical_instability), - 'kozai_type': triple[0].kozai_type, - 'error_flag_secular': triple[0].error_flag_secular, - 'CPU_time': triple[0].CPU_time, -# 'delta_e_in': triple[0].delta_e_in, -# 'max_delta_e_in': triple[0].max_delta_e_in, - - 'outer_bin_type': bin_type[triple[0].bin_type], -# 'outer_mt_Stable': int(triple[0].is_mt_stable), - 'outer_semi_RSun': (triple[0].semimajor_axis).value_in(units.RSun), - 'outer_ecc': triple[0].eccentricity, - 'outer_aop': triple[0].argument_of_pericenter, - 'outer_loan': triple[0].longitude_of_ascending_node, - #'TripleMDotMSunYr': (triple[0].mass_transfer_rate).value_in(units.MSun/units.yr), - - 'inner_bin_type': bin_type[triple[0].child2.bin_type], -# 'inner_mt_stable': int(triple[0].child2.is_mt_stable), - 'inner_semi_RSun': triple[0].child2.semimajor_axis.value_in(units.RSun), - 'inner_ecc': triple[0].child2.eccentricity, - 'inner_aop': triple[0].child2.argument_of_pericenter, - 'inner_loan': triple[0].child2.longitude_of_ascending_node, - - 'star1_is_donor': int(triple[0].child2.child1.is_donor), -# 'star1_is_OLOF': int(triple[0].child2.child1.is_OLOF), - 'star1_stellar_type': triple[0].child2.child1.stellar_type.value_in(units.stellar_type), - 'star1_mass_MSun': triple[0].child2.child1.mass.value_in(units.MSun), - 'star1_spin_Myr_inv': triple[0].child2.child1.spin_angular_frequency.value_in(1./units.Myr), - 'star1_rad_RSun': triple[0].child2.child1.radius.value_in(units.RSun), - 'star1_coremass_MSun': triple[0].child2.child1.core_mass.value_in(units.MSun), -# 'star1_previous_mass_MSun': triple[0].child2.child1.previous_mass.value_in(units.MSun), -# 'star1_luminosity_LSun': triple[0].child2.child1.luminosity.value_in(units.LSun), -# 'star1_temperature_K': triple[0].child2.child1.temperature.value_in(units.K), - - 'star2_is_donor': int(triple[0].child2.child2.is_donor), -# 'star2_is_OLOF': int(triple[0].child2.child2.is_OLOF), - 'star2_stellar_type': triple[0].child2.child2.stellar_type.value_in(units.stellar_type), - 'star2_mass_MSun': triple[0].child2.child2.mass.value_in(units.MSun), - 'star2_spin_Myr_inv': triple[0].child2.child2.spin_angular_frequency.value_in(1./units.Myr), - 'star2_rad_RSun': triple[0].child2.child2.radius.value_in(units.RSun), - 'star2_coremass_MSun': triple[0].child2.child2.core_mass.value_in(units.MSun), -# 'star2_previous_mass_MSun': triple[0].child2.child2.previous_mass.value_in(units.MSun), -# 'star2_luminosity_LSun': triple[0].child2.child2.luminosity.value_in(units.LSun), -# 'star2_temperature_K': triple[0].child2.child2.temperature.value_in(units.K), - - 'star3_is_donor': int(triple[0].child1.is_donor), -# 'star3_is_OLOF': int(triple[0].child1.is_OLOF), - 'star3_stellar_type': triple[0].child1.stellar_type.value_in(units.stellar_type), - 'star3_mass_MSun': triple[0].child1.mass.value_in(units.MSun), - 'star3_spin_Myr_inv': triple[0].child1.spin_angular_frequency.value_in(1./units.Myr), - 'star3_rad_RSun': triple[0].child1.radius.value_in(units.RSun), - 'star3_coremass_MSun': triple[0].child1.core_mass.value_in(units.MSun), -# 'star3_previous_mass_MSun': triple[0].child1.previous_mass.value_in(units.MSun), -# 'star3_luminosity_LSun': triple[0].child1.luminosity.value_in(units.LSun), -# 'star3_temperature_K': triple[0].child1.temperature.value_in(units.K), - - } - - - return snapshot_props - - - - - - - -#for more info on mass transfer stability, see triple[0].is_mt_stable & triple[0].child2.is_mt_stable -def rdc(file_name_root, parameter_style, print_style, save_all_snapshots, print_init, line_number, inner_primary_star_type, inner_secondary_star_type, outer_star_type, inner_primary_star_type_string, inner_secondary_star_type_string, outer_star_type_string, -inner_bin_type, outer_bin_type, inner_bin_type_string, outer_bin_type_string, triple_type, triple_type_string): - - - file_name = file_name_root + ".hdf" - if file_name_root[-4:]==".hdf": + if particle.is_star: + print(particle) + else: + print(particle) + print_particle(particle.child1) + print_particle(particle.child2) + + +def create_snapshot_for_dict(triple, parameter_style): + if parameter_style == 0: # all available parameters + snapshot_props = { + "system_ID": triple[0].number, + "time_Myr": (triple[0].time).value_in(units.Myr), + "incl": triple[0].relative_inclination, + "dynamical_instabiity": int(triple[0].dynamical_instability), + "kozai_type": triple[0].kozai_type, + "error_flag_secular": triple[0].error_flag_secular, + "CPU_time": triple[0].CPU_time, + "delta_e_in": triple[0].delta_e_in, + "max_delta_e_in": triple[0].max_delta_e_in, + "outer_bin_type": bin_type[triple[0].bin_type], + "outer_mt_Stable": int(triple[0].is_mt_stable), + "outer_semi_RSun": (triple[0].semimajor_axis).value_in(units.RSun), + "outer_ecc": triple[0].eccentricity, + "outer_aop": triple[0].argument_of_pericenter, + "outer_loan": triple[0].longitude_of_ascending_node, + #'TripleMDotMSunYr': (triple[0].mass_transfer_rate).value_in(units.MSun/units.yr), + "inner_bin_type": bin_type[triple[0].child2.bin_type], + "inner_mt_stable": int(triple[0].child2.is_mt_stable), + "inner_semi_RSun": triple[0].child2.semimajor_axis.value_in(units.RSun), + "inner_ecc": triple[0].child2.eccentricity, + "inner_aop": triple[0].child2.argument_of_pericenter, + "inner_loan": triple[0].child2.longitude_of_ascending_node, + "star1_is_donor": int(triple[0].child2.child1.is_donor), + # 'star1_is_OLOF': int(triple[0].child2.child1.is_OLOF), + "star1_stellar_type": triple[0].child2.child1.stellar_type.value_in( + units.stellar_type + ), + "star1_mass_MSun": triple[0].child2.child1.mass.value_in(units.MSun), + "star1_spin_Myr_inv": triple[ + 0 + ].child2.child1.spin_angular_frequency.value_in(1.0 / units.Myr), + "star1_rad_RSun": triple[0].child2.child1.radius.value_in(units.RSun), + "star1_coremass_MSun": triple[0].child2.child1.core_mass.value_in( + units.MSun + ), + "star1_previous_mass_MSun": triple[0].child2.child1.previous_mass.value_in( + units.MSun + ), + "star1_luminosity_LSun": triple[0].child2.child1.luminosity.value_in( + units.LSun + ), + "star1_temperature_K": triple[0].child2.child1.temperature.value_in( + units.K + ), + "star2_is_donor": int(triple[0].child2.child2.is_donor), + # 'star2_is_OLOF': int(triple[0].child2.child2.is_OLOF), + "star2_stellar_type": triple[0].child2.child2.stellar_type.value_in( + units.stellar_type + ), + "star2_mass_MSun": triple[0].child2.child2.mass.value_in(units.MSun), + "star2_spin_Myr_inv": triple[ + 0 + ].child2.child2.spin_angular_frequency.value_in(1.0 / units.Myr), + "star2_rad_RSun": triple[0].child2.child2.radius.value_in(units.RSun), + "star2_coremass_MSun": triple[0].child2.child2.core_mass.value_in( + units.MSun + ), + "star2_previous_mass_MSun": triple[0].child2.child2.previous_mass.value_in( + units.MSun + ), + "star2_luminosity_LSun": triple[0].child2.child2.luminosity.value_in( + units.LSun + ), + "star2_temperature_K": triple[0].child2.child2.temperature.value_in( + units.K + ), + "star3_is_donor": int(triple[0].child1.is_donor), + # 'star3_is_OLOF': int(triple[0].child1.is_OLOF), + "star3_stellar_type": triple[0].child1.stellar_type.value_in( + units.stellar_type + ), + "star3_mass_MSun": triple[0].child1.mass.value_in(units.MSun), + "star3_spin_Myr_inv": triple[0].child1.spin_angular_frequency.value_in( + 1.0 / units.Myr + ), + "star3_rad_RSun": triple[0].child1.radius.value_in(units.RSun), + "star3_coremass_MSun": triple[0].child1.core_mass.value_in(units.MSun), + "star3_previous_mass_MSun": triple[0].child1.previous_mass.value_in( + units.MSun + ), + "star3_luminosity_LSun": triple[0].child1.luminosity.value_in(units.LSun), + "star3_temperature_K": triple[0].child1.temperature.value_in(units.K), + } + + elif parameter_style == 2: + # User selected parameters - select by commenting / uncommenting lines + snapshot_props = { + "system_ID": triple[0].number, + "time_Myr": (triple[0].time).value_in(units.Myr), + "incl": triple[0].relative_inclination, + "dynamical_instabiity": int(triple[0].dynamical_instability), + "kozai_type": triple[0].kozai_type, + "error_flag_secular": triple[0].error_flag_secular, + "CPU_time": triple[0].CPU_time, + # 'delta_e_in': triple[0].delta_e_in, + # 'max_delta_e_in': triple[0].max_delta_e_in, + "outer_bin_type": bin_type[triple[0].bin_type], + # 'outer_mt_Stable': int(triple[0].is_mt_stable), + "outer_semi_RSun": (triple[0].semimajor_axis).value_in(units.RSun), + "outer_ecc": triple[0].eccentricity, + "outer_aop": triple[0].argument_of_pericenter, + "outer_loan": triple[0].longitude_of_ascending_node, + #'TripleMDotMSunYr': (triple[0].mass_transfer_rate).value_in(units.MSun/units.yr), + "inner_bin_type": bin_type[triple[0].child2.bin_type], + # 'inner_mt_stable': int(triple[0].child2.is_mt_stable), + "inner_semi_RSun": triple[0].child2.semimajor_axis.value_in(units.RSun), + "inner_ecc": triple[0].child2.eccentricity, + "inner_aop": triple[0].child2.argument_of_pericenter, + "inner_loan": triple[0].child2.longitude_of_ascending_node, + "star1_is_donor": int(triple[0].child2.child1.is_donor), + # 'star1_is_OLOF': int(triple[0].child2.child1.is_OLOF), + "star1_stellar_type": triple[0].child2.child1.stellar_type.value_in( + units.stellar_type + ), + "star1_mass_MSun": triple[0].child2.child1.mass.value_in(units.MSun), + "star1_spin_Myr_inv": triple[ + 0 + ].child2.child1.spin_angular_frequency.value_in(1.0 / units.Myr), + "star1_rad_RSun": triple[0].child2.child1.radius.value_in(units.RSun), + "star1_coremass_MSun": triple[0].child2.child1.core_mass.value_in( + units.MSun + ), + # 'star1_previous_mass_MSun': triple[0].child2.child1.previous_mass.value_in(units.MSun), + # 'star1_luminosity_LSun': triple[0].child2.child1.luminosity.value_in(units.LSun), + # 'star1_temperature_K': triple[0].child2.child1.temperature.value_in(units.K), + "star2_is_donor": int(triple[0].child2.child2.is_donor), + # 'star2_is_OLOF': int(triple[0].child2.child2.is_OLOF), + "star2_stellar_type": triple[0].child2.child2.stellar_type.value_in( + units.stellar_type + ), + "star2_mass_MSun": triple[0].child2.child2.mass.value_in(units.MSun), + "star2_spin_Myr_inv": triple[ + 0 + ].child2.child2.spin_angular_frequency.value_in(1.0 / units.Myr), + "star2_rad_RSun": triple[0].child2.child2.radius.value_in(units.RSun), + "star2_coremass_MSun": triple[0].child2.child2.core_mass.value_in( + units.MSun + ), + # 'star2_previous_mass_MSun': triple[0].child2.child2.previous_mass.value_in(units.MSun), + # 'star2_luminosity_LSun': triple[0].child2.child2.luminosity.value_in(units.LSun), + # 'star2_temperature_K': triple[0].child2.child2.temperature.value_in(units.K), + "star3_is_donor": int(triple[0].child1.is_donor), + # 'star3_is_OLOF': int(triple[0].child1.is_OLOF), + "star3_stellar_type": triple[0].child1.stellar_type.value_in( + units.stellar_type + ), + "star3_mass_MSun": triple[0].child1.mass.value_in(units.MSun), + "star3_spin_Myr_inv": triple[0].child1.spin_angular_frequency.value_in( + 1.0 / units.Myr + ), + "star3_rad_RSun": triple[0].child1.radius.value_in(units.RSun), + "star3_coremass_MSun": triple[0].child1.core_mass.value_in(units.MSun), + # 'star3_previous_mass_MSun': triple[0].child1.previous_mass.value_in(units.MSun), + # 'star3_luminosity_LSun': triple[0].child1.luminosity.value_in(units.LSun), + # 'star3_temperature_K': triple[0].child1.temperature.value_in(units.K), + } + else: # lib_parameter_style[parameter_style]==1: #selected parameters + snapshot_props = { + "system_ID": triple[0].number, + "time_Myr": (triple[0].time).value_in(units.Myr), + "incl": triple[0].relative_inclination, + "dynamical_instabiity": int(triple[0].dynamical_instability), + "kozai_type": triple[0].kozai_type, + "error_flag_secular": triple[0].error_flag_secular, + "CPU_time": triple[0].CPU_time, + # 'delta_e_in': triple[0].delta_e_in, + # 'max_delta_e_in': triple[0].max_delta_e_in, + "outer_bin_type": bin_type[triple[0].bin_type], + # 'outer_mt_Stable': int(triple[0].is_mt_stable), + "outer_semi_RSun": (triple[0].semimajor_axis).value_in(units.RSun), + "outer_ecc": triple[0].eccentricity, + "outer_aop": triple[0].argument_of_pericenter, + "outer_loan": triple[0].longitude_of_ascending_node, + #'TripleMDotMSunYr': (triple[0].mass_transfer_rate).value_in(units.MSun/units.yr), + "inner_bin_type": bin_type[triple[0].child2.bin_type], + # 'inner_mt_stable': int(triple[0].child2.is_mt_stable), + "inner_semi_RSun": triple[0].child2.semimajor_axis.value_in(units.RSun), + "inner_ecc": triple[0].child2.eccentricity, + "inner_aop": triple[0].child2.argument_of_pericenter, + "inner_loan": triple[0].child2.longitude_of_ascending_node, + "star1_is_donor": int(triple[0].child2.child1.is_donor), + # 'star1_is_OLOF': int(triple[0].child2.child1.is_OLOF), + "star1_stellar_type": triple[0].child2.child1.stellar_type.value_in( + units.stellar_type + ), + "star1_mass_MSun": triple[0].child2.child1.mass.value_in(units.MSun), + "star1_spin_Myr_inv": triple[ + 0 + ].child2.child1.spin_angular_frequency.value_in(1.0 / units.Myr), + "star1_rad_RSun": triple[0].child2.child1.radius.value_in(units.RSun), + "star1_coremass_MSun": triple[0].child2.child1.core_mass.value_in( + units.MSun + ), + # 'star1_previous_mass_MSun': triple[0].child2.child1.previous_mass.value_in(units.MSun), + # 'star1_luminosity_LSun': triple[0].child2.child1.luminosity.value_in(units.LSun), + # 'star1_temperature_K': triple[0].child2.child1.temperature.value_in(units.K), + "star2_is_donor": int(triple[0].child2.child2.is_donor), + # 'star2_is_OLOF': int(triple[0].child2.child2.is_OLOF), + "star2_stellar_type": triple[0].child2.child2.stellar_type.value_in( + units.stellar_type + ), + "star2_mass_MSun": triple[0].child2.child2.mass.value_in(units.MSun), + "star2_spin_Myr_inv": triple[ + 0 + ].child2.child2.spin_angular_frequency.value_in(1.0 / units.Myr), + "star2_rad_RSun": triple[0].child2.child2.radius.value_in(units.RSun), + "star2_coremass_MSun": triple[0].child2.child2.core_mass.value_in( + units.MSun + ), + # 'star2_previous_mass_MSun': triple[0].child2.child2.previous_mass.value_in(units.MSun), + # 'star2_luminosity_LSun': triple[0].child2.child2.luminosity.value_in(units.LSun), + # 'star2_temperature_K': triple[0].child2.child2.temperature.value_in(units.K), + "star3_is_donor": int(triple[0].child1.is_donor), + # 'star3_is_OLOF': int(triple[0].child1.is_OLOF), + "star3_stellar_type": triple[0].child1.stellar_type.value_in( + units.stellar_type + ), + "star3_mass_MSun": triple[0].child1.mass.value_in(units.MSun), + "star3_spin_Myr_inv": triple[0].child1.spin_angular_frequency.value_in( + 1.0 / units.Myr + ), + "star3_rad_RSun": triple[0].child1.radius.value_in(units.RSun), + "star3_coremass_MSun": triple[0].child1.core_mass.value_in(units.MSun), + # 'star3_previous_mass_MSun': triple[0].child1.previous_mass.value_in(units.MSun), + # 'star3_luminosity_LSun': triple[0].child1.luminosity.value_in(units.LSun), + # 'star3_temperature_K': triple[0].child1.temperature.value_in(units.K), + } + + return snapshot_props + + +# for more info on mass transfer stability, see triple[0].is_mt_stable & triple[0].child2.is_mt_stable +def rdc( + file_name_root, + parameter_style, + print_style, + save_all_snapshots, + print_init, + line_number, + inner_primary_star_type, + inner_secondary_star_type, + outer_star_type, + inner_primary_star_type_string, + inner_secondary_star_type_string, + outer_star_type_string, + inner_bin_type, + outer_bin_type, + inner_bin_type_string, + outer_bin_type_string, + triple_type, + triple_type_string, +): + + file_name = file_name_root + ".hdf" + if file_name_root[-4:] == ".hdf": file_name = file_name_root - - print('Reducing file: \t\t\t', file_name) - print('Parameter style: \t\t', lib_parameter_style[parameter_style]) - print('Print style: \t\t\t', lib_print_style[print_style]) - print('Save_all_snapshots: \t\t', save_all_snapshots) - print('') - - - - triple=read_set_from_file(file_name , "hdf5") -# counter = list(enumerate(triple.history))[0][1].number - + + print("Reducing file: \t\t\t", file_name) + print("Parameter style: \t\t", lib_parameter_style[parameter_style]) + print("Print style: \t\t\t", lib_print_style[print_style]) + print("Save_all_snapshots: \t\t", save_all_snapshots) + print("") + + triple = read_set_from_file(file_name, "hdf5") + # counter = list(enumerate(triple.history))[0][1].number if print_init: for i, triple in enumerate(triple.history): if i == line_number: - print('amuse TRES.py ', end = '' ) - print(' -M ', triple[0].child2.child1.mass.value_in(units.MSun), ' -m ', triple[0].child2.child2.mass.value_in(units.MSun), ' -l ', triple[0].child1.mass.value_in(units.MSun), end = '') - print(' -A ', triple[0].child2.semimajor_axis.value_in(units.RSun), ' -a ', triple[0].semimajor_axis.value_in(units.RSun), end = '') - print(' -E ', triple[0].child2.eccentricity, ' -e ', triple[0].eccentricity, end = '') - print(' -G ', triple[0].child2.argument_of_pericenter, ' -g ', triple[0].argument_of_pericenter, end = '') - print(' -I ', triple[0].relative_inclination, end = '\t') - + print("amuse TRES.py ", end="") + print( + " -M ", + triple[0].child2.child1.mass.value_in(units.MSun), + " -m ", + triple[0].child2.child2.mass.value_in(units.MSun), + " -l ", + triple[0].child1.mass.value_in(units.MSun), + end="", + ) + print( + " -A ", + triple[0].child2.semimajor_axis.value_in(units.RSun), + " -a ", + triple[0].semimajor_axis.value_in(units.RSun), + end="", + ) + print( + " -E ", + triple[0].child2.eccentricity, + " -e ", + triple[0].eccentricity, + end="", + ) + print( + " -G ", + triple[0].child2.argument_of_pericenter, + " -g ", + triple[0].argument_of_pericenter, + end="", + ) + print(" -I ", triple[0].relative_inclination, end="\t") + if triple[0].time > minimum_time_step: - print('Warning: these parameters do not represent a system at birth (ZAMS).') + print( + "Warning: these parameters do not represent a system at birth (ZAMS)." + ) return + # print(inner_primary_star_type, inner_secondary_star_type, outer_star_type) + # print(star_type[inner_primary_star_type_string],star_type[inner_secondary_star_type_string],star_type[outer_star_type_string] ) + # print(inner_bin_type, outer_bin_type, triple_type) + # print(bin_type[inner_bin_type_string], bin_type[outer_bin_type_string], tr_type[triple_type_string]) -# print(inner_primary_star_type, inner_secondary_star_type, outer_star_type) -# print(star_type[inner_primary_star_type_string],star_type[inner_secondary_star_type_string],star_type[outer_star_type_string] ) -# print(inner_bin_type, outer_bin_type, triple_type) -# print(bin_type[inner_bin_type_string], bin_type[outer_bin_type_string], tr_type[triple_type_string]) - - if inner_primary_star_type != -1 and star_type[inner_primary_star_type_string] != -1 and inner_primary_star_type != star_type[inner_primary_star_type_string] : - print('error: two different inner primary star types requested') + if ( + inner_primary_star_type != -1 + and star_type[inner_primary_star_type_string] != -1 + and inner_primary_star_type != star_type[inner_primary_star_type_string] + ): + print("error: two different inner primary star types requested") return - if inner_secondary_star_type != -1 and star_type[inner_secondary_star_type_string] != -1 and inner_secondary_star_type != star_type[inner_secondary_star_type_string] : - print('error: two different inner secondary star types requested') + if ( + inner_secondary_star_type != -1 + and star_type[inner_secondary_star_type_string] != -1 + and inner_secondary_star_type != star_type[inner_secondary_star_type_string] + ): + print("error: two different inner secondary star types requested") return - if outer_star_type != -1 and star_type[outer_star_type_string] != -1 and outer_star_type != star_type[outer_star_type_string] : - print('error: two different outer star types requested') + if ( + outer_star_type != -1 + and star_type[outer_star_type_string] != -1 + and outer_star_type != star_type[outer_star_type_string] + ): + print("error: two different outer star types requested") return - if inner_bin_type > -1 and bin_type[inner_bin_type_string] > -1 and inner_bin_type != bin_type[inner_bin_type_string] : - print('error: two different inner binary types requested') + if ( + inner_bin_type > -1 + and bin_type[inner_bin_type_string] > -1 + and inner_bin_type != bin_type[inner_bin_type_string] + ): + print("error: two different inner binary types requested") return - if outer_bin_type > -1 and bin_type[outer_bin_type_string] > -1 and outer_bin_type != bin_type[outer_bin_type_string]: - print('error: two different outer binary types requested') + if ( + outer_bin_type > -1 + and bin_type[outer_bin_type_string] > -1 + and outer_bin_type != bin_type[outer_bin_type_string] + ): + print("error: two different outer binary types requested") return - if triple_type > -1 and tr_type[triple_type_string] > -1 and triple_type != tr_type[triple_type_string] : - print('error: two different triple types requested') - return - + if ( + triple_type > -1 + and tr_type[triple_type_string] > -1 + and triple_type != tr_type[triple_type_string] + ): + print("error: two different triple types requested") + return + if star_type[inner_primary_star_type_string] != -1: inner_primary_star_type = star_type[inner_primary_star_type_string] if star_type[inner_secondary_star_type_string] != -1: inner_secondary_star_type = star_type[inner_secondary_star_type_string] if star_type[outer_star_type_string] != -1: outer_star_type = star_type[outer_star_type_string] - inner_bin_type = max(inner_bin_type, bin_type[inner_bin_type_string]) - outer_bin_type = max(outer_bin_type, bin_type[outer_bin_type_string]) - triple_type = max(triple_type, tr_type[triple_type_string]) - - - snapshot_props = [] - previous_triple_number = -1 - previous_correct_system = False - + inner_bin_type = max(inner_bin_type, bin_type[inner_bin_type_string]) + outer_bin_type = max(outer_bin_type, bin_type[outer_bin_type_string]) + triple_type = max(triple_type, tr_type[triple_type_string]) + + snapshot_props = [] + previous_triple_number = -1 + previous_correct_system = False + for i, triple in enumerate(triple.history): - + if print_style == 3: print_particle(triple[0]) sys.exit(0) - - triple_number = triple[0].number - previous_snapshot_props = snapshot_props + + triple_number = triple[0].number + previous_snapshot_props = snapshot_props snapshot_props = create_snapshot_for_dict(triple, parameter_style) - - if triple_type != tr_type['all']: - triple_type_snapshot = tr_type['hierarchical'] + + if triple_type != tr_type["all"]: + triple_type_snapshot = tr_type["hierarchical"] if triple[0].dynamical_instability: - triple_type_snapshot = tr_type['dynamical_instability'] -# if triple[0].semisecular_regime: -# triple_type_snapshot = tr_type['semisecular_regime'] + triple_type_snapshot = tr_type["dynamical_instability"] + # if triple[0].semisecular_regime: + # triple_type_snapshot = tr_type['semisecular_regime'] if triple[0].error_flag_secular: - triple_type_snapshot = tr_type['error_flag_secular'] - - if (inner_primary_star_type == star_type['all'] or triple[0].child2.child1.stellar_type.value_in(units.stellar_type) in np.array(inner_primary_star_type)) and \ - (inner_secondary_star_type == star_type['all'] or triple[0].child2.child2.stellar_type.value_in(units.stellar_type) in np.array(inner_secondary_star_type)) and \ - (outer_star_type == star_type['all'] or triple[0].child1.stellar_type.value_in(units.stellar_type) in np.array(outer_star_type)) and \ - (inner_bin_type == bin_type['all'] or inner_bin_type == bin_type[triple[0].child2.bin_type]) and \ - (outer_bin_type == bin_type['all'] or outer_bin_type == bin_type[triple[0].bin_type]) and \ - (triple_type == tr_type['all'] or triple_type == triple_type_snapshot): + triple_type_snapshot = tr_type["error_flag_secular"] + + if ( + ( + inner_primary_star_type == star_type["all"] + or triple[0].child2.child1.stellar_type.value_in(units.stellar_type) + in np.array(inner_primary_star_type) + ) + and ( + inner_secondary_star_type == star_type["all"] + or triple[0].child2.child2.stellar_type.value_in(units.stellar_type) + in np.array(inner_secondary_star_type) + ) + and ( + outer_star_type == star_type["all"] + or triple[0].child1.stellar_type.value_in(units.stellar_type) + in np.array(outer_star_type) + ) + and ( + inner_bin_type == bin_type["all"] + or inner_bin_type == bin_type[triple[0].child2.bin_type] + ) + and ( + outer_bin_type == bin_type["all"] + or outer_bin_type == bin_type[triple[0].bin_type] + ) + and (triple_type == tr_type["all"] or triple_type == triple_type_snapshot) + ): correct_system = True - - - #which snapshots to save - if save_all_snapshots and correct_system: #all snapshots - SaveDictSet = [] - SaveDictSet.append(snapshot_props) - df = pd.DataFrame(SaveDictSet) - df.to_csv(file_name_root+'.csv', mode='a', header=not os.path.exists(file_name_root+'.csv')) - if print_style == 1: - if i==0: - print(df.to_string()) - print(df.to_string(header=False)) - elif triple_number>previous_triple_number: #new system - #save last line previous system if necessary - if previous_correct_system: - SaveDictSet.append(previous_snapshot_props) - df = pd.DataFrame(SaveDictSet) - df.to_csv(file_name_root+'.csv', mode='a', header=not os.path.exists(file_name_root+'.csv')) - if print_style == 1: - if triple_number==0: - print(df.to_string()) - print(df.to_string(header=False)) - - #first line of current system - #saving for now - SaveDictSet = [] - SaveDictSet.append(snapshot_props) - previous_triple_number = triple_number - previous_correct_system = correct_system - - - #last line for last system - if correct_system and save_all_snapshots==False: - SaveDictSet.append(snapshot_props) - df = pd.DataFrame(SaveDictSet) - df.to_csv(file_name_root+'.csv', mode='a', header=not os.path.exists(file_name_root+'.csv')) - if print_style == 1: - print(df.to_string(header=False)) - - - + + # which snapshots to save + if save_all_snapshots and correct_system: # all snapshots + SaveDictSet = [] + SaveDictSet.append(snapshot_props) + df = pd.DataFrame(SaveDictSet) + df.to_csv( + file_name_root + ".csv", + mode="a", + header=not os.path.exists(file_name_root + ".csv"), + ) + if print_style == 1: + if i == 0: + print(df.to_string()) + print(df.to_string(header=False)) + elif triple_number > previous_triple_number: # new system + # save last line previous system if necessary + if previous_correct_system: + SaveDictSet.append(previous_snapshot_props) + df = pd.DataFrame(SaveDictSet) + df.to_csv( + file_name_root + ".csv", + mode="a", + header=not os.path.exists(file_name_root + ".csv"), + ) + if print_style == 1: + if triple_number == 0: + print(df.to_string()) + print(df.to_string(header=False)) + + # first line of current system + # saving for now + SaveDictSet = [] + SaveDictSet.append(snapshot_props) + previous_triple_number = triple_number + previous_correct_system = correct_system + + # last line for last system + if correct_system and save_all_snapshots == False: + SaveDictSet.append(snapshot_props) + df = pd.DataFrame(SaveDictSet) + df.to_csv( + file_name_root + ".csv", + mode="a", + header=not os.path.exists(file_name_root + ".csv"), + ) + if print_style == 1: + print(df.to_string(header=False)) + def parse_arguments(): from amuse.units.optparse import OptionParser + parser = OptionParser() - parser.add_option("-f", dest="file_name_root", default = "TRES", - help="file name [%default]") - parser.add_option("-P", dest="parameter_style", type="int", default = 1, - help="parameter style - which parameters should be recorded[%default]") - parser.add_option("-S", dest="print_style", type="int", default = 0, - help="print style [%default]") - parser.add_option("-F", "--save_all_snapshots", dest="save_all_snapshots", action="store_true", default = False, - help="save every snapshot for specified triple [%default]") - parser.add_option("--print_init", dest="print_init", action="store_true", default = False, - help="print initial conditions for re running [%default]") - parser.add_option("-l", dest="line_number", type="int", default = 0, - help="line number for printing initial conditions [%default]") #will only do something when print_init = True - - #returns first instance where desired star_type, bin_type & triple_type is reached - parser.add_option("--st1", dest="inner_primary_star_type", type="int", default = -1, - help="desired stellar type of inner binary primary star (int) [%default]") - parser.add_option("--st2", dest="inner_secondary_star_type", type="int", default = -1, - help="desired stellar type of inner binary secondary star (int) [%default]") - parser.add_option("--st3", dest="outer_star_type", type="int", default = -1, - help="desired stellar type of tertiary star (int) [%default]") - parser.add_option("--st1str", dest="inner_primary_star_type_string", default = "all", - help="desired stellar type of inner binary primary star (int) [%default]") - parser.add_option("--st2str", dest="inner_secondary_star_type_string", default = "all", - help="desired stellar type of inner binary secondary star (int) [%default]") - parser.add_option("--st3str", dest="outer_star_type_string", default = "all", - help="desired stellar type of tertiary star [%default]") - parser.add_option("--btin", dest="inner_bin_type", type="int", default = -1, - help="desired binary type of inner binary (int) [%default]") - parser.add_option("--btout", dest="outer_bin_type", type="int", default = -1, - help="desired binary type of inner binary (int) [%default]") - parser.add_option("--btinstr", dest="inner_bin_type_string", default = "all", - help="desired binary type of inner binary (string) [%default]") - parser.add_option("--btoutstr", dest="outer_bin_type_string", default = "all", - help="desired binary type of outer binary (string) [%default]") - parser.add_option("--trt", dest="triple_type", type="int", default = -1, - help="desired triple type (int) [%default]") - parser.add_option("--trtstr", dest="triple_type_string", default = "all", - help="desired triple type [%default]") - - + parser.add_option( + "-f", dest="file_name_root", default="TRES", help="file name [%default]" + ) + parser.add_option( + "-P", + dest="parameter_style", + type="int", + default=1, + help="parameter style - which parameters should be recorded[%default]", + ) + parser.add_option( + "-S", dest="print_style", type="int", default=0, help="print style [%default]" + ) + parser.add_option( + "-F", + "--save_all_snapshots", + dest="save_all_snapshots", + action="store_true", + default=False, + help="save every snapshot for specified triple [%default]", + ) + parser.add_option( + "--print_init", + dest="print_init", + action="store_true", + default=False, + help="print initial conditions for re running [%default]", + ) + parser.add_option( + "-l", + dest="line_number", + type="int", + default=0, + help="line number for printing initial conditions [%default]", + ) # will only do something when print_init = True + + # returns first instance where desired star_type, bin_type & triple_type is reached + parser.add_option( + "--st1", + dest="inner_primary_star_type", + type="int", + default=-1, + help="desired stellar type of inner binary primary star (int) [%default]", + ) + parser.add_option( + "--st2", + dest="inner_secondary_star_type", + type="int", + default=-1, + help="desired stellar type of inner binary secondary star (int) [%default]", + ) + parser.add_option( + "--st3", + dest="outer_star_type", + type="int", + default=-1, + help="desired stellar type of tertiary star (int) [%default]", + ) + parser.add_option( + "--st1str", + dest="inner_primary_star_type_string", + default="all", + help="desired stellar type of inner binary primary star (int) [%default]", + ) + parser.add_option( + "--st2str", + dest="inner_secondary_star_type_string", + default="all", + help="desired stellar type of inner binary secondary star (int) [%default]", + ) + parser.add_option( + "--st3str", + dest="outer_star_type_string", + default="all", + help="desired stellar type of tertiary star [%default]", + ) + parser.add_option( + "--btin", + dest="inner_bin_type", + type="int", + default=-1, + help="desired binary type of inner binary (int) [%default]", + ) + parser.add_option( + "--btout", + dest="outer_bin_type", + type="int", + default=-1, + help="desired binary type of inner binary (int) [%default]", + ) + parser.add_option( + "--btinstr", + dest="inner_bin_type_string", + default="all", + help="desired binary type of inner binary (string) [%default]", + ) + parser.add_option( + "--btoutstr", + dest="outer_bin_type_string", + default="all", + help="desired binary type of outer binary (string) [%default]", + ) + parser.add_option( + "--trt", + dest="triple_type", + type="int", + default=-1, + help="desired triple type (int) [%default]", + ) + parser.add_option( + "--trtstr", + dest="triple_type_string", + default="all", + help="desired triple type [%default]", + ) + options, args = parser.parse_args() return options.__dict__ -if __name__ == '__main__': +if __name__ == "__main__": options = parse_arguments() - set_printing_strategy("custom", - preferred_units = [units.MSun, units.RSun, units.Myr], - precision = 11, prefix = "", - separator = " [", suffix = "]") - - + set_printing_strategy( + "custom", + preferred_units=[units.MSun, units.RSun, units.Myr], + precision=11, + prefix="", + separator=" [", + suffix="]", + ) - print(' ') - rdc(**options) - + print(" ") + rdc(**options) From e25bd7a65ce484ca2a97e58a1bb15d272a18294f Mon Sep 17 00:00:00 2001 From: Steven Rieder Date: Mon, 4 Nov 2024 13:45:35 +0100 Subject: [PATCH 15/30] refactor setup.py --- src/tres/setup.py | 342 +++++++++++++++++++++++++++------------------- 1 file changed, 201 insertions(+), 141 deletions(-) diff --git a/src/tres/setup.py b/src/tres/setup.py index 32d57f1..7240745 100644 --- a/src/tres/setup.py +++ b/src/tres/setup.py @@ -1,27 +1,26 @@ +import numpy as np + from amuse.community.seba import Seba from amuse.datamodel import Particles from amuse.units import units -from tres.seculartriple_TPS.interface import SecularTriple +from tres.seculartriple_TPS.interface import SecularTriple from tres.options import max_mass, absolute_min_mass - from tres.interactions import * from tres.tidal_friction_constant import * -import numpy as np - -#------- -#to initialize the triple object +# ------- +# to initialize the triple object def make_stars(inner_primary_mass, inner_secondary_mass, outer_mass): stars = Particles(3) stars.is_star = True stars.is_donor = False - + if inner_primary_mass < inner_secondary_mass: spare = inner_primary_mass inner_primary_mass = inner_secondary_mass - inner_secondary_mass = spare + inner_secondary_mass = spare stars[0].mass = inner_primary_mass stars[1].mass = inner_secondary_mass @@ -31,18 +30,26 @@ def make_stars(inner_primary_mass, inner_secondary_mass, outer_mass): stars[1].initial_mass = inner_secondary_mass stars[2].initial_mass = outer_mass - return stars - -def make_bins(stars, inner_semimajor_axis, outer_semimajor_axis, - inner_eccentricity, outer_eccentricity, - inner_argument_of_pericenter, outer_argument_of_pericenter, - inner_longitude_of_ascending_node, outer_longitude_of_ascending_node): + return stars + + +def make_bins( + stars, + inner_semimajor_axis, + outer_semimajor_axis, + inner_eccentricity, + outer_eccentricity, + inner_argument_of_pericenter, + outer_argument_of_pericenter, + inner_longitude_of_ascending_node, + outer_longitude_of_ascending_node, +): bins = Particles(2) bins.is_star = False bins.is_mt_stable = True - bins.part_dt_mt = 1. - bins.bin_type = bin_type['unknown'] #Unknown + bins.part_dt_mt = 1.0 + bins.bin_type = bin_type["unknown"] # Unknown bins[0].child1 = stars[0] bins[0].child2 = stars[1] @@ -53,8 +60,8 @@ def make_bins(stars, inner_semimajor_axis, outer_semimajor_axis, bins[0].eccentricity = inner_eccentricity bins[0].argument_of_pericenter = inner_argument_of_pericenter bins[0].longitude_of_ascending_node = inner_longitude_of_ascending_node - - bins[0].mass_transfer_rate = 0.0 | units.MSun/units.yr + + bins[0].mass_transfer_rate = 0.0 | units.MSun / units.yr bins[0].accretion_efficiency_mass_transfer = 1.0 bins[0].accretion_efficiency_wind_child1_to_child2 = 0.0 bins[0].accretion_efficiency_wind_child2_to_child1 = 0.0 @@ -63,150 +70,194 @@ def make_bins(stars, inner_semimajor_axis, outer_semimajor_axis, bins[1].child2 = bins[0] bins[1].child1.parent = bins[1] bins[1].child2.parent = bins[1] - + bins[1].semimajor_axis = outer_semimajor_axis bins[1].eccentricity = outer_eccentricity - bins[1].argument_of_pericenter = outer_argument_of_pericenter + bins[1].argument_of_pericenter = outer_argument_of_pericenter bins[1].longitude_of_ascending_node = outer_longitude_of_ascending_node - - bins[1].mass_transfer_rate = 0.0 | units.MSun/units.yr + + bins[1].mass_transfer_rate = 0.0 | units.MSun / units.yr bins[1].accretion_efficiency_mass_transfer = 1.0 bins[1].accretion_efficiency_wind_child1_to_child2 = 0.0 bins[1].accretion_efficiency_wind_child2_to_child1 = 0.0 # binary evolutionary settings - bins[0].specific_AM_loss_mass_transfer = 2.5 + bins[0].specific_AM_loss_mass_transfer = 2.5 bins[1].specific_AM_loss_mass_transfer = 2.5 return bins - -def test_initial_parameters(inner_primary_mass, inner_secondary_mass, outer_mass, - inner_semimajor_axis, outer_semimajor_axis, - inner_eccentricity, outer_eccentricity, - relative_inclination, - inner_argument_of_pericenter, outer_argument_of_pericenter, - inner_longitude_of_ascending_node): - - if max(inner_primary_mass, outer_mass) > max_mass: - print('error: masses not in allowed range') - print('m1=',inner_primary_mass, 'm2=',inner_secondary_mass, 'm3=',outer_mass) - print('should be below:', max_mass) - print('max_mass settable in TRES_options.py') - return False, 0,0 - - if min(inner_secondary_mass, outer_mass) <= absolute_min_mass: - print('error: masses not in allowed range') - print('m1=',inner_primary_mass, 'm2=',inner_secondary_mass, 'm3=',outer_mass) - print('should be at least above:', absolute_min_mass) - print('absolute_min_mass settable in TRES_options.py') - print('substellar objects can be included through EXCLUDE_SSO in TRES_options.py') - return False, 0,0 + + +def test_initial_parameters( + inner_primary_mass, + inner_secondary_mass, + outer_mass, + inner_semimajor_axis, + outer_semimajor_axis, + inner_eccentricity, + outer_eccentricity, + relative_inclination, + inner_argument_of_pericenter, + outer_argument_of_pericenter, + inner_longitude_of_ascending_node, +): + + if max(inner_primary_mass, outer_mass) > max_mass: + print("error: masses not in allowed range") + print("m1=", inner_primary_mass, "m2=", inner_secondary_mass, "m3=", outer_mass) + print("should be below:", max_mass) + print("max_mass settable in TRES_options.py") + return False, 0, 0 + + if min(inner_secondary_mass, outer_mass) <= absolute_min_mass: + print("error: masses not in allowed range") + print("m1=", inner_primary_mass, "m2=", inner_secondary_mass, "m3=", outer_mass) + print("should be at least above:", absolute_min_mass) + print("absolute_min_mass settable in TRES_options.py") + print( + "substellar objects can be included through EXCLUDE_SSO in TRES_options.py" + ) + return False, 0, 0 if inner_semimajor_axis >= outer_semimajor_axis: - print('error input parameters, should be:') - print('inner_semimajor_axis < outer_semimajor_axis' ) - return False, 0,0 - if (inner_semimajor_axis < 0.|units.RSun): - print('error: inner separation not in allowed range') - return False, 0,0 - if (outer_semimajor_axis < 0.|units.RSun): - print('error: outer separation not in allowed range') - return False, 0,0 - - if (inner_eccentricity < 0.) or (inner_eccentricity > 1.): - print('error: inner eccentricity not in allowed range') - return False, 0,0 - if (outer_eccentricity < 0.) or (outer_eccentricity > 1.): - print('error: outer eccentricity not in allowed range') - return False, 0,0 - if (inner_eccentricity < minimum_eccentricity): + print("error input parameters, should be:") + print("inner_semimajor_axis < outer_semimajor_axis") + return False, 0, 0 + if inner_semimajor_axis < 0.0 | units.RSun: + print("error: inner separation not in allowed range") + return False, 0, 0 + if outer_semimajor_axis < 0.0 | units.RSun: + print("error: outer separation not in allowed range") + return False, 0, 0 + + if (inner_eccentricity < 0.0) or (inner_eccentricity > 1.0): + print("error: inner eccentricity not in allowed range") + return False, 0, 0 + if (outer_eccentricity < 0.0) or (outer_eccentricity > 1.0): + print("error: outer eccentricity not in allowed range") + return False, 0, 0 + if inner_eccentricity < minimum_eccentricity: inner_eccentricity = minimum_eccentricity - if (outer_eccentricity < minimum_eccentricity): + if outer_eccentricity < minimum_eccentricity: outer_eccentricity = minimum_eccentricity - if (relative_inclination < 0.) or (relative_inclination > np.pi): - print('error: relative inclination not in allowed range') - return False, 0,0 - - if (inner_argument_of_pericenter < -1.*np.pi) or (inner_argument_of_pericenter > np.pi): - print('error: inner argument of pericenter not in allowed range') - return False, 0,0 - if (outer_argument_of_pericenter < -1.*np.pi) or (outer_argument_of_pericenter > np.pi): - print('error: outer argument of pericenter not in allowed range') - return False, 0,0 - - if (inner_longitude_of_ascending_node < -1.*np.pi) or (inner_longitude_of_ascending_node > np.pi): - print('error: inner longitude of ascending node not in allowed range') - return False, 0,0 - - return True, inner_eccentricity, outer_eccentricity - -def make_particle_sets(inner_primary_mass, inner_secondary_mass, outer_mass, - inner_semimajor_axis, outer_semimajor_axis, - inner_eccentricity, outer_eccentricity, - relative_inclination, - inner_argument_of_pericenter, outer_argument_of_pericenter, - inner_longitude_of_ascending_node): - - correct_params, inner_eccentricity, outer_eccentricity = test_initial_parameters(inner_primary_mass, inner_secondary_mass, outer_mass, - inner_semimajor_axis, outer_semimajor_axis, inner_eccentricity, outer_eccentricity, - relative_inclination, inner_argument_of_pericenter, outer_argument_of_pericenter, - inner_longitude_of_ascending_node) - - outer_longitude_of_ascending_node = inner_longitude_of_ascending_node - np.pi - - stars = make_stars(inner_primary_mass, inner_secondary_mass, outer_mass) - bins = make_bins(stars, inner_semimajor_axis, outer_semimajor_axis, - inner_eccentricity, outer_eccentricity, - inner_argument_of_pericenter, outer_argument_of_pericenter, - inner_longitude_of_ascending_node, outer_longitude_of_ascending_node) - - return stars, bins, correct_params - -#------- -#setup community codes + if (relative_inclination < 0.0) or (relative_inclination > np.pi): + print("error: relative inclination not in allowed range") + return False, 0, 0 + + if (inner_argument_of_pericenter < -1.0 * np.pi) or ( + inner_argument_of_pericenter > np.pi + ): + print("error: inner argument of pericenter not in allowed range") + return False, 0, 0 + if (outer_argument_of_pericenter < -1.0 * np.pi) or ( + outer_argument_of_pericenter > np.pi + ): + print("error: outer argument of pericenter not in allowed range") + return False, 0, 0 + + if (inner_longitude_of_ascending_node < -1.0 * np.pi) or ( + inner_longitude_of_ascending_node > np.pi + ): + print("error: inner longitude of ascending node not in allowed range") + return False, 0, 0 + + return True, inner_eccentricity, outer_eccentricity + + +def make_particle_sets( + inner_primary_mass, + inner_secondary_mass, + outer_mass, + inner_semimajor_axis, + outer_semimajor_axis, + inner_eccentricity, + outer_eccentricity, + relative_inclination, + inner_argument_of_pericenter, + outer_argument_of_pericenter, + inner_longitude_of_ascending_node, +): + + correct_params, inner_eccentricity, outer_eccentricity = test_initial_parameters( + inner_primary_mass, + inner_secondary_mass, + outer_mass, + inner_semimajor_axis, + outer_semimajor_axis, + inner_eccentricity, + outer_eccentricity, + relative_inclination, + inner_argument_of_pericenter, + outer_argument_of_pericenter, + inner_longitude_of_ascending_node, + ) + + outer_longitude_of_ascending_node = inner_longitude_of_ascending_node - np.pi + + stars = make_stars(inner_primary_mass, inner_secondary_mass, outer_mass) + bins = make_bins( + stars, + inner_semimajor_axis, + outer_semimajor_axis, + inner_eccentricity, + outer_eccentricity, + inner_argument_of_pericenter, + outer_argument_of_pericenter, + inner_longitude_of_ascending_node, + outer_longitude_of_ascending_node, + ) + + return stars, bins, correct_params + + +# ------- +# setup community codes + def setup_stellar_code(stellar_code, stars): stellar_code.particles.add_particles(stars) - return stellar_code + return stellar_code + - def setup_secular_code(triple, secular_code, stop_at_semisecular_regime): triple_set = triple.as_set() triple_time = triple_set.time secular_code.triples.add_particles(triple_set) secular_code.parameters.verbose = False -# secular_code.parameters.verbose = True - - #needed for initialisation in some circumstances + # secular_code.parameters.verbose = True + + # needed for initialisation in some circumstances secular_code.model_time = triple_time - + secular_code.parameters.equations_of_motion_specification = 0 secular_code.parameters.roche_radius_specification = 0 - #0: eccentric eggleton, 1: sepinsky, 2: classical circular eggleton + # 0: eccentric eggleton, 1: sepinsky, 2: classical circular eggleton secular_code.parameters.stability_limit_specification = 0 - #for stars 0, 5-6, for exoplanets 1-4 - #0: mardling & aarseth 2001, 1:petrovich et al. 2015 simple, 2:petrovich et al. 2015 - #3: holman et al. 98 s-type, 4: holman et al. 98 p-type, - #5: vynatheya+ 22 - #6: tory+ 22 + # for stars 0, 5-6, for exoplanets 1-4 + # 0: mardling & aarseth 2001, 1:petrovich et al. 2015 simple, 2:petrovich et al. 2015 + # 3: holman et al. 98 s-type, 4: holman et al. 98 p-type, + # 5: vynatheya+ 22 + # 6: tory+ 22 secular_code.parameters.ignore_tertiary = False secular_code.parameters.include_quadrupole_terms = True - secular_code.parameters.include_octupole_terms = True + secular_code.parameters.include_octupole_terms = True secular_code.parameters.include_inner_wind_terms = True secular_code.parameters.include_outer_wind_terms = True secular_code.parameters.include_inner_RLOF_terms = True secular_code.parameters.include_outer_RLOF_terms = True - secular_code.parameters.include_magnetic_braking_terms = False # not tested + secular_code.parameters.include_magnetic_braking_terms = False # not tested secular_code.parameters.include_inner_tidal_terms = True secular_code.parameters.include_outer_tidal_terms = True - + secular_code.parameters.include_1PN_inner_terms = True secular_code.parameters.include_1PN_outer_terms = True - secular_code.parameters.include_1PN_inner_outer_terms = False ### warning: probably broken + secular_code.parameters.include_1PN_inner_outer_terms = ( + False ### warning: probably broken + ) secular_code.parameters.include_25PN_inner_terms = True secular_code.parameters.include_25PN_outer_terms = True @@ -214,30 +265,39 @@ def setup_secular_code(triple, secular_code, stop_at_semisecular_regime): secular_code.parameters.check_for_dynamical_stability_at_initialisation = True secular_code.parameters.check_for_semisecular_regime = stop_at_semisecular_regime - secular_code.parameters.check_for_semisecular_regime_at_initialisation = stop_at_semisecular_regime - + secular_code.parameters.check_for_semisecular_regime_at_initialisation = ( + stop_at_semisecular_regime + ) + secular_code.parameters.check_for_inner_collision = True secular_code.parameters.check_for_outer_collision = True - secular_code.parameters.check_for_inner_RLOF = True - secular_code.parameters.check_for_outer_RLOF = True - + secular_code.parameters.check_for_inner_RLOF = True + secular_code.parameters.check_for_outer_RLOF = True + secular_code.parameters.include_spin_radius_mass_coupling_terms_star1 = True secular_code.parameters.include_spin_radius_mass_coupling_terms_star2 = True secular_code.parameters.include_spin_radius_mass_coupling_terms_star3 = True - - # accuracy of secular code -# secular_code.parameters.input_precision = 1.0e-10#1.0e-5 -# secular_code.parameters.relative_tolerance = 1.0e-10 -# secular_code.parameters.threshold_value_of_e_in_for_setting_tidal_e_in_dot_zero = 1.0e-12 - secular_code.parameters.threshold_value_of_spin_angular_frequency_for_setting_spin_angular_frequency_dot_moment_of_inertia_plus_wind_changes_zero = 1.0e-7|units.Myr**-1 - - secular_code.parameters.include_linear_mass_change = True #needed for Jspin conservation - secular_code.parameters.include_linear_radius_change = True #needed for Jspin conservation - -# channel_from_secular = secular_code.triples.new_channel_to(triple_set) -# channel_to_secular = triple_set.new_channel_to(secular_code.triples) - - return secular_code - -#------- + + # accuracy of secular code + # secular_code.parameters.input_precision = 1.0e-10#1.0e-5 + # secular_code.parameters.relative_tolerance = 1.0e-10 + # secular_code.parameters.threshold_value_of_e_in_for_setting_tidal_e_in_dot_zero = 1.0e-12 + secular_code.parameters.threshold_value_of_spin_angular_frequency_for_setting_spin_angular_frequency_dot_moment_of_inertia_plus_wind_changes_zero = ( + 1.0e-7 | units.Myr**-1 + ) + + secular_code.parameters.include_linear_mass_change = ( + True # needed for Jspin conservation + ) + secular_code.parameters.include_linear_radius_change = ( + True # needed for Jspin conservation + ) + + # channel_from_secular = secular_code.triples.new_channel_to(triple_set) + # channel_to_secular = triple_set.new_channel_to(secular_code.triples) + + return secular_code + + +# ------- From 39e67401ae7dea95f6ba7f2e627391e189565ea8 Mon Sep 17 00:00:00 2001 From: Steven Rieder Date: Mon, 4 Nov 2024 13:46:12 +0100 Subject: [PATCH 16/30] refactor tidal_friction_constant --- src/tres/tidal_friction_constant.py | 180 ++++++++++++++++++---------- 1 file changed, 115 insertions(+), 65 deletions(-) diff --git a/src/tres/tidal_friction_constant.py b/src/tres/tidal_friction_constant.py index 877c968..e360807 100644 --- a/src/tres/tidal_friction_constant.py +++ b/src/tres/tidal_friction_constant.py @@ -1,4 +1,4 @@ -#used for estimating tidal timestep +# used for estimating tidal timestep """ Routine that calculates the ratio k/T for tidal friction, where k is the apsidal motion constant and T the tidal friction time scale as they appear in Hut (1981; 1981A&A....99..126H). The entire routine has been copied directly from c-code that is part of binary_c and converted to Python. @@ -7,102 +7,152 @@ Adrian Hamers 16-06-2014 """ -#define USE_RADIATIVE_DAMPING (((stardata->star[star_number].stellar_type==MAIN_SEQUENCE)&&(MORE_OR_EQUAL(stardata->star[star_number].mass,1.25)))||(stardata->star[star_number].stellar_type==CHeB)||(stardata->star[star_number].stellar_type==HeMS)) +# define USE_RADIATIVE_DAMPING (((stardata->star[star_number].stellar_type==MAIN_SEQUENCE)&&(MORE_OR_EQUAL(stardata->star[star_number].mass,1.25)))||(stardata->star[star_number].stellar_type==CHeB)||(stardata->star[star_number].stellar_type==HeMS)) -#define USE_CONVECTIVE_DAMPING (stardata->star[star_number].stellar_typestar[star_number].stellar_type= MINIMUM_MASS_FOR_RADIATIVE_DAMPING_MSUN): +def check_for_radiative_damping(stellar_type, mass): + if ( + stellar_type == MAIN_SEQUENCE + and mass.value_in(units.MSun) >= MINIMUM_MASS_FOR_RADIATIVE_DAMPING_MSUN + ): return True - elif (stellar_type == CHeB or stellar_type == HeMS): + elif stellar_type == CHeB or stellar_type == HeMS: return True else: return False - -def check_for_convective_damping(stellar_type): + + +def check_for_convective_damping(stellar_type): if stellar_type < HeWD or stellar_type == PREMS: return True else: return False -def tidal_friction_constant(stellar_type,mass,companion_mass,semimajor_axis,radius,convective_envelope_mass,convective_envelope_radius,luminosity,spin_angular_frequency, gyration_radius, amc): - - USE_RADIATIVE_DAMPING = check_for_radiative_damping(stellar_type,mass) + +def tidal_friction_constant( + stellar_type, + mass, + companion_mass, + semimajor_axis, + radius, + convective_envelope_mass, + convective_envelope_radius, + luminosity, + spin_angular_frequency, + gyration_radius, + amc, +): + + USE_RADIATIVE_DAMPING = check_for_radiative_damping(stellar_type, mass) USE_CONVECTIVE_DAMPING = check_for_convective_damping(stellar_type) - - if USE_RADIATIVE_DAMPING: ### radiative damping ### - E2 = 1.592e-09*pow(mass.value_in(units.MSun),2.84) ### Hurley prescription; Zahn, 1977, A&A, 57, 383 and 1975, A&A, 41, 329. ### - - k_div_T_tides = E2*pow(1.0 + companion_mass/mass,5.0/6.0)*radius*numpy.sqrt(constants.G*mass/(semimajor_axis**5)) -# print('radiative damping', mass, k_div_T_tides) + + if USE_RADIATIVE_DAMPING: ### radiative damping ### + E2 = 1.592e-09 * pow( + mass.value_in(units.MSun), 2.84 + ) ### Hurley prescription; Zahn, 1977, A&A, 57, 383 and 1975, A&A, 41, 329. ### + + k_div_T_tides = ( + E2 + * pow(1.0 + companion_mass / mass, 5.0 / 6.0) + * radius + * numpy.sqrt(constants.G * mass / (semimajor_axis**5)) + ) + # print('radiative damping', mass, k_div_T_tides) return k_div_T_tides - -# kTradiative_damping = 1.9782e+04*sqrt((mass.value_in(units.MSun)*(radius.value_in(units.RSun))**2))/((semimajor_axis.value_in(units.AU))**5))*E2*pow(1.0+companion_mass/mass,5.0/6.0) -# kTradiative_damping = kTradiative_damping/YEAR_LENGTH_IN_SECONDS; /* This converts (k/T) to units of s^-1 */ - - elif USE_CONVECTIVE_DAMPING: ### convective damping ### - P_orb = 2.0*numpy.pi*numpy.sqrt((semimajor_axis**3)/(constants.G*(mass + companion_mass))) - if spin_angular_frequency.value_in(1.0/units.s) == 0.0: + + # kTradiative_damping = 1.9782e+04*sqrt((mass.value_in(units.MSun)*(radius.value_in(units.RSun))**2))/((semimajor_axis.value_in(units.AU))**5))*E2*pow(1.0+companion_mass/mass,5.0/6.0) + # kTradiative_damping = kTradiative_damping/YEAR_LENGTH_IN_SECONDS; /* This converts (k/T) to units of s^-1 */ + + elif USE_CONVECTIVE_DAMPING: ### convective damping ### + P_orb = ( + 2.0 + * numpy.pi + * numpy.sqrt((semimajor_axis**3) / (constants.G * (mass + companion_mass))) + ) + if spin_angular_frequency.value_in(1.0 / units.s) == 0.0: P_tid = P_orb else: - P_spin = 2.0*numpy.pi/spin_angular_frequency - P_tid_s = 1.0/( 1e-10 + numpy.fabs( 1.0/(P_orb.value_in(units.s)) - 1.0/(P_spin.value_in(units.s)) ) ) + P_spin = 2.0 * numpy.pi / spin_angular_frequency + P_tid_s = 1.0 / ( + 1e-10 + + numpy.fabs( + 1.0 / (P_orb.value_in(units.s)) - 1.0 / (P_spin.value_in(units.s)) + ) + ) P_tid = P_tid_s | units.s - tau_convective = pow( (convective_envelope_mass*convective_envelope_radius*(radius - (1.0/2.0)*convective_envelope_radius))/(3.0*luminosity), 1.0/3.0) -# print 'tau',envelope_mass,envelope_mass*envelope_radius*(radius - (1.0/2.0)*envelope_radius)/(3.0*luminosity) - - #print 'tau convective',tau_convective - f_convective = (P_tid/(2.0*tau_convective))**2 - - f_convective = numpy.amin([1.0,f_convective]) - - k_div_T_tides = (2.0/21.0)*(f_convective/tau_convective)*(convective_envelope_mass/mass) -# print('convective damping', mass, k_div_T_tides) + tau_convective = pow( + ( + convective_envelope_mass + * convective_envelope_radius + * (radius - (1.0 / 2.0) * convective_envelope_radius) + ) + / (3.0 * luminosity), + 1.0 / 3.0, + ) + # print 'tau',envelope_mass,envelope_mass*envelope_radius*(radius - (1.0/2.0)*envelope_radius)/(3.0*luminosity) + + # print 'tau convective',tau_convective + f_convective = (P_tid / (2.0 * tau_convective)) ** 2 + + f_convective = numpy.amin([1.0, f_convective]) + + k_div_T_tides = ( + (2.0 / 21.0) + * (f_convective / tau_convective) + * (convective_envelope_mass / mass) + ) + # print('convective damping', mass, k_div_T_tides) return k_div_T_tides - elif stellar_type==NS or stellar_type==BH: + elif stellar_type == NS or stellar_type == BH: ### no tides for NS or BH - k_div_T_tides = 0 -# print('ns/bh tides', k_div_T_tides, stellar_type) - return k_div_T_tides - elif stellar_type==PLANET or stellar_type==BD: #based on Fabrycky & Tremaine 2007, appendix - T_viscous = 0.001|units.yr - return amc/T_viscous - else: ### degenerate damping -- 1984MNRAS.207..433C ### - tau_degenerate = 1.3e7 | units.yr - k_div_T_tides = (1.0/(3.0*tau_degenerate))*gyration_radius**2*pow(luminosity.value_in(units.LSun)/mass.value_in(units.MSun),5.0/7.0) -# print('degenerate damping', k_div_T_tides) -# print('degenerate damping ', k_div_T_tides, gyration_radius_star1, luminosity.value_in(units.LSun),mass.value_in(units.MSun)) + k_div_T_tides = 0 + # print('ns/bh tides', k_div_T_tides, stellar_type) + return k_div_T_tides + elif ( + stellar_type == PLANET or stellar_type == BD + ): # based on Fabrycky & Tremaine 2007, appendix + T_viscous = 0.001 | units.yr + return amc / T_viscous + else: ### degenerate damping -- 1984MNRAS.207..433C ### + tau_degenerate = 1.3e7 | units.yr + k_div_T_tides = ( + (1.0 / (3.0 * tau_degenerate)) + * gyration_radius**2 + * pow( + luminosity.value_in(units.LSun) / mass.value_in(units.MSun), 5.0 / 7.0 + ) + ) + # print('degenerate damping', k_div_T_tides) + # print('degenerate damping ', k_div_T_tides, gyration_radius_star1, luminosity.value_in(units.LSun),mass.value_in(units.MSun)) return k_div_T_tides From 486d48043d68a917e9448c5b22ab05e76553c2a2 Mon Sep 17 00:00:00 2001 From: Steven Rieder Date: Mon, 4 Nov 2024 13:46:45 +0100 Subject: [PATCH 17/30] refactor triple_class --- src/tres/triple_class.py | 172 +++++++++++++++++++-------------------- 1 file changed, 85 insertions(+), 87 deletions(-) diff --git a/src/tres/triple_class.py b/src/tres/triple_class.py index 66756e5..a98bc5f 100644 --- a/src/tres/triple_class.py +++ b/src/tres/triple_class.py @@ -10,6 +10,7 @@ # from math import isnan import numpy as np +# FIXME SR: don't import * here from tres.interactions import * from tres.tidal_friction_constant import * @@ -26,10 +27,10 @@ from tres.options import * from tres.setup import setup_secular_code, setup_stellar_code -from tres.plotting import plot_data_container +from tres.plotting import PlotDataContainer -class Triple_Class: +class Triple: # ------- # setup stellar system def __init__( @@ -72,7 +73,7 @@ def __init__( ): self.correct_params = correct_params - if correct_params == False: + if correct_params is False: self.triple = Particles(1) return @@ -207,8 +208,8 @@ def initialize_secular( self.secular_code.check_for_dynamical_stability() if ( - stop_at_dynamical_instability == True - and self.secular_code.triples[0].dynamical_instability == True + stop_at_dynamical_instability is True + and self.secular_code.triples[0].dynamical_instability is True ): self.dynamical_instability_at_initialisation = True self.triple.dynamical_instability = True @@ -217,8 +218,8 @@ def initialize_secular( self.secular_code.check_for_semisecular_regime() if ( - stop_at_semisecular_regime == True - and self.secular_code.triples[0].semisecular_regime == True + stop_at_semisecular_regime is True + and self.secular_code.triples[0].semisecular_regime is True ): self.semisecular_regime_at_initialisation = True self.triple.semisecular_regime = True @@ -244,19 +245,19 @@ def set_stopping_conditions( stop_at_CPU_time, ): - if stop_at_disintegrated == False: + if stop_at_disintegrated is False: sys.exit( "stop_at_disintegrated = False not possible yet. After the disintegration of the triple, further evolution can be done with stellar code directly. " ) - if stop_at_outer_mass_transfer == False: + if stop_at_outer_mass_transfer is False: sys.exit( "stop_at_outer_mass_transfer = False not possible yet. Methodology is as of yet non-existent." ) - if stop_at_outer_collision == False: + if stop_at_outer_collision is False: sys.exit( "stop_at_outer_collision = False not possible. Non-hierarchical triples can not be simulated using the secular equations as used in TRES. Further evolution should be done by other means, e.g. one of the N-body codes implemented in AMUSE." ) - if stop_at_dynamical_instability == False: + if stop_at_dynamical_instability is False: sys.exit( "stop_at_dynamical_instability = False not possible. Unstable triples can not be simulated using the secular equations as used in TRES. Further evolution should be done by other means, e.g. one of the N-body codes implemented in AMUSE." ) @@ -312,7 +313,7 @@ def copy_from_stellar(self): # ------- def initial_angular_frequency(self, stellar_system=None): - if stellar_system == None: + if stellar_system is None: stellar_system = self.triple self.previous_time = self.triple.time @@ -348,7 +349,7 @@ def initial_angular_frequency(self, stellar_system=None): # ------- def refresh_memory(self, stellar_system=None): - if stellar_system == None: + if stellar_system is None: stellar_system = self.triple self.triple.time = self.previous_time @@ -376,7 +377,7 @@ def refresh_memory(self, stellar_system=None): stellar_system.kozai_type = stellar_system.previous_kozai_type def update_previous_stellar_parameters(self, stellar_system=None): - if stellar_system == None: + if stellar_system is None: stellar_system = self.triple self.previous_time = self.triple.time @@ -413,7 +414,7 @@ def update_previous_stellar_parameters(self, stellar_system=None): def update_time_derivative_of_radius(self, stellar_system=None): # update time_derivative_of_radius for effect of wind on spin # radius change due to stellar evolution, not mass transfer - if stellar_system == None: + if stellar_system is None: stellar_system = self.triple time_step = self.triple.time - self.previous_time @@ -441,7 +442,7 @@ def update_time_derivative_of_radius(self, stellar_system=None): # ------- def update_time_derivative_of_moment_of_inertia(self, stellar_system=None): # update time_derivative_of_radius for effect of changing Jspin - if stellar_system == None: + if stellar_system is None: stellar_system = self.triple time_step = self.triple.time - self.previous_time @@ -475,7 +476,7 @@ def update_stellar_parameters(self, stellar_system=None): # the prescription of Hurley, Pols & Tout 2000 is implemented in SeBa, however note that the prescription in BSE is different # for the convective envelope radius: # the prescription of Hurley, Tout & Pols 2002 is implemented in SeBa, however note that the prescription in BSE is different - if stellar_system == None: + if stellar_system is None: stellar_system = self.triple if stellar_system.is_star: @@ -521,7 +522,7 @@ def update_stellar_parameters(self, stellar_system=None): # whether or not a stellar system consists of just two stars def is_binary(self, stellar_system=None): - if stellar_system == None: + if stellar_system is None: stellar_system = self.triple if ( @@ -534,7 +535,7 @@ def is_binary(self, stellar_system=None): return False def is_triple(self, stellar_system=None): - if stellar_system == None: + if stellar_system is None: stellar_system = self.triple if not stellar_system.is_star: @@ -548,7 +549,7 @@ def is_triple(self, stellar_system=None): return False def has_donor(self, stellar_system=None): - if stellar_system == None: + if stellar_system is None: stellar_system = self.triple if stellar_system.is_star: @@ -563,7 +564,7 @@ def has_donor(self, stellar_system=None): return False def has_OLOF_donor(self, stellar_system=None): - if stellar_system == None: + if stellar_system is None: stellar_system = self.triple if stellar_system.is_star: @@ -578,7 +579,7 @@ def has_OLOF_donor(self, stellar_system=None): return False def has_contact_system(self, stellar_system=None): - if stellar_system == None: + if stellar_system is None: stellar_system = self.triple if stellar_system.is_star: @@ -596,7 +597,7 @@ def has_contact_system(self, stellar_system=None): # if a merger is currently taking place, not if a merger has happened in the past def has_merger(self, stellar_system=None): - if stellar_system == None: + if stellar_system is None: stellar_system = self.triple if stellar_system.is_star: @@ -613,7 +614,7 @@ def has_merger(self, stellar_system=None): # if a disruption is currently taking place, not if a disruption has happened in the past def has_disintegrated(self, stellar_system=None): - if stellar_system == None: + if stellar_system is None: stellar_system = self.triple if stellar_system.is_star: @@ -630,7 +631,7 @@ def has_disintegrated(self, stellar_system=None): # if a dynamical instability is currently taking place, not if an instability has happened in the past def has_dynamical_instability(self, stellar_system=None): - if stellar_system == None: + if stellar_system is None: stellar_system = self.triple if stellar_system.is_star: @@ -647,10 +648,10 @@ def has_dynamical_instability(self, stellar_system=None): def set_bintype_to_dynamical_instability(self, stellar_system=None): if self.triple.dynamical_instability: - if stellar_system == None: + if stellar_system is None: stellar_system = self.triple - if stellar_system.is_star == False: + if stellar_system.is_star is False: stellar_system.bin_type = bin_type["dyn_inst"] self.set_bintype_to_dynamical_instability(stellar_system.child1) self.set_bintype_to_dynamical_instability(stellar_system.child2) @@ -658,7 +659,7 @@ def set_bintype_to_dynamical_instability(self, stellar_system=None): # doesn't work well, as it uses bin_types that are set later -> use has_tertiary_donor # if a mass transfer in the outer binary of the triple is currently taking place, not if a mass transfer has happened in the past # def has_outer_mass_transfer(self, stellar_system = None): - # if stellar_system == None: + # if stellar_system is None: # stellar_system = self.triple # # if stellar_system.is_star: @@ -677,7 +678,7 @@ def set_bintype_to_dynamical_instability(self, stellar_system=None): # if a mass transfer in the outer binary of the triple is currently taking place, not if a mass transfer has happened in the past def has_tertiary_donor(self, stellar_system=None): - if stellar_system == None: + if stellar_system is None: stellar_system = self.triple if stellar_system.is_star: @@ -704,7 +705,7 @@ def has_tertiary_donor(self, stellar_system=None): return False def contains_SN_remnant(self, stellar_system=None): - if stellar_system == None: + if stellar_system is None: stellar_system = self.triple if stellar_system.is_star: @@ -719,7 +720,7 @@ def contains_SN_remnant(self, stellar_system=None): return False def has_stellar_type_changed_into_SN_remnant(self, stellar_system=None): - if stellar_system == None: + if stellar_system is None: stellar_system = self.triple if stellar_system.is_star: @@ -737,7 +738,7 @@ def has_stellar_type_changed_into_SN_remnant(self, stellar_system=None): return False def has_stellar_type_changed(self, stellar_system=None): - if stellar_system == None: + if stellar_system is None: stellar_system = self.triple if stellar_system.is_star: @@ -752,7 +753,7 @@ def has_stellar_type_changed(self, stellar_system=None): return False def has_kozai_type_changed(self, stellar_system=None): - if stellar_system == None: + if stellar_system is None: stellar_system = self.triple if self.is_triple(stellar_system): @@ -763,7 +764,7 @@ def has_kozai_type_changed(self, stellar_system=None): # obsolete? # def is_system_stable(self, stellar_system = None): - # if stellar_system == None: + # if stellar_system is None: # stellar_system = self.triple # # if stellar_system.is_star: @@ -777,7 +778,7 @@ def has_kozai_type_changed(self, stellar_system=None): # return False def get_mass(self, stellar_system=None): - if stellar_system == None: + if stellar_system is None: stellar_system = self.triple if stellar_system.is_star: @@ -788,7 +789,7 @@ def get_mass(self, stellar_system=None): return M1 + M2 def get_size(self, stellar_system=None): - if stellar_system == None: + if stellar_system is None: stellar_system = self.triple if stellar_system.is_star: @@ -934,7 +935,7 @@ def kozai_timescale(self): def get_kozai_type(self): if self.is_triple(): - if self.secular_code.parameters.ignore_tertiary == True: + if self.secular_code.parameters.ignore_tertiary is True: return False t_kozai = self.kozai_timescale() @@ -950,7 +951,7 @@ def get_kozai_type(self): sys.exit("Kozai type needs triple system") def get_min_stellar_evolution_timescale_of_system(self, stellar_system=None): - if stellar_system == None: + if stellar_system is None: stellar_system = self.triple if stellar_system.is_star: @@ -990,7 +991,7 @@ def check_RLOF(self): ): self.triple.child2.is_donor = True - elif self.is_triple() and self.secular_code.parameters.ignore_tertiary == True: + elif self.is_triple() and self.secular_code.parameters.ignore_tertiary is True: # for disrupted binary if self.triple.child1.is_star: bin = self.triple.child2 @@ -1192,7 +1193,7 @@ def check_CHE(self): # future option: potentially use: che_flag in SeBa # # def determine_partial_timestep_stable_mass_transfer(self, stellar_system = None): - # if stellar_system == None: + # if stellar_system is None: # stellar_system = self.triple # # if stellar_system.is_star: @@ -1290,7 +1291,7 @@ def print_binary(self, binary): sys.exit("print_binary needs a binary") def print_stellar_system(self, stellar_system=None): - if stellar_system == None: + if stellar_system is None: stellar_system = self.triple print( stellar_system.number, @@ -1310,7 +1311,7 @@ def print_stellar_system(self, stellar_system=None): # ------- # don't change this unless you know what you're doing def remove_parents(self, stellar_system=None): - if stellar_system == None: + if stellar_system is None: stellar_system = self.triple parents = [] @@ -1335,7 +1336,7 @@ def remove_parents(self, stellar_system=None): # don't change this unless you know what you're doing def set_parents(self, parents, stellar_system=None): - if stellar_system == None: + if stellar_system is None: stellar_system = self.triple if stellar_system.is_star: @@ -1433,7 +1434,7 @@ def save_snapshot(self): # determining time steps def determine_time_step_wind(self, stellar_system=None): # note: returned value can be inf when the wind_mass_loss_rate = 0 - if stellar_system == None: + if stellar_system is None: stellar_system = self.triple if stellar_system.is_star: @@ -1466,7 +1467,7 @@ def determine_time_step_radius_change(self, stellar_system=None): ): return np.inf | units.Myr - if stellar_system == None: + if stellar_system is None: stellar_system = self.triple if stellar_system.is_star: @@ -1528,7 +1529,7 @@ def determine_time_step_kozai(self): def determine_time_step_stable_mt(self, stellar_system=None): # note: returned value can be inf when the mass_transfer_rate = 0 - if stellar_system == None: + if stellar_system is None: stellar_system = self.triple if stellar_system.is_star: @@ -1597,7 +1598,7 @@ def e_dot_tides(self, star, m_comp, semi, eccentricity): def determine_time_step_tides(self, stellar_system=None): # print("determine_time_step_tides") - if stellar_system == None: + if stellar_system is None: stellar_system = self.triple if self.triple.is_star: @@ -2064,7 +2065,7 @@ def get_SN_kick(self, star): def save_mean_anomalies_at_SN( self, inner_mean_anomaly, outer_mean_anomaly, stellar_system=None ): - if stellar_system == None: + if stellar_system is None: stellar_system = self.triple if stellar_system.is_star: @@ -2083,7 +2084,7 @@ def save_mean_anomalies_at_SN( ) def adjust_spin_after_supernova(self, stellar_system=None): - if stellar_system == None: + if stellar_system is None: stellar_system = self.triple if stellar_system.is_star: @@ -2330,7 +2331,7 @@ def adjust_system_after_supernova_kick(self): # that can evaporise part of the planetary envelope. # would be best to do in secular code instead, such that eccentricity variations due to KL are taken into account properly def planetary_mass_evaporation(self, dt, stellar_system=None): - if stellar_system == None: + if stellar_system is None: stellar_system = self.triple if stellar_system.is_star: @@ -2411,7 +2412,7 @@ def planetary_mass_evaporation(self, dt, stellar_system=None): def resolve_stellar_interaction(self, stellar_system=None): # the most inner binary is calculated first, and then move outwards - if stellar_system == None: + if stellar_system is None: stellar_system = self.triple if stellar_system.is_star: @@ -2456,7 +2457,7 @@ def resolve_stellar_interaction(self, stellar_system=None): def determine_mass_transfer_timescale(self, stellar_system=None): - if stellar_system == None: + if stellar_system is None: stellar_system = self.triple if stellar_system.is_star: @@ -2502,7 +2503,7 @@ def solve_for_partial_time_step_stable_mass_transfer(self): return True def safety_check_time_step(self, stellar_system=None): - if stellar_system == None: + if stellar_system is None: stellar_system = self.triple successfull_dr = True @@ -2562,16 +2563,16 @@ def safety_check_time_step(self, stellar_system=None): successfull_dr2, nr_dr2, star_dr2 = self.safety_check_time_step( stellar_system.child2 ) - if successfull_dr1 == False and successfull_dr2 == False: + if successfull_dr1 is False and successfull_dr2 is False: if nr_dr1 > 1: return False, 3, np.array([star_dr1[0], star_dr1[1], star_dr2]) elif nr_dr2 > 1: return False, 3, np.array([star_dr1, star_dr2[0], star_dr2[1]]) else: return False, 2, np.array([star_dr1, star_dr2]) - elif successfull_dr1 == False: + elif successfull_dr1 is False: return False, nr_dr1, star_dr1 - elif successfull_dr2 == False: + elif successfull_dr2 is False: return False, nr_dr2, star_dr2 else: return True, 0, 0 @@ -2621,7 +2622,7 @@ def rewind_to_begin_of_rlof_stellar(self, dt): print("rewind to begin of rlof stellar") dt_new = dt dt_min = max(minimum_time_step, self.determine_time_step_stable_mt()) - while self.has_donor() == True and dt_new > dt_min: + while self.has_donor() is True and dt_new > dt_min: dt_old = self.triple.time - self.previous_time dt_new = max(minimum_time_step, 0.5 * dt_old) @@ -2698,7 +2699,7 @@ def check_stopping_conditions_stellar(self, stellar_system=None): # before check stopping conditions_stellar, always make sure the stability labels are up to date # by running self.determine_mass_transfer_timescale() - if stellar_system == None: + if stellar_system is None: stellar_system = self.triple if self.is_triple(stellar_system): @@ -2772,12 +2773,12 @@ def check_stopping_conditions_stellar(self, stellar_system=None): # when these processes are implemented, also the bintypes need to be set in those functions def check_stopping_conditions(self): - if self.check_stopping_conditions_stellar() == False: + if self.check_stopping_conditions_stellar() is False: return False if ( self.stop_at_dynamical_instability - and self.triple.dynamical_instability == True + and self.triple.dynamical_instability is True ): if self.secular_code.model_time < self.triple.time: self.triple.time = self.secular_code.model_time @@ -2785,23 +2786,20 @@ def check_stopping_conditions(self): if REPORT_TRIPLE_EVOLUTION: print("Dynamical instability at time = ", self.triple.time) return False - if self.stop_at_inner_collision and self.triple.inner_collision == True: - if self.secular_code.model_time < self.triple.time: - self.triple.time = self.secular_code.model_time + if self.stop_at_inner_collision and self.triple.inner_collision is True: + self.triple.time = min(self.secular_code.model_time, self.triple.time) self.triple.child2.bin_type = bin_type["collision"] if REPORT_TRIPLE_EVOLUTION: print("Inner collision at time = ", self.triple.time) return False - if self.stop_at_outer_collision and self.triple.outer_collision == True: - if self.secular_code.model_time < self.triple.time: - self.triple.time = self.secular_code.model_time + if self.stop_at_outer_collision and self.triple.outer_collision is True: + self.triple.time = min(self.secular_code.model_time, self.triple.time) self.triple.bin_type = bin_type["collision"] if REPORT_TRIPLE_EVOLUTION: print("Outer collision at time = ", self.triple.time) return False - if self.stop_at_semisecular_regime and self.triple.semisecular_regime == True: - if self.secular_code.model_time < self.triple.time: - self.triple.time = self.secular_code.model_time + if self.stop_at_semisecular_regime and self.triple.semisecular_regime is True: + self.triple.time = min(self.secular_code.model_time, self.triple.time) self.triple.bin_type = bin_type["semisecular"] if REPORT_TRIPLE_EVOLUTION: print("Semisecular regime at time = ", self.triple.time) @@ -2825,7 +2823,7 @@ def check_stopping_conditions(self): return True def check_spin_angular_frequency(self, stellar_system=None): - if stellar_system == None: + if stellar_system is None: stellar_system = self.triple if stellar_system.is_star: @@ -2837,8 +2835,8 @@ def check_spin_angular_frequency(self, stellar_system=None): return True else: if ( - self.check_spin_angular_frequency(stellar_system.child1) == False - or self.check_spin_angular_frequency(stellar_system.child2) == False + self.check_spin_angular_frequency(stellar_system.child1) is False + or self.check_spin_angular_frequency(stellar_system.child2) is False ): return False return True @@ -2971,7 +2969,7 @@ def evolve_model(self, tend): # if the maximum CPU time has been exceeded for the system, stop the evolution and continue with the next system CPU_end_time = time.time() self.triple.CPU_time = CPU_end_time - CPU_start_time - if (self.stop_at_CPU_time == True) and float( + if (self.stop_at_CPU_time is True) and float( CPU_end_time - CPU_start_time ) > self.max_CPU_time: print("stopping conditions maximum CPU time") @@ -2980,9 +2978,9 @@ def evolve_model(self, tend): # turning RLOF terms back on if they were on in the first place # they might have been turned off for contact systems with is_mt_stable in perform_mass_equalisation_for_contact - if include_inner_RLOF_term_initial == True: + if include_inner_RLOF_term_initial is True: self.secular_code.parameters.include_inner_RLOF_terms = True - if include_outer_RLOF_term_initial == True: + if include_outer_RLOF_term_initial is True: self.secular_code.parameters.include_outer_RLOF_terms = True # setting time parameters @@ -3019,7 +3017,7 @@ def evolve_model(self, tend): successfull_step, nr_unsuccessfull, star_unsuccessfull = ( self.safety_check_time_step() ) - while successfull_step == False: + while successfull_step is False: successfull_step, nr_unsuccessfull, star_unsuccessfull = ( self.recall_memory_one_step_stellar( nr_unsuccessfull, star_unsuccessfull @@ -3030,7 +3028,7 @@ def evolve_model(self, tend): if self.has_stellar_type_changed_into_SN_remnant(): if REPORT_TRIPLE_EVOLUTION: print("Supernova at time = ", self.triple.time, dt) - if self.adjust_system_after_supernova_kick() == False: + if self.adjust_system_after_supernova_kick() is False: break self.instantaneous_evolution = True # skip secular evolution @@ -3066,7 +3064,7 @@ def evolve_model(self, tend): print("Stellar interaction") self.determine_mass_transfer_timescale() - if self.check_stopping_conditions_stellar() == False: + if self.check_stopping_conditions_stellar() is False: print("stopping conditions stellar") break if not self.resolve_stellar_interaction(): @@ -3074,12 +3072,12 @@ def evolve_model(self, tend): break self.update_time_derivative_of_radius() # includes radius change from wind and ce, not stable mt self.update_time_derivative_of_moment_of_inertia() # includes mass and radius change from wind and mass transfer - if self.check_stopping_conditions_stellar_interaction() == False: + if self.check_stopping_conditions_stellar_interaction() is False: print("stopping conditions stellar interaction 2") break # do secular evolution - if self.instantaneous_evolution == False: + if self.instantaneous_evolution is False: if REPORT_DEBUG: print("Secular evolution") @@ -3103,7 +3101,7 @@ def evolve_model(self, tend): self.triple.child2.part_dt_mt < 1 ): # inner binary, see function determine_partial_time_step_stable_mass_transfer print("skipping") - if self.solve_for_partial_time_step_stable_mass_transfer() == False: + if self.solve_for_partial_time_step_stable_mass_transfer() is False: break else: self.secular_code.evolve_model(self.triple.time) @@ -3143,7 +3141,7 @@ def evolve_model(self, tend): # factor 0.01 times time_step_stable_mt as used mass_transfer_timescale from previous timestep self.determine_mass_transfer_timescale() - if self.check_stopping_conditions_stellar() == False: + if self.check_stopping_conditions_stellar() is False: print("stopping conditions stellar 2") break @@ -3169,17 +3167,17 @@ def evolve_model(self, tend): self.channel_from_secular.copy() - if self.check_error_flag_secular() == False: + if self.check_error_flag_secular() is False: break - if self.check_spin_angular_frequency() == False: + if self.check_spin_angular_frequency() is False: break self.determine_mass_transfer_timescale() - if self.check_stopping_conditions() == False: + if self.check_stopping_conditions() is False: print("stopping conditions") break if ( not self.stop_at_inner_collision - and self.triple.inner_collision == True + and self.triple.inner_collision is True ): perform_inner_collision(self) @@ -3268,7 +3266,7 @@ def evolve_model(self, tend): RL2_array = np.array(RL2_array) RL3_array = np.array(RL3_array) - self.plot_data = plot_data_container() + self.plot_data = PlotDataContainer() self.plot_data.times_array = times_array self.plot_data.a_in_array = a_in_array self.plot_data.e_in_array = e_in_array From 562f0f0091453766627bf943d5176f00cd140ac1 Mon Sep 17 00:00:00 2001 From: Steven Rieder Date: Mon, 4 Nov 2024 13:50:22 +0100 Subject: [PATCH 18/30] refactor SecularTriple python code --- src/tres/seculartriple_TPS/interface.py | 3365 +++++++++++------ .../tidal_friction_constant.py | 179 +- 2 files changed, 2344 insertions(+), 1200 deletions(-) diff --git a/src/tres/seculartriple_TPS/interface.py b/src/tres/seculartriple_TPS/interface.py index 1238d41..8010a20 100644 --- a/src/tres/seculartriple_TPS/interface.py +++ b/src/tres/seculartriple_TPS/interface.py @@ -6,1445 +6,1945 @@ """ from amuse.community import * -from amuse.units import units,constants +from amuse.units import units, constants import sys ### units used internally in the ODE solver ### unit_l = units.AU unit_m = units.MSun -unit_t = 1.0e6*units.yr -unit_h = unit_m*unit_l**2/unit_t ### angular momentum +unit_t = 1.0e6 * units.yr +unit_h = unit_m * unit_l**2 / unit_t ### angular momentum ### CVODE flags ### -CV_SUCCESS=0 -CV_ROOT_RETURN=2 -CV_WARNING=99 -CV_TOO_MUCH_WORK=-1 -CV_TOO_MUCH_ACC=-2 -CV_ERR_FAILURE=-3 -CV_CONV_FAILURE=-4 -CV_LINIT_FAIL=-5 -CV_LSETUP_FAIL=-6 -CV_LSOLVE_FAIL=-7 -CV_RHSFUNC_FAIL=-8 -CV_FIRST_RHSFUNC_ERR=-9 -CV_REPTD_RHSFUNC_ERR=-10 -CV_UNREC_RHSFUNC_ERR=-11 -CV_RTFUNC_FAIL=-12 -CV_MEM_FAIL=-20 -CV_MEM_NULL=-21 -CV_ILL_INPUT=-22 -CV_NO_MALLOC=-23 -CV_BAD_K=-24 -CV_BAD_T=-25 -CV_BAD_DKY=-26 -CV_TOO_CLOSE=-27 +CV_SUCCESS = 0 +CV_ROOT_RETURN = 2 +CV_WARNING = 99 +CV_TOO_MUCH_WORK = -1 +CV_TOO_MUCH_ACC = -2 +CV_ERR_FAILURE = -3 +CV_CONV_FAILURE = -4 +CV_LINIT_FAIL = -5 +CV_LSETUP_FAIL = -6 +CV_LSOLVE_FAIL = -7 +CV_RHSFUNC_FAIL = -8 +CV_FIRST_RHSFUNC_ERR = -9 +CV_REPTD_RHSFUNC_ERR = -10 +CV_UNREC_RHSFUNC_ERR = -11 +CV_RTFUNC_FAIL = -12 +CV_MEM_FAIL = -20 +CV_MEM_NULL = -21 +CV_ILL_INPUT = -22 +CV_NO_MALLOC = -23 +CV_BAD_K = -24 +CV_BAD_T = -25 +CV_BAD_DKY = -26 +CV_TOO_CLOSE = -27 class SecularTripleInterface(CodeInterface): - include_headers = ['src/main_code.h','src/ODE_system.h'] + include_headers = ["src/main_code.h", "src/ODE_system.h"] def __init__(self, **options): - CodeInterface.__init__(self, **options) - + CodeInterface.__init__(self, **options) + @legacy_function def evolve(): function = LegacyFunctionSpecification() - function.addParameter('stellar_type1', dtype='int32', direction=function.IN) - function.addParameter('stellar_type2', dtype='int32', direction=function.IN) - function.addParameter('stellar_type3', dtype='int32', direction=function.IN) - function.addParameter('m1', dtype='float64', direction=function.IN) - function.addParameter('m2', dtype='float64', direction=function.IN) - function.addParameter('m3', dtype='float64', direction=function.IN) - function.addParameter('m1_convective_envelope', dtype='float64', direction=function.IN) - function.addParameter('m2_convective_envelope', dtype='float64', direction=function.IN) - function.addParameter('m3_convective_envelope', dtype='float64', direction=function.IN) - function.addParameter('R1', dtype='float64', direction=function.IN) - function.addParameter('R2', dtype='float64', direction=function.IN) - function.addParameter('R3', dtype='float64', direction=function.IN) - function.addParameter('R1_convective_envelope', dtype='float64', direction=function.IN) - function.addParameter('R2_convective_envelope', dtype='float64', direction=function.IN) - function.addParameter('R3_convective_envelope', dtype='float64', direction=function.IN) - function.addParameter('luminosity_star1', dtype='float64', direction=function.IN) - function.addParameter('luminosity_star2', dtype='float64', direction=function.IN) - function.addParameter('luminosity_star3', dtype='float64', direction=function.IN) - function.addParameter('spin_angular_frequency1', dtype='float64', direction=function.IN) - function.addParameter('spin_angular_frequency2', dtype='float64', direction=function.IN) - function.addParameter('spin_angular_frequency3', dtype='float64', direction=function.IN) - function.addParameter('AMC_star1', dtype='float64', direction=function.IN) - function.addParameter('AMC_star2', dtype='float64', direction=function.IN) - function.addParameter('AMC_star3', dtype='float64', direction=function.IN) - function.addParameter('gyration_radius_star1', dtype='float64', direction=function.IN) - function.addParameter('gyration_radius_star2', dtype='float64', direction=function.IN) - function.addParameter('gyration_radius_star3', dtype='float64', direction=function.IN) - function.addParameter('moment_of_inertia_star1', dtype='float64', direction=function.IN) - function.addParameter('moment_of_inertia_star2', dtype='float64', direction=function.IN) - function.addParameter('moment_of_inertia_star3', dtype='float64', direction=function.IN) - function.addParameter('moment_of_inertia_dot_star1', dtype='float64', direction=function.IN) - function.addParameter('moment_of_inertia_dot_star2', dtype='float64', direction=function.IN) - function.addParameter('moment_of_inertia_dot_star3', dtype='float64', direction=function.IN) -# function.addParameter('k_div_T_tides_star1', dtype='float64', direction=function.IN) -# function.addParameter('k_div_T_tides_star2', dtype='float64', direction=function.IN) -# function.addParameter('k_div_T_tides_star3', dtype='float64', direction=function.IN) - function.addParameter('a_in', dtype='float64', direction=function.IN) - function.addParameter('a_out', dtype='float64', direction=function.IN) - function.addParameter('e_in', dtype='float64', direction=function.IN) - function.addParameter('e_out', dtype='float64', direction=function.IN) - function.addParameter('INCL_in', dtype='float64', direction=function.IN) - function.addParameter('INCL_out', dtype='float64', direction=function.IN) - function.addParameter('AP_in', dtype='float64', direction=function.IN) - function.addParameter('AP_out', dtype='float64', direction=function.IN) - function.addParameter('LAN_in', dtype='float64', direction=function.IN) - function.addParameter('LAN_out', dtype='float64', direction=function.IN) - function.addParameter('star1_is_donor', dtype='bool', direction=function.IN) - function.addParameter('star2_is_donor', dtype='bool', direction=function.IN) - function.addParameter('star3_is_donor', dtype='bool', direction=function.IN) - function.addParameter('wind_mass_loss_rate_star1', dtype='float64', direction=function.IN) - function.addParameter('wind_mass_loss_rate_star2', dtype='float64', direction=function.IN) - function.addParameter('wind_mass_loss_rate_star3', dtype='float64', direction=function.IN) - function.addParameter('time_derivative_of_radius_star1', dtype='float64', direction=function.IN) - function.addParameter('time_derivative_of_radius_star2', dtype='float64', direction=function.IN) - function.addParameter('time_derivative_of_radius_star3', dtype='float64', direction=function.IN) - function.addParameter('inner_mass_transfer_rate', dtype='float64', direction=function.IN) - function.addParameter('outer_mass_transfer_rate', dtype='float64', direction=function.IN) - function.addParameter('inner_accretion_efficiency_wind_child1_to_child2', dtype='float64', direction=function.IN) - function.addParameter('inner_accretion_efficiency_wind_child2_to_child1', dtype='float64', direction=function.IN) - function.addParameter('outer_accretion_efficiency_wind_child1_to_child2', dtype='float64', direction=function.IN) - function.addParameter('outer_accretion_efficiency_wind_child2_to_child1', dtype='float64', direction=function.IN) - function.addParameter('inner_accretion_efficiency_mass_transfer', dtype='float64', direction=function.IN) - function.addParameter('outer_accretion_efficiency_mass_transfer', dtype='float64', direction=function.IN) - function.addParameter('inner_specific_AM_loss_mass_transfer', dtype='float64', direction=function.IN) - function.addParameter('outer_specific_AM_loss_mass_transfer', dtype='float64', direction=function.IN) - function.addParameter('inner_spin_angular_momentum_wind_accretion_efficiency_child1_to_child2', dtype='float64', direction=function.IN) - function.addParameter('inner_spin_angular_momentum_wind_accretion_efficiency_child2_to_child1', dtype='float64', direction=function.IN) - function.addParameter('t', dtype='float64', direction=function.IN) - function.addParameter('global_time_step', dtype='float64', direction=function.IN) - function.addParameter('m1_output', dtype='float64', direction=function.OUT) - function.addParameter('m2_output', dtype='float64', direction=function.OUT) - function.addParameter('m3_output', dtype='float64', direction=function.OUT) - function.addParameter('R1_output', dtype='float64', direction=function.OUT) - function.addParameter('R2_output', dtype='float64', direction=function.OUT) - function.addParameter('R3_output', dtype='float64', direction=function.OUT) - function.addParameter('spin_angular_frequency1_output', dtype='float64', direction=function.OUT) - function.addParameter('spin_angular_frequency2_output', dtype='float64', direction=function.OUT) - function.addParameter('spin_angular_frequency3_output', dtype='float64', direction=function.OUT) - function.addParameter('a_in_output', dtype='float64', direction=function.OUT) - function.addParameter('a_out_output', dtype='float64', direction=function.OUT) - function.addParameter('e_in_output', dtype='float64', direction=function.OUT) - function.addParameter('e_out_output', dtype='float64', direction=function.OUT) - function.addParameter('delta_e_in_output', dtype='float64', direction=function.OUT) - function.addParameter('INCL_in_output', dtype='float64', direction=function.OUT) - function.addParameter('INCL_out_output', dtype='float64', direction=function.OUT) - function.addParameter('INCL_in_out_output', dtype='float64', direction=function.OUT) - function.addParameter('AP_in_output', dtype='float64', direction=function.OUT) - function.addParameter('AP_out_output', dtype='float64', direction=function.OUT) - function.addParameter('LAN_in_output', dtype='float64', direction=function.OUT) - function.addParameter('LAN_out_output', dtype='float64', direction=function.OUT) - function.addParameter('t_output', dtype='float64', direction=function.OUT) - function.addParameter('CVODE_flag', dtype='int32', direction=function.OUT) - function.addParameter('root_finding_flag', dtype='int32', direction=function.OUT) - function.result_type = 'int32' + function.addParameter("stellar_type1", dtype="int32", direction=function.IN) + function.addParameter("stellar_type2", dtype="int32", direction=function.IN) + function.addParameter("stellar_type3", dtype="int32", direction=function.IN) + function.addParameter("m1", dtype="float64", direction=function.IN) + function.addParameter("m2", dtype="float64", direction=function.IN) + function.addParameter("m3", dtype="float64", direction=function.IN) + function.addParameter( + "m1_convective_envelope", dtype="float64", direction=function.IN + ) + function.addParameter( + "m2_convective_envelope", dtype="float64", direction=function.IN + ) + function.addParameter( + "m3_convective_envelope", dtype="float64", direction=function.IN + ) + function.addParameter("R1", dtype="float64", direction=function.IN) + function.addParameter("R2", dtype="float64", direction=function.IN) + function.addParameter("R3", dtype="float64", direction=function.IN) + function.addParameter( + "R1_convective_envelope", dtype="float64", direction=function.IN + ) + function.addParameter( + "R2_convective_envelope", dtype="float64", direction=function.IN + ) + function.addParameter( + "R3_convective_envelope", dtype="float64", direction=function.IN + ) + function.addParameter( + "luminosity_star1", dtype="float64", direction=function.IN + ) + function.addParameter( + "luminosity_star2", dtype="float64", direction=function.IN + ) + function.addParameter( + "luminosity_star3", dtype="float64", direction=function.IN + ) + function.addParameter( + "spin_angular_frequency1", dtype="float64", direction=function.IN + ) + function.addParameter( + "spin_angular_frequency2", dtype="float64", direction=function.IN + ) + function.addParameter( + "spin_angular_frequency3", dtype="float64", direction=function.IN + ) + function.addParameter("AMC_star1", dtype="float64", direction=function.IN) + function.addParameter("AMC_star2", dtype="float64", direction=function.IN) + function.addParameter("AMC_star3", dtype="float64", direction=function.IN) + function.addParameter( + "gyration_radius_star1", dtype="float64", direction=function.IN + ) + function.addParameter( + "gyration_radius_star2", dtype="float64", direction=function.IN + ) + function.addParameter( + "gyration_radius_star3", dtype="float64", direction=function.IN + ) + function.addParameter( + "moment_of_inertia_star1", dtype="float64", direction=function.IN + ) + function.addParameter( + "moment_of_inertia_star2", dtype="float64", direction=function.IN + ) + function.addParameter( + "moment_of_inertia_star3", dtype="float64", direction=function.IN + ) + function.addParameter( + "moment_of_inertia_dot_star1", dtype="float64", direction=function.IN + ) + function.addParameter( + "moment_of_inertia_dot_star2", dtype="float64", direction=function.IN + ) + function.addParameter( + "moment_of_inertia_dot_star3", dtype="float64", direction=function.IN + ) + # function.addParameter('k_div_T_tides_star1', dtype='float64', direction=function.IN) + # function.addParameter('k_div_T_tides_star2', dtype='float64', direction=function.IN) + # function.addParameter('k_div_T_tides_star3', dtype='float64', direction=function.IN) + function.addParameter("a_in", dtype="float64", direction=function.IN) + function.addParameter("a_out", dtype="float64", direction=function.IN) + function.addParameter("e_in", dtype="float64", direction=function.IN) + function.addParameter("e_out", dtype="float64", direction=function.IN) + function.addParameter("INCL_in", dtype="float64", direction=function.IN) + function.addParameter("INCL_out", dtype="float64", direction=function.IN) + function.addParameter("AP_in", dtype="float64", direction=function.IN) + function.addParameter("AP_out", dtype="float64", direction=function.IN) + function.addParameter("LAN_in", dtype="float64", direction=function.IN) + function.addParameter("LAN_out", dtype="float64", direction=function.IN) + function.addParameter("star1_is_donor", dtype="bool", direction=function.IN) + function.addParameter("star2_is_donor", dtype="bool", direction=function.IN) + function.addParameter("star3_is_donor", dtype="bool", direction=function.IN) + function.addParameter( + "wind_mass_loss_rate_star1", dtype="float64", direction=function.IN + ) + function.addParameter( + "wind_mass_loss_rate_star2", dtype="float64", direction=function.IN + ) + function.addParameter( + "wind_mass_loss_rate_star3", dtype="float64", direction=function.IN + ) + function.addParameter( + "time_derivative_of_radius_star1", dtype="float64", direction=function.IN + ) + function.addParameter( + "time_derivative_of_radius_star2", dtype="float64", direction=function.IN + ) + function.addParameter( + "time_derivative_of_radius_star3", dtype="float64", direction=function.IN + ) + function.addParameter( + "inner_mass_transfer_rate", dtype="float64", direction=function.IN + ) + function.addParameter( + "outer_mass_transfer_rate", dtype="float64", direction=function.IN + ) + function.addParameter( + "inner_accretion_efficiency_wind_child1_to_child2", + dtype="float64", + direction=function.IN, + ) + function.addParameter( + "inner_accretion_efficiency_wind_child2_to_child1", + dtype="float64", + direction=function.IN, + ) + function.addParameter( + "outer_accretion_efficiency_wind_child1_to_child2", + dtype="float64", + direction=function.IN, + ) + function.addParameter( + "outer_accretion_efficiency_wind_child2_to_child1", + dtype="float64", + direction=function.IN, + ) + function.addParameter( + "inner_accretion_efficiency_mass_transfer", + dtype="float64", + direction=function.IN, + ) + function.addParameter( + "outer_accretion_efficiency_mass_transfer", + dtype="float64", + direction=function.IN, + ) + function.addParameter( + "inner_specific_AM_loss_mass_transfer", + dtype="float64", + direction=function.IN, + ) + function.addParameter( + "outer_specific_AM_loss_mass_transfer", + dtype="float64", + direction=function.IN, + ) + function.addParameter( + "inner_spin_angular_momentum_wind_accretion_efficiency_child1_to_child2", + dtype="float64", + direction=function.IN, + ) + function.addParameter( + "inner_spin_angular_momentum_wind_accretion_efficiency_child2_to_child1", + dtype="float64", + direction=function.IN, + ) + function.addParameter("t", dtype="float64", direction=function.IN) + function.addParameter( + "global_time_step", dtype="float64", direction=function.IN + ) + function.addParameter("m1_output", dtype="float64", direction=function.OUT) + function.addParameter("m2_output", dtype="float64", direction=function.OUT) + function.addParameter("m3_output", dtype="float64", direction=function.OUT) + function.addParameter("R1_output", dtype="float64", direction=function.OUT) + function.addParameter("R2_output", dtype="float64", direction=function.OUT) + function.addParameter("R3_output", dtype="float64", direction=function.OUT) + function.addParameter( + "spin_angular_frequency1_output", dtype="float64", direction=function.OUT + ) + function.addParameter( + "spin_angular_frequency2_output", dtype="float64", direction=function.OUT + ) + function.addParameter( + "spin_angular_frequency3_output", dtype="float64", direction=function.OUT + ) + function.addParameter("a_in_output", dtype="float64", direction=function.OUT) + function.addParameter("a_out_output", dtype="float64", direction=function.OUT) + function.addParameter("e_in_output", dtype="float64", direction=function.OUT) + function.addParameter("e_out_output", dtype="float64", direction=function.OUT) + function.addParameter( + "delta_e_in_output", dtype="float64", direction=function.OUT + ) + function.addParameter("INCL_in_output", dtype="float64", direction=function.OUT) + function.addParameter( + "INCL_out_output", dtype="float64", direction=function.OUT + ) + function.addParameter( + "INCL_in_out_output", dtype="float64", direction=function.OUT + ) + function.addParameter("AP_in_output", dtype="float64", direction=function.OUT) + function.addParameter("AP_out_output", dtype="float64", direction=function.OUT) + function.addParameter("LAN_in_output", dtype="float64", direction=function.OUT) + function.addParameter("LAN_out_output", dtype="float64", direction=function.OUT) + function.addParameter("t_output", dtype="float64", direction=function.OUT) + function.addParameter("CVODE_flag", dtype="int32", direction=function.OUT) + function.addParameter( + "root_finding_flag", dtype="int32", direction=function.OUT + ) + function.result_type = "int32" return function @legacy_function def compute_orbital_vectors_from_orbital_elements(): function = LegacyFunctionSpecification() - function.addParameter('m1', dtype='float64', direction=function.IN) - function.addParameter('m2', dtype='float64', direction=function.IN) - function.addParameter('m3', dtype='float64', direction=function.IN) - function.addParameter('a1', dtype='float64', direction=function.IN) - function.addParameter('a2', dtype='float64', direction=function.IN) - function.addParameter('e1', dtype='float64', direction=function.IN) - function.addParameter('e2', dtype='float64', direction=function.IN) - function.addParameter('INCL_rel', dtype='float64', direction=function.IN) - function.addParameter('AP1', dtype='float64', direction=function.IN) - function.addParameter('AP2', dtype='float64', direction=function.IN) - function.addParameter('LAN1', dtype='float64', direction=function.IN) - function.addParameter('LAN2', dtype='float64', direction=function.IN) - function.addParameter('e1_vec_x', dtype='float64',direction=function.OUT,description = "") - function.addParameter('e1_vec_y', dtype='float64',direction=function.OUT,description = "") - function.addParameter('e1_vec_z', dtype='float64',direction=function.OUT,description = "") - function.addParameter('e2_vec_x', dtype='float64',direction=function.OUT,description = "") - function.addParameter('e2_vec_y', dtype='float64',direction=function.OUT,description = "") - function.addParameter('e2_vec_z', dtype='float64',direction=function.OUT,description = "") - function.addParameter('h1_vec_x', dtype='float64',direction=function.OUT,description = "") - function.addParameter('h1_vec_y', dtype='float64',direction=function.OUT,description = "") - function.addParameter('h1_vec_z', dtype='float64',direction=function.OUT,description = "") - function.addParameter('h2_vec_x', dtype='float64',direction=function.OUT,description = "") - function.addParameter('h2_vec_y', dtype='float64',direction=function.OUT,description = "") - function.addParameter('h2_vec_z', dtype='float64',direction=function.OUT,description = "") - function.result_type = 'float64' - return function - + function.addParameter("m1", dtype="float64", direction=function.IN) + function.addParameter("m2", dtype="float64", direction=function.IN) + function.addParameter("m3", dtype="float64", direction=function.IN) + function.addParameter("a1", dtype="float64", direction=function.IN) + function.addParameter("a2", dtype="float64", direction=function.IN) + function.addParameter("e1", dtype="float64", direction=function.IN) + function.addParameter("e2", dtype="float64", direction=function.IN) + function.addParameter("INCL_rel", dtype="float64", direction=function.IN) + function.addParameter("AP1", dtype="float64", direction=function.IN) + function.addParameter("AP2", dtype="float64", direction=function.IN) + function.addParameter("LAN1", dtype="float64", direction=function.IN) + function.addParameter("LAN2", dtype="float64", direction=function.IN) + function.addParameter( + "e1_vec_x", dtype="float64", direction=function.OUT, description="" + ) + function.addParameter( + "e1_vec_y", dtype="float64", direction=function.OUT, description="" + ) + function.addParameter( + "e1_vec_z", dtype="float64", direction=function.OUT, description="" + ) + function.addParameter( + "e2_vec_x", dtype="float64", direction=function.OUT, description="" + ) + function.addParameter( + "e2_vec_y", dtype="float64", direction=function.OUT, description="" + ) + function.addParameter( + "e2_vec_z", dtype="float64", direction=function.OUT, description="" + ) + function.addParameter( + "h1_vec_x", dtype="float64", direction=function.OUT, description="" + ) + function.addParameter( + "h1_vec_y", dtype="float64", direction=function.OUT, description="" + ) + function.addParameter( + "h1_vec_z", dtype="float64", direction=function.OUT, description="" + ) + function.addParameter( + "h2_vec_x", dtype="float64", direction=function.OUT, description="" + ) + function.addParameter( + "h2_vec_y", dtype="float64", direction=function.OUT, description="" + ) + function.addParameter( + "h2_vec_z", dtype="float64", direction=function.OUT, description="" + ) + function.result_type = "float64" + return function + @legacy_function def compute_orbital_elements_from_orbital_vectors(): function = LegacyFunctionSpecification() - function.addParameter('m1', dtype='float64', direction=function.IN) - function.addParameter('m2', dtype='float64', direction=function.IN) - function.addParameter('m3', dtype='float64', direction=function.IN) - function.addParameter('e1_vec_x', dtype='float64',direction=function.IN,description = "") - function.addParameter('e1_vec_y', dtype='float64',direction=function.IN,description = "") - function.addParameter('e1_vec_z', dtype='float64',direction=function.IN,description = "") - function.addParameter('e2_vec_x', dtype='float64',direction=function.IN,description = "") - function.addParameter('e2_vec_y', dtype='float64',direction=function.IN,description = "") - function.addParameter('e2_vec_z', dtype='float64',direction=function.IN,description = "") - function.addParameter('h1_vec_x', dtype='float64',direction=function.IN,description = "") - function.addParameter('h1_vec_y', dtype='float64',direction=function.IN,description = "") - function.addParameter('h1_vec_z', dtype='float64',direction=function.IN,description = "") - function.addParameter('h2_vec_x', dtype='float64',direction=function.IN,description = "") - function.addParameter('h2_vec_y', dtype='float64',direction=function.IN,description = "") - function.addParameter('h2_vec_z', dtype='float64',direction=function.IN,description = "") - function.addParameter('a1', dtype='float64', direction=function.OUT) - function.addParameter('a2', dtype='float64', direction=function.OUT) - function.addParameter('e1', dtype='float64', direction=function.OUT) - function.addParameter('e2', dtype='float64', direction=function.OUT) - function.addParameter('INCL_rel', dtype='float64', direction=function.OUT) - function.addParameter('AP1', dtype='float64', direction=function.OUT) - function.addParameter('AP2', dtype='float64', direction=function.OUT) - function.addParameter('LAN1', dtype='float64', direction=function.OUT) - function.addParameter('LAN2', dtype='float64', direction=function.OUT) - function.result_type = 'float64' + function.addParameter("m1", dtype="float64", direction=function.IN) + function.addParameter("m2", dtype="float64", direction=function.IN) + function.addParameter("m3", dtype="float64", direction=function.IN) + function.addParameter( + "e1_vec_x", dtype="float64", direction=function.IN, description="" + ) + function.addParameter( + "e1_vec_y", dtype="float64", direction=function.IN, description="" + ) + function.addParameter( + "e1_vec_z", dtype="float64", direction=function.IN, description="" + ) + function.addParameter( + "e2_vec_x", dtype="float64", direction=function.IN, description="" + ) + function.addParameter( + "e2_vec_y", dtype="float64", direction=function.IN, description="" + ) + function.addParameter( + "e2_vec_z", dtype="float64", direction=function.IN, description="" + ) + function.addParameter( + "h1_vec_x", dtype="float64", direction=function.IN, description="" + ) + function.addParameter( + "h1_vec_y", dtype="float64", direction=function.IN, description="" + ) + function.addParameter( + "h1_vec_z", dtype="float64", direction=function.IN, description="" + ) + function.addParameter( + "h2_vec_x", dtype="float64", direction=function.IN, description="" + ) + function.addParameter( + "h2_vec_y", dtype="float64", direction=function.IN, description="" + ) + function.addParameter( + "h2_vec_z", dtype="float64", direction=function.IN, description="" + ) + function.addParameter("a1", dtype="float64", direction=function.OUT) + function.addParameter("a2", dtype="float64", direction=function.OUT) + function.addParameter("e1", dtype="float64", direction=function.OUT) + function.addParameter("e2", dtype="float64", direction=function.OUT) + function.addParameter("INCL_rel", dtype="float64", direction=function.OUT) + function.addParameter("AP1", dtype="float64", direction=function.OUT) + function.addParameter("AP2", dtype="float64", direction=function.OUT) + function.addParameter("LAN1", dtype="float64", direction=function.OUT) + function.addParameter("LAN2", dtype="float64", direction=function.OUT) + function.result_type = "float64" return function @legacy_function def compute_effect_of_SN_on_orbital_vectors(): function = LegacyFunctionSpecification() - function.addParameter('m1', dtype='float64', direction=function.IN) - function.addParameter('m2', dtype='float64', direction=function.IN) - function.addParameter('m3', dtype='float64', direction=function.IN) - function.addParameter('e1_vec_x', dtype='float64',direction=function.IN,description = "") - function.addParameter('e1_vec_y', dtype='float64',direction=function.IN,description = "") - function.addParameter('e1_vec_z', dtype='float64',direction=function.IN,description = "") - function.addParameter('e2_vec_x', dtype='float64',direction=function.IN,description = "") - function.addParameter('e2_vec_y', dtype='float64',direction=function.IN,description = "") - function.addParameter('e2_vec_z', dtype='float64',direction=function.IN,description = "") - function.addParameter('h1_vec_x', dtype='float64',direction=function.IN,description = "") - function.addParameter('h1_vec_y', dtype='float64',direction=function.IN,description = "") - function.addParameter('h1_vec_z', dtype='float64',direction=function.IN,description = "") - function.addParameter('h2_vec_x', dtype='float64',direction=function.IN,description = "") - function.addParameter('h2_vec_y', dtype='float64',direction=function.IN,description = "") - function.addParameter('h2_vec_z', dtype='float64',direction=function.IN,description = "") - function.addParameter('Vkick1_vec_x', dtype='float64',direction=function.IN,description = "") - function.addParameter('Vkick1_vec_y', dtype='float64',direction=function.IN,description = "") - function.addParameter('Vkick1_vec_z', dtype='float64',direction=function.IN,description = "") - function.addParameter('Vkick2_vec_x', dtype='float64',direction=function.IN,description = "") - function.addParameter('Vkick2_vec_y', dtype='float64',direction=function.IN,description = "") - function.addParameter('Vkick2_vec_z', dtype='float64',direction=function.IN,description = "") - function.addParameter('Vkick3_vec_x', dtype='float64',direction=function.IN,description = "") - function.addParameter('Vkick3_vec_y', dtype='float64',direction=function.IN,description = "") - function.addParameter('Vkick3_vec_z', dtype='float64',direction=function.IN,description = "") - function.addParameter('delta_m1', dtype='float64', direction=function.IN) - function.addParameter('delta_m2', dtype='float64', direction=function.IN) - function.addParameter('delta_m3', dtype='float64', direction=function.IN) - function.addParameter('f1', dtype='float64',direction=function.IN,description = "") - function.addParameter('f2', dtype='float64',direction=function.IN,description = "") - function.addParameter('V1_prime_x', dtype='float64',direction=function.OUT,description = "") - function.addParameter('V1_prime_y', dtype='float64',direction=function.OUT,description = "") - function.addParameter('V1_prime_z', dtype='float64',direction=function.OUT,description = "") - function.addParameter('V2_prime_x', dtype='float64',direction=function.OUT,description = "") - function.addParameter('V2_prime_y', dtype='float64',direction=function.OUT,description = "") - function.addParameter('V2_prime_z', dtype='float64',direction=function.OUT,description = "") - function.addParameter('V3_prime_x', dtype='float64',direction=function.OUT,description = "") - function.addParameter('V3_prime_y', dtype='float64',direction=function.OUT,description = "") - function.addParameter('V3_prime_z', dtype='float64',direction=function.OUT,description = "") - function.addParameter('e1_vec_x_p', dtype='float64',direction=function.OUT,description = "") - function.addParameter('e1_vec_y_p', dtype='float64',direction=function.OUT,description = "") - function.addParameter('e1_vec_z_p', dtype='float64',direction=function.OUT,description = "") - function.addParameter('e2_vec_x_p', dtype='float64',direction=function.OUT,description = "") - function.addParameter('e2_vec_y_p', dtype='float64',direction=function.OUT,description = "") - function.addParameter('e2_vec_z_p', dtype='float64',direction=function.OUT,description = "") - function.addParameter('h1_vec_x_p', dtype='float64',direction=function.OUT,description = "") - function.addParameter('h1_vec_y_p', dtype='float64',direction=function.OUT,description = "") - function.addParameter('h1_vec_z_p', dtype='float64',direction=function.OUT,description = "") - function.addParameter('h2_vec_x_p', dtype='float64',direction=function.OUT,description = "") - function.addParameter('h2_vec_y_p', dtype='float64',direction=function.OUT,description = "") - function.addParameter('h2_vec_z_p', dtype='float64',direction=function.OUT,description = "") - function.addParameter('cos_phi1', dtype='float64',direction=function.OUT,description = "") - function.addParameter('cos_phi2', dtype='float64',direction=function.OUT,description = "") - function.addParameter('R', dtype='float64',direction=function.OUT,description = "") - function.addParameter('v_sys', dtype='float64',direction=function.OUT,description = "") - function.addParameter('r1dotv1', dtype='float64',direction=function.OUT,description = "") - function.addParameter('r1dotvk', dtype='float64',direction=function.OUT,description = "") - function.addParameter('v1dotvk', dtype='float64',direction=function.OUT,description = "") - function.addParameter('r1dotvsys', dtype='float64',direction=function.OUT,description = "") - function.addParameter('v1dotvsys', dtype='float64',direction=function.OUT,description = "") - function.addParameter('r2dot2', dtype='float64',direction=function.OUT,description = "") - function.addParameter('r2dotvsys', dtype='float64',direction=function.OUT,description = "") - function.addParameter('v2dotvsys', dtype='float64',direction=function.OUT,description = "") - function.addParameter('r1dotr2', dtype='float64',direction=function.OUT,description = "") - function.addParameter('r1dotv2', dtype='float64',direction=function.OUT,description = "") - function.result_type = 'float64' - return function - + function.addParameter("m1", dtype="float64", direction=function.IN) + function.addParameter("m2", dtype="float64", direction=function.IN) + function.addParameter("m3", dtype="float64", direction=function.IN) + function.addParameter( + "e1_vec_x", dtype="float64", direction=function.IN, description="" + ) + function.addParameter( + "e1_vec_y", dtype="float64", direction=function.IN, description="" + ) + function.addParameter( + "e1_vec_z", dtype="float64", direction=function.IN, description="" + ) + function.addParameter( + "e2_vec_x", dtype="float64", direction=function.IN, description="" + ) + function.addParameter( + "e2_vec_y", dtype="float64", direction=function.IN, description="" + ) + function.addParameter( + "e2_vec_z", dtype="float64", direction=function.IN, description="" + ) + function.addParameter( + "h1_vec_x", dtype="float64", direction=function.IN, description="" + ) + function.addParameter( + "h1_vec_y", dtype="float64", direction=function.IN, description="" + ) + function.addParameter( + "h1_vec_z", dtype="float64", direction=function.IN, description="" + ) + function.addParameter( + "h2_vec_x", dtype="float64", direction=function.IN, description="" + ) + function.addParameter( + "h2_vec_y", dtype="float64", direction=function.IN, description="" + ) + function.addParameter( + "h2_vec_z", dtype="float64", direction=function.IN, description="" + ) + function.addParameter( + "Vkick1_vec_x", dtype="float64", direction=function.IN, description="" + ) + function.addParameter( + "Vkick1_vec_y", dtype="float64", direction=function.IN, description="" + ) + function.addParameter( + "Vkick1_vec_z", dtype="float64", direction=function.IN, description="" + ) + function.addParameter( + "Vkick2_vec_x", dtype="float64", direction=function.IN, description="" + ) + function.addParameter( + "Vkick2_vec_y", dtype="float64", direction=function.IN, description="" + ) + function.addParameter( + "Vkick2_vec_z", dtype="float64", direction=function.IN, description="" + ) + function.addParameter( + "Vkick3_vec_x", dtype="float64", direction=function.IN, description="" + ) + function.addParameter( + "Vkick3_vec_y", dtype="float64", direction=function.IN, description="" + ) + function.addParameter( + "Vkick3_vec_z", dtype="float64", direction=function.IN, description="" + ) + function.addParameter("delta_m1", dtype="float64", direction=function.IN) + function.addParameter("delta_m2", dtype="float64", direction=function.IN) + function.addParameter("delta_m3", dtype="float64", direction=function.IN) + function.addParameter( + "f1", dtype="float64", direction=function.IN, description="" + ) + function.addParameter( + "f2", dtype="float64", direction=function.IN, description="" + ) + function.addParameter( + "V1_prime_x", dtype="float64", direction=function.OUT, description="" + ) + function.addParameter( + "V1_prime_y", dtype="float64", direction=function.OUT, description="" + ) + function.addParameter( + "V1_prime_z", dtype="float64", direction=function.OUT, description="" + ) + function.addParameter( + "V2_prime_x", dtype="float64", direction=function.OUT, description="" + ) + function.addParameter( + "V2_prime_y", dtype="float64", direction=function.OUT, description="" + ) + function.addParameter( + "V2_prime_z", dtype="float64", direction=function.OUT, description="" + ) + function.addParameter( + "V3_prime_x", dtype="float64", direction=function.OUT, description="" + ) + function.addParameter( + "V3_prime_y", dtype="float64", direction=function.OUT, description="" + ) + function.addParameter( + "V3_prime_z", dtype="float64", direction=function.OUT, description="" + ) + function.addParameter( + "e1_vec_x_p", dtype="float64", direction=function.OUT, description="" + ) + function.addParameter( + "e1_vec_y_p", dtype="float64", direction=function.OUT, description="" + ) + function.addParameter( + "e1_vec_z_p", dtype="float64", direction=function.OUT, description="" + ) + function.addParameter( + "e2_vec_x_p", dtype="float64", direction=function.OUT, description="" + ) + function.addParameter( + "e2_vec_y_p", dtype="float64", direction=function.OUT, description="" + ) + function.addParameter( + "e2_vec_z_p", dtype="float64", direction=function.OUT, description="" + ) + function.addParameter( + "h1_vec_x_p", dtype="float64", direction=function.OUT, description="" + ) + function.addParameter( + "h1_vec_y_p", dtype="float64", direction=function.OUT, description="" + ) + function.addParameter( + "h1_vec_z_p", dtype="float64", direction=function.OUT, description="" + ) + function.addParameter( + "h2_vec_x_p", dtype="float64", direction=function.OUT, description="" + ) + function.addParameter( + "h2_vec_y_p", dtype="float64", direction=function.OUT, description="" + ) + function.addParameter( + "h2_vec_z_p", dtype="float64", direction=function.OUT, description="" + ) + function.addParameter( + "cos_phi1", dtype="float64", direction=function.OUT, description="" + ) + function.addParameter( + "cos_phi2", dtype="float64", direction=function.OUT, description="" + ) + function.addParameter( + "R", dtype="float64", direction=function.OUT, description="" + ) + function.addParameter( + "v_sys", dtype="float64", direction=function.OUT, description="" + ) + function.addParameter( + "r1dotv1", dtype="float64", direction=function.OUT, description="" + ) + function.addParameter( + "r1dotvk", dtype="float64", direction=function.OUT, description="" + ) + function.addParameter( + "v1dotvk", dtype="float64", direction=function.OUT, description="" + ) + function.addParameter( + "r1dotvsys", dtype="float64", direction=function.OUT, description="" + ) + function.addParameter( + "v1dotvsys", dtype="float64", direction=function.OUT, description="" + ) + function.addParameter( + "r2dot2", dtype="float64", direction=function.OUT, description="" + ) + function.addParameter( + "r2dotvsys", dtype="float64", direction=function.OUT, description="" + ) + function.addParameter( + "v2dotvsys", dtype="float64", direction=function.OUT, description="" + ) + function.addParameter( + "r1dotr2", dtype="float64", direction=function.OUT, description="" + ) + function.addParameter( + "r1dotv2", dtype="float64", direction=function.OUT, description="" + ) + function.result_type = "float64" + return function + @legacy_function def a_out_div_a_in_dynamical_stability(): function = LegacyFunctionSpecification() - function.addParameter('m1', dtype='float64', direction=function.IN) - function.addParameter('m2', dtype='float64', direction=function.IN) - function.addParameter('m3', dtype='float64', direction=function.IN) - function.addParameter('a_in', dtype='float64', direction=function.IN) - function.addParameter('a_out', dtype='float64', direction=function.IN) - function.addParameter('e_in', dtype='float64', direction=function.IN) - function.addParameter('e_out', dtype='float64', direction=function.IN) - function.addParameter('itot', dtype='float64', direction=function.IN) - function.addParameter('stability_limit_specification', dtype='int32', direction=function.IN) - function.result_type = 'float64' + function.addParameter("m1", dtype="float64", direction=function.IN) + function.addParameter("m2", dtype="float64", direction=function.IN) + function.addParameter("m3", dtype="float64", direction=function.IN) + function.addParameter("a_in", dtype="float64", direction=function.IN) + function.addParameter("a_out", dtype="float64", direction=function.IN) + function.addParameter("e_in", dtype="float64", direction=function.IN) + function.addParameter("e_out", dtype="float64", direction=function.IN) + function.addParameter("itot", dtype="float64", direction=function.IN) + function.addParameter( + "stability_limit_specification", dtype="int32", direction=function.IN + ) + function.result_type = "float64" return function @legacy_function def a_out_div_a_in_semisecular_regime(): function = LegacyFunctionSpecification() - function.addParameter('m1', dtype='float64', direction=function.IN) - function.addParameter('m2', dtype='float64', direction=function.IN) - function.addParameter('m3', dtype='float64', direction=function.IN) - function.addParameter('e_in', dtype='float64', direction=function.IN) - function.addParameter('e_out', dtype='float64', direction=function.IN) - function.addParameter('check_for_semisecular_regime_parameter', dtype='float64', direction=function.IN) - function.result_type = 'float64' + function.addParameter("m1", dtype="float64", direction=function.IN) + function.addParameter("m2", dtype="float64", direction=function.IN) + function.addParameter("m3", dtype="float64", direction=function.IN) + function.addParameter("e_in", dtype="float64", direction=function.IN) + function.addParameter("e_out", dtype="float64", direction=function.IN) + function.addParameter( + "check_for_semisecular_regime_parameter", + dtype="float64", + direction=function.IN, + ) + function.result_type = "float64" return function @legacy_function def roche_radius(): function = LegacyFunctionSpecification() - function.addParameter('rp', dtype='float64', direction=function.IN) - function.addParameter('q', dtype='float64', direction=function.IN) - function.addParameter('e', dtype='float64', direction=function.IN) - function.addParameter('f', dtype='float64', direction=function.IN) - function.addParameter('roche_radius_specification', dtype='int32', direction=function.IN) - function.result_type = 'float64' + function.addParameter("rp", dtype="float64", direction=function.IN) + function.addParameter("q", dtype="float64", direction=function.IN) + function.addParameter("e", dtype="float64", direction=function.IN) + function.addParameter("f", dtype="float64", direction=function.IN) + function.addParameter( + "roche_radius_specification", dtype="int32", direction=function.IN + ) + function.result_type = "float64" return function - @legacy_function def get_relative_tolerance(): function = LegacyFunctionSpecification() - function.addParameter('value', dtype='float64',direction=function.OUT,description = "Relative tolerance, default 1e-10") - function.result_type = 'int32' + function.addParameter( + "value", + dtype="float64", + direction=function.OUT, + description="Relative tolerance, default 1e-10", + ) + function.result_type = "int32" return function @legacy_function def set_relative_tolerance(): function = LegacyFunctionSpecification() - function.addParameter('value', dtype='float64',direction=function.IN,description = "Relative tolerance, default 1e-10") - function.result_type = 'int32' + function.addParameter( + "value", + dtype="float64", + direction=function.IN, + description="Relative tolerance, default 1e-10", + ) + function.result_type = "int32" return function @legacy_function def get_threshold_value_of_e_in_for_setting_tidal_e_in_dot_zero(): function = LegacyFunctionSpecification() - function.addParameter('value', dtype='float64',direction=function.OUT,description = "") - function.result_type = 'int32' + function.addParameter( + "value", dtype="float64", direction=function.OUT, description="" + ) + function.result_type = "int32" return function @legacy_function def set_threshold_value_of_e_in_for_setting_tidal_e_in_dot_zero(): function = LegacyFunctionSpecification() - function.addParameter('value', dtype='float64',direction=function.IN,description = "") - function.result_type = 'int32' + function.addParameter( + "value", dtype="float64", direction=function.IN, description="" + ) + function.result_type = "int32" return function @legacy_function def get_threshold_value_of_spin_angular_frequency_for_setting_spin_angular_frequency_dot_moment_of_inertia_plus_wind_changes_zero(): function = LegacyFunctionSpecification() - function.addParameter('value', dtype='float64',direction=function.OUT,description = "",unit=1.0/unit_t) - function.result_type = 'int32' + function.addParameter( + "value", + dtype="float64", + direction=function.OUT, + description="", + unit=1.0 / unit_t, + ) + function.result_type = "int32" return function @legacy_function def set_threshold_value_of_spin_angular_frequency_for_setting_spin_angular_frequency_dot_moment_of_inertia_plus_wind_changes_zero(): function = LegacyFunctionSpecification() - function.addParameter('value', dtype='float64',direction=function.IN,description = "",unit=1.0/unit_t) - function.result_type = 'int32' - return function - -# @legacy_function -# def get_dynamical_stability_model(): -# function = LegacyFunctionSpecification() -# function.addParameter('value', dtype='int32',direction=function.OUT,description = "") -# function.result_type = 'int32' -# return function -# -# @legacy_function -# def set_dynamical_stability_model(): -# function = LegacyFunctionSpecification() -# function.addParameter('value', dtype='int32',direction=function.IN,description = "") -# function.result_type = 'int32' -# return function - + function.addParameter( + "value", + dtype="float64", + direction=function.IN, + description="", + unit=1.0 / unit_t, + ) + function.result_type = "int32" + return function + + # @legacy_function + # def get_dynamical_stability_model(): + # function = LegacyFunctionSpecification() + # function.addParameter('value', dtype='int32',direction=function.OUT,description = "") + # function.result_type = 'int32' + # return function + # + # @legacy_function + # def set_dynamical_stability_model(): + # function = LegacyFunctionSpecification() + # function.addParameter('value', dtype='int32',direction=function.IN,description = "") + # function.result_type = 'int32' + # return function + @legacy_function def get_input_precision(): function = LegacyFunctionSpecification() - function.addParameter('value', dtype='float64',direction=function.OUT,description = "") - function.result_type = 'int32' + function.addParameter( + "value", dtype="float64", direction=function.OUT, description="" + ) + function.result_type = "int32" return function @legacy_function def set_input_precision(): function = LegacyFunctionSpecification() - function.addParameter('value', dtype='float64',direction=function.IN,description = "") - function.result_type = 'int32' + function.addParameter( + "value", dtype="float64", direction=function.IN, description="" + ) + function.result_type = "int32" return function @legacy_function def get_linear_solver(): function = LegacyFunctionSpecification() - function.addParameter('value', dtype='int32',direction=function.OUT,description = "linear solver") - function.result_type = 'int32' + function.addParameter( + "value", dtype="int32", direction=function.OUT, description="linear solver" + ) + function.result_type = "int32" return function @legacy_function def set_linear_solver(): function = LegacyFunctionSpecification() - function.addParameter('value', dtype='int32',direction=function.IN,description = "linear solver") - function.result_type = 'int32' + function.addParameter( + "value", dtype="int32", direction=function.IN, description="linear solver" + ) + function.result_type = "int32" return function - + @legacy_function def get_equations_of_motion_specification(): function = LegacyFunctionSpecification() - function.addParameter('value', dtype='int32',direction=function.OUT,description = "...") - function.result_type = 'int32' + function.addParameter( + "value", dtype="int32", direction=function.OUT, description="..." + ) + function.result_type = "int32" return function @legacy_function def set_equations_of_motion_specification(): function = LegacyFunctionSpecification() - function.addParameter('value', dtype='int32',direction=function.IN,description = "...") - function.result_type = 'int32' + function.addParameter( + "value", dtype="int32", direction=function.IN, description="..." + ) + function.result_type = "int32" return function @legacy_function def get_roche_radius_specification(): function = LegacyFunctionSpecification() - function.addParameter('value', dtype='int32',direction=function.OUT,description = "...") - function.result_type = 'int32' + function.addParameter( + "value", dtype="int32", direction=function.OUT, description="..." + ) + function.result_type = "int32" return function @legacy_function def set_roche_radius_specification(): function = LegacyFunctionSpecification() - function.addParameter('value', dtype='int32',direction=function.IN,description = "...") - function.result_type = 'int32' + function.addParameter( + "value", dtype="int32", direction=function.IN, description="..." + ) + function.result_type = "int32" return function @legacy_function def get_stability_limit_specification(): function = LegacyFunctionSpecification() - function.addParameter('value', dtype='int32',direction=function.OUT,description = "...") - function.result_type = 'int32' + function.addParameter( + "value", dtype="int32", direction=function.OUT, description="..." + ) + function.result_type = "int32" return function @legacy_function def set_stability_limit_specification(): function = LegacyFunctionSpecification() - function.addParameter('value', dtype='int32',direction=function.IN,description = "...") - function.result_type = 'int32' + function.addParameter( + "value", dtype="int32", direction=function.IN, description="..." + ) + function.result_type = "int32" return function - + @legacy_function def get_check_for_dynamical_stability(): function = LegacyFunctionSpecification() - function.addParameter('value', dtype='bool',direction=function.OUT,description = "...") - function.result_type = 'int32' + function.addParameter( + "value", dtype="bool", direction=function.OUT, description="..." + ) + function.result_type = "int32" return function @legacy_function def set_check_for_dynamical_stability(): function = LegacyFunctionSpecification() - function.addParameter('value', dtype='bool',direction=function.IN,description = "...") - function.result_type = 'int32' + function.addParameter( + "value", dtype="bool", direction=function.IN, description="..." + ) + function.result_type = "int32" return function - + @legacy_function def get_check_for_inner_collision(): function = LegacyFunctionSpecification() - function.addParameter('value', dtype='bool',direction=function.OUT,description = "...") - function.result_type = 'int32' + function.addParameter( + "value", dtype="bool", direction=function.OUT, description="..." + ) + function.result_type = "int32" return function @legacy_function def set_check_for_inner_collision(): function = LegacyFunctionSpecification() - function.addParameter('value', dtype='bool',direction=function.IN,description = "...") - function.result_type = 'int32' + function.addParameter( + "value", dtype="bool", direction=function.IN, description="..." + ) + function.result_type = "int32" return function @legacy_function def get_check_for_outer_collision(): function = LegacyFunctionSpecification() - function.addParameter('value', dtype='bool',direction=function.OUT,description = "...") - function.result_type = 'int32' + function.addParameter( + "value", dtype="bool", direction=function.OUT, description="..." + ) + function.result_type = "int32" return function @legacy_function def set_check_for_outer_collision(): function = LegacyFunctionSpecification() - function.addParameter('value', dtype='bool',direction=function.IN,description = "...") - function.result_type = 'int32' + function.addParameter( + "value", dtype="bool", direction=function.IN, description="..." + ) + function.result_type = "int32" return function @legacy_function def get_check_for_inner_RLOF(): function = LegacyFunctionSpecification() - function.addParameter('value', dtype='bool',direction=function.OUT,description = "...") - function.result_type = 'int32' + function.addParameter( + "value", dtype="bool", direction=function.OUT, description="..." + ) + function.result_type = "int32" return function @legacy_function def set_check_for_inner_RLOF(): function = LegacyFunctionSpecification() - function.addParameter('value', dtype='bool',direction=function.IN,description = "...") - function.result_type = 'int32' + function.addParameter( + "value", dtype="bool", direction=function.IN, description="..." + ) + function.result_type = "int32" return function @legacy_function def get_check_for_outer_RLOF(): function = LegacyFunctionSpecification() - function.addParameter('value', dtype='bool',direction=function.OUT,description = "...") - function.result_type = 'int32' + function.addParameter( + "value", dtype="bool", direction=function.OUT, description="..." + ) + function.result_type = "int32" return function @legacy_function def set_check_for_outer_RLOF(): function = LegacyFunctionSpecification() - function.addParameter('value', dtype='bool',direction=function.IN,description = "...") - function.result_type = 'int32' + function.addParameter( + "value", dtype="bool", direction=function.IN, description="..." + ) + function.result_type = "int32" return function - + @legacy_function def set_include_quadrupole_terms(): function = LegacyFunctionSpecification() - function.addParameter('value', dtype='bool',direction=function.IN,description = "Whether or not to include quadrupole terms in the secular equations of motion") - function.result_type = 'int32' - return function - + function.addParameter( + "value", + dtype="bool", + direction=function.IN, + description="Whether or not to include quadrupole terms in the secular equations of motion", + ) + function.result_type = "int32" + return function + @legacy_function def get_include_quadrupole_terms(): function = LegacyFunctionSpecification() - function.addParameter('value', dtype='bool',direction=function.OUT,description = "Whether or not to include quadrupole terms in the secular equations of motion") - function.result_type = 'int32' - return function + function.addParameter( + "value", + dtype="bool", + direction=function.OUT, + description="Whether or not to include quadrupole terms in the secular equations of motion", + ) + function.result_type = "int32" + return function @legacy_function def set_include_octupole_terms(): function = LegacyFunctionSpecification() - function.addParameter('value', dtype='bool',direction=function.IN,description = "Whether or not to include octupole terms in the secular equations of motion") - function.result_type = 'int32' - return function - + function.addParameter( + "value", + dtype="bool", + direction=function.IN, + description="Whether or not to include octupole terms in the secular equations of motion", + ) + function.result_type = "int32" + return function + @legacy_function def get_include_octupole_terms(): function = LegacyFunctionSpecification() - function.addParameter('value', dtype='bool',direction=function.OUT,description = "Whether or not to include octupole terms in the secular equations of motion") - function.result_type = 'int32' - return function + function.addParameter( + "value", + dtype="bool", + direction=function.OUT, + description="Whether or not to include octupole terms in the secular equations of motion", + ) + function.result_type = "int32" + return function @legacy_function def get_include_1PN_inner_terms(): function = LegacyFunctionSpecification() - function.addParameter('value', dtype='bool',direction=function.OUT,description = "Include 1PN inner binary terms in the equations of motion") - function.result_type = 'int32' + function.addParameter( + "value", + dtype="bool", + direction=function.OUT, + description="Include 1PN inner binary terms in the equations of motion", + ) + function.result_type = "int32" return function + @legacy_function def set_include_1PN_inner_terms(): function = LegacyFunctionSpecification() - function.addParameter('value', dtype='bool',direction=function.IN,description = "Include 1PN inner binary terms in the equations of motion") - function.result_type = 'int32' + function.addParameter( + "value", + dtype="bool", + direction=function.IN, + description="Include 1PN inner binary terms in the equations of motion", + ) + function.result_type = "int32" return function @legacy_function def get_include_1PN_outer_terms(): function = LegacyFunctionSpecification() - function.addParameter('value', dtype='bool',direction=function.OUT,description = "Include 1PN outer binary terms in the equations of motion") - function.result_type = 'int32' + function.addParameter( + "value", + dtype="bool", + direction=function.OUT, + description="Include 1PN outer binary terms in the equations of motion", + ) + function.result_type = "int32" return function + @legacy_function def set_include_1PN_outer_terms(): function = LegacyFunctionSpecification() - function.addParameter('value', dtype='bool',direction=function.IN,description = "Include 1PN outer binary terms in the equations of motion") - function.result_type = 'int32' + function.addParameter( + "value", + dtype="bool", + direction=function.IN, + description="Include 1PN outer binary terms in the equations of motion", + ) + function.result_type = "int32" return function @legacy_function def get_include_1PN_inner_outer_terms(): function = LegacyFunctionSpecification() - function.addParameter('value', dtype='bool',direction=function.OUT,description = "Include 1PN 'interaction terms' in the equations of motion") - function.result_type = 'int32' + function.addParameter( + "value", + dtype="bool", + direction=function.OUT, + description="Include 1PN 'interaction terms' in the equations of motion", + ) + function.result_type = "int32" return function + @legacy_function def set_include_1PN_inner_outer_terms(): function = LegacyFunctionSpecification() - function.addParameter('value', dtype='bool',direction=function.IN,description = "Include 1PN 'interaction terms' in the equations of motion") - function.result_type = 'int32' + function.addParameter( + "value", + dtype="bool", + direction=function.IN, + description="Include 1PN 'interaction terms' in the equations of motion", + ) + function.result_type = "int32" return function @legacy_function def get_include_25PN_inner_terms(): function = LegacyFunctionSpecification() - function.addParameter('value', dtype='bool',direction=function.OUT,description = "Include 2.5PN inner binary terms in the equations of motion") - function.result_type = 'int32' + function.addParameter( + "value", + dtype="bool", + direction=function.OUT, + description="Include 2.5PN inner binary terms in the equations of motion", + ) + function.result_type = "int32" return function + @legacy_function def set_include_25PN_inner_terms(): function = LegacyFunctionSpecification() - function.addParameter('value', dtype='bool',direction=function.IN,description = "Include 2.5PN inner binary terms in the equations of motion") - function.result_type = 'int32' + function.addParameter( + "value", + dtype="bool", + direction=function.IN, + description="Include 2.5PN inner binary terms in the equations of motion", + ) + function.result_type = "int32" return function @legacy_function def get_include_25PN_outer_terms(): function = LegacyFunctionSpecification() - function.addParameter('value', dtype='bool',direction=function.OUT,description = "Include 2.5PN outer binary terms in the equations of motion") - function.result_type = 'int32' + function.addParameter( + "value", + dtype="bool", + direction=function.OUT, + description="Include 2.5PN outer binary terms in the equations of motion", + ) + function.result_type = "int32" return function + @legacy_function def set_include_25PN_outer_terms(): function = LegacyFunctionSpecification() - function.addParameter('value', dtype='bool',direction=function.IN,description = "Include 2.5PN outer binary terms in the equations of motion") - function.result_type = 'int32' + function.addParameter( + "value", + dtype="bool", + direction=function.IN, + description="Include 2.5PN outer binary terms in the equations of motion", + ) + function.result_type = "int32" return function @legacy_function def set_include_inner_tidal_terms(): function = LegacyFunctionSpecification() - function.addParameter('value', dtype='bool',direction=function.IN,description = "Whether or not to include the effects of tides in the inner binary system") - function.result_type = 'int32' - return function - + function.addParameter( + "value", + dtype="bool", + direction=function.IN, + description="Whether or not to include the effects of tides in the inner binary system", + ) + function.result_type = "int32" + return function + @legacy_function def get_include_inner_tidal_terms(): function = LegacyFunctionSpecification() - function.addParameter('value', dtype='bool',direction=function.OUT,description = "Whether or not to include the effects of tides in the inner binary system") - function.result_type = 'int32' + function.addParameter( + "value", + dtype="bool", + direction=function.OUT, + description="Whether or not to include the effects of tides in the inner binary system", + ) + function.result_type = "int32" return function @legacy_function def set_include_outer_tidal_terms(): function = LegacyFunctionSpecification() - function.addParameter('value', dtype='bool',direction=function.IN,description = "Whether or not to include the effects of tides in the outer binary system") - function.result_type = 'int32' - return function - + function.addParameter( + "value", + dtype="bool", + direction=function.IN, + description="Whether or not to include the effects of tides in the outer binary system", + ) + function.result_type = "int32" + return function + @legacy_function def get_include_outer_tidal_terms(): function = LegacyFunctionSpecification() - function.addParameter('value', dtype='bool',direction=function.OUT,description = "Whether or not to include the effects of tides in the outer binary system") - function.result_type = 'int32' + function.addParameter( + "value", + dtype="bool", + direction=function.OUT, + description="Whether or not to include the effects of tides in the outer binary system", + ) + function.result_type = "int32" return function @legacy_function def set_ignore_tertiary(): function = LegacyFunctionSpecification() - function.addParameter('value', dtype='bool',direction=function.IN,description = "Whether or not to include the effects of tides in the outer binary system") - function.result_type = 'int32' - return function - + function.addParameter( + "value", + dtype="bool", + direction=function.IN, + description="Whether or not to include the effects of tides in the outer binary system", + ) + function.result_type = "int32" + return function + @legacy_function def get_ignore_tertiary(): function = LegacyFunctionSpecification() - function.addParameter('value', dtype='bool',direction=function.OUT,description = "Whether or not to include the effects of tides in the outer binary system") - function.result_type = 'int32' + function.addParameter( + "value", + dtype="bool", + direction=function.OUT, + description="Whether or not to include the effects of tides in the outer binary system", + ) + function.result_type = "int32" return function - + @legacy_function def set_include_inner_wind_terms(): function = LegacyFunctionSpecification() - function.addParameter('value', dtype='bool',direction=function.IN,description = "..") - function.result_type = 'int32' - return function - + function.addParameter( + "value", dtype="bool", direction=function.IN, description=".." + ) + function.result_type = "int32" + return function + @legacy_function def get_include_inner_wind_terms(): function = LegacyFunctionSpecification() - function.addParameter('value', dtype='bool',direction=function.OUT,description = "..") - function.result_type = 'int32' + function.addParameter( + "value", dtype="bool", direction=function.OUT, description=".." + ) + function.result_type = "int32" return function @legacy_function def set_include_outer_wind_terms(): function = LegacyFunctionSpecification() - function.addParameter('value', dtype='bool',direction=function.IN,description = "..") - function.result_type = 'int32' - return function - + function.addParameter( + "value", dtype="bool", direction=function.IN, description=".." + ) + function.result_type = "int32" + return function + @legacy_function def get_include_outer_wind_terms(): function = LegacyFunctionSpecification() - function.addParameter('value', dtype='bool',direction=function.OUT,description = "..") - function.result_type = 'int32' + function.addParameter( + "value", dtype="bool", direction=function.OUT, description=".." + ) + function.result_type = "int32" return function @legacy_function def set_include_magnetic_braking_terms(): function = LegacyFunctionSpecification() - function.addParameter('value', dtype='bool',direction=function.IN,description = "..") - function.result_type = 'int32' - return function - + function.addParameter( + "value", dtype="bool", direction=function.IN, description=".." + ) + function.result_type = "int32" + return function + @legacy_function def get_include_magnetic_braking_terms(): function = LegacyFunctionSpecification() - function.addParameter('value', dtype='bool',direction=function.OUT,description = "..") - function.result_type = 'int32' + function.addParameter( + "value", dtype="bool", direction=function.OUT, description=".." + ) + function.result_type = "int32" return function @legacy_function def set_include_spin_radius_mass_coupling_terms_star1(): function = LegacyFunctionSpecification() - function.addParameter('value', dtype='bool',direction=function.IN,description = "..") - function.result_type = 'int32' - return function - + function.addParameter( + "value", dtype="bool", direction=function.IN, description=".." + ) + function.result_type = "int32" + return function + @legacy_function def get_include_spin_radius_mass_coupling_terms_star1(): function = LegacyFunctionSpecification() - function.addParameter('value', dtype='bool',direction=function.OUT,description = "..") - function.result_type = 'int32' + function.addParameter( + "value", dtype="bool", direction=function.OUT, description=".." + ) + function.result_type = "int32" return function @legacy_function def set_include_spin_radius_mass_coupling_terms_star2(): function = LegacyFunctionSpecification() - function.addParameter('value', dtype='bool',direction=function.IN,description = "..") - function.result_type = 'int32' - return function - + function.addParameter( + "value", dtype="bool", direction=function.IN, description=".." + ) + function.result_type = "int32" + return function + @legacy_function def get_include_spin_radius_mass_coupling_terms_star2(): function = LegacyFunctionSpecification() - function.addParameter('value', dtype='bool',direction=function.OUT,description = "..") - function.result_type = 'int32' + function.addParameter( + "value", dtype="bool", direction=function.OUT, description=".." + ) + function.result_type = "int32" return function @legacy_function def set_include_spin_radius_mass_coupling_terms_star3(): function = LegacyFunctionSpecification() - function.addParameter('value', dtype='bool',direction=function.IN,description = "..") - function.result_type = 'int32' - return function - + function.addParameter( + "value", dtype="bool", direction=function.IN, description=".." + ) + function.result_type = "int32" + return function + @legacy_function def get_include_spin_radius_mass_coupling_terms_star3(): function = LegacyFunctionSpecification() - function.addParameter('value', dtype='bool',direction=function.OUT,description = "..") - function.result_type = 'int32' + function.addParameter( + "value", dtype="bool", direction=function.OUT, description=".." + ) + function.result_type = "int32" return function - + @legacy_function def set_include_inner_RLOF_terms(): function = LegacyFunctionSpecification() - function.addParameter('value', dtype='bool',direction=function.IN,description = "..") - function.result_type = 'int32' - return function - + function.addParameter( + "value", dtype="bool", direction=function.IN, description=".." + ) + function.result_type = "int32" + return function + @legacy_function def get_include_inner_RLOF_terms(): function = LegacyFunctionSpecification() - function.addParameter('value', dtype='bool',direction=function.OUT,description = "..") - function.result_type = 'int32' + function.addParameter( + "value", dtype="bool", direction=function.OUT, description=".." + ) + function.result_type = "int32" return function @legacy_function def set_include_outer_RLOF_terms(): function = LegacyFunctionSpecification() - function.addParameter('value', dtype='bool',direction=function.IN,description = "..") - function.result_type = 'int32' - return function - + function.addParameter( + "value", dtype="bool", direction=function.IN, description=".." + ) + function.result_type = "int32" + return function + @legacy_function def get_include_outer_RLOF_terms(): function = LegacyFunctionSpecification() - function.addParameter('value', dtype='bool',direction=function.OUT,description = "..") - function.result_type = 'int32' + function.addParameter( + "value", dtype="bool", direction=function.OUT, description=".." + ) + function.result_type = "int32" return function @legacy_function def set_include_linear_mass_change(): function = LegacyFunctionSpecification() - function.addParameter('value', dtype='bool',direction=function.IN,description = "..") - function.result_type = 'int32' - return function - + function.addParameter( + "value", dtype="bool", direction=function.IN, description=".." + ) + function.result_type = "int32" + return function + @legacy_function def get_include_linear_mass_change(): function = LegacyFunctionSpecification() - function.addParameter('value', dtype='bool',direction=function.OUT,description = "..") - function.result_type = 'int32' + function.addParameter( + "value", dtype="bool", direction=function.OUT, description=".." + ) + function.result_type = "int32" return function @legacy_function def set_include_linear_radius_change(): function = LegacyFunctionSpecification() - function.addParameter('value', dtype='bool',direction=function.IN,description = "..") - function.result_type = 'int32' - return function - + function.addParameter( + "value", dtype="bool", direction=function.IN, description=".." + ) + function.result_type = "int32" + return function + @legacy_function def get_include_linear_radius_change(): function = LegacyFunctionSpecification() - function.addParameter('value', dtype='bool',direction=function.OUT,description = "..") - function.result_type = 'int32' + function.addParameter( + "value", dtype="bool", direction=function.OUT, description=".." + ) + function.result_type = "int32" return function - + @legacy_function def set_check_for_dynamical_stability_at_initialisation(): function = LegacyFunctionSpecification() - function.addParameter('value', dtype='bool',direction=function.IN,description = "..") - function.result_type = 'int32' - return function + function.addParameter( + "value", dtype="bool", direction=function.IN, description=".." + ) + function.result_type = "int32" + return function @legacy_function def get_check_for_dynamical_stability_at_initialisation(): function = LegacyFunctionSpecification() - function.addParameter('value', dtype='bool',direction=function.OUT,description = "..") - function.result_type = 'int32' + function.addParameter( + "value", dtype="bool", direction=function.OUT, description=".." + ) + function.result_type = "int32" return function @legacy_function def set_check_for_semisecular_regime_at_initialisation(): function = LegacyFunctionSpecification() - function.addParameter('value', dtype='bool',direction=function.IN,description = "..") - function.result_type = 'int32' - return function + function.addParameter( + "value", dtype="bool", direction=function.IN, description=".." + ) + function.result_type = "int32" + return function @legacy_function def get_check_for_semisecular_regime_at_initialisation(): function = LegacyFunctionSpecification() - function.addParameter('value', dtype='bool',direction=function.OUT,description = "..") - function.result_type = 'int32' + function.addParameter( + "value", dtype="bool", direction=function.OUT, description=".." + ) + function.result_type = "int32" return function @legacy_function def set_verbose(): function = LegacyFunctionSpecification() - function.addParameter('value', dtype='bool',direction=function.IN,description = "..") - function.result_type = 'int32' - return function + function.addParameter( + "value", dtype="bool", direction=function.IN, description=".." + ) + function.result_type = "int32" + return function @legacy_function def get_verbose(): function = LegacyFunctionSpecification() - function.addParameter('value', dtype='bool',direction=function.OUT,description = "..") - function.result_type = 'int32' + function.addParameter( + "value", dtype="bool", direction=function.OUT, description=".." + ) + function.result_type = "int32" return function - - - ### addition Jan 2017 ### @legacy_function def get_check_for_semisecular_regime(): function = LegacyFunctionSpecification() - function.addParameter('value', dtype='bool',direction=function.OUT,description = "") - function.result_type = 'int32' + function.addParameter( + "value", dtype="bool", direction=function.OUT, description="" + ) + function.result_type = "int32" return function @legacy_function def set_check_for_semisecular_regime(): function = LegacyFunctionSpecification() - function.addParameter('value', dtype='bool',direction=function.IN,description = "") - function.result_type = 'int32' + function.addParameter( + "value", dtype="bool", direction=function.IN, description="" + ) + function.result_type = "int32" return function @legacy_function def get_check_for_semisecular_regime_parameter(): function = LegacyFunctionSpecification() - function.addParameter('value', dtype='float64',direction=function.OUT,description = "") - function.result_type = 'int32' + function.addParameter( + "value", dtype="float64", direction=function.OUT, description="" + ) + function.result_type = "int32" return function @legacy_function def set_check_for_semisecular_regime_parameter(): function = LegacyFunctionSpecification() - function.addParameter('value', dtype='float64',direction=function.IN,description = "") - function.result_type = 'int32' + function.addParameter( + "value", dtype="float64", direction=function.IN, description="" + ) + function.result_type = "int32" return function - - class SecularTriple(InCodeComponentImplementation): def __init__(self, **options): - InCodeComponentImplementation.__init__(self, SecularTripleInterface(**options), **options) + InCodeComponentImplementation.__init__( + self, SecularTripleInterface(**options), **options + ) self.model_time = 0.0 | units.Myr - self.evolve_further_after_root_was_found = False ### in some cases, it is desirable to integrate until the given end time, despite the finding of a root - self.take_into_account_RLOF_after_no_longer_filling_Roche_lobe = True ### this may seem like a strange `feature', but exists for consistency with the stellar/binary evolution code + self.evolve_further_after_root_was_found = False ### in some cases, it is desirable to integrate until the given end time, despite the finding of a root + self.take_into_account_RLOF_after_no_longer_filling_Roche_lobe = True ### this may seem like a strange `feature', but exists for consistency with the stellar/binary evolution code def define_parameters(self, object): - + object.add_method_parameter( "get_model_time", "set_model_time", "model_time", "model_time", - default_value = 0.0 | units.Myr + default_value=0.0 | units.Myr, ) object.add_method_parameter( "get_relative_tolerance", "set_relative_tolerance", "relative_tolerance", "Relative tolerance, default 1e-10", - default_value = 1.0e-10 + default_value=1.0e-10, ) object.add_method_parameter( "get_threshold_value_of_e_in_for_setting_tidal_e_in_dot_zero", "set_threshold_value_of_e_in_for_setting_tidal_e_in_dot_zero", "threshold_value_of_e_in_for_setting_tidal_e_in_dot_zero", "", - default_value = 1.0e-12 + default_value=1.0e-12, ) object.add_method_parameter( "get_threshold_value_of_spin_angular_frequency_for_setting_spin_angular_frequency_dot_moment_of_inertia_plus_wind_changes_zero", "set_threshold_value_of_spin_angular_frequency_for_setting_spin_angular_frequency_dot_moment_of_inertia_plus_wind_changes_zero", "threshold_value_of_spin_angular_frequency_for_setting_spin_angular_frequency_dot_moment_of_inertia_plus_wind_changes_zero", "", - default_value = 1.0e-8 - ) -# object.add_method_parameter( -# "get_dynamical_stability_model", -# "set_dynamical_stability_model", -# "dynamical_stability_model", -# "", -# default_value = 0 -# ) + default_value=1.0e-8, + ) + # object.add_method_parameter( + # "get_dynamical_stability_model", + # "set_dynamical_stability_model", + # "dynamical_stability_model", + # "", + # default_value = 0 + # ) object.add_method_parameter( "get_input_precision", "set_input_precision", "input_precision", "Input_precision, default 1e-5", - default_value = 1.0e-5 - ) + default_value=1.0e-5, + ) object.add_method_parameter( "get_linear_solver", "set_linear_solver", "linear_solver", "linear_solver, default 0", - default_value = 0 - ) + default_value=0, + ) object.add_method_parameter( "get_equations_of_motion_specification", "set_equations_of_motion_specification", "equations_of_motion_specification", "equations_of_motion_specification", - default_value = 0 + default_value=0, ) object.add_method_parameter( "get_roche_radius_specification", "set_roche_radius_specification", "roche_radius_specification", "roche_radius_specification", - default_value = 0 + default_value=0, ) object.add_method_parameter( "get_stability_limit_specification", "set_stability_limit_specification", "stability_limit_specification", "stability_limit_specification", - default_value = 0 + default_value=0, ) object.add_method_parameter( "get_check_for_dynamical_stability", "set_check_for_dynamical_stability", "check_for_dynamical_stability", "check_for_dynamical_stability", - default_value = True - ) + default_value=True, + ) object.add_method_parameter( "get_check_for_inner_collision", "set_check_for_inner_collision", "check_for_inner_collision", "check_for_inner_collision", - default_value = True - ) + default_value=True, + ) object.add_method_parameter( "get_check_for_outer_collision", "set_check_for_outer_collision", "check_for_outer_collision", "check_for_outer_collision", - default_value = False - ) + default_value=False, + ) object.add_method_parameter( "get_check_for_inner_RLOF", "set_check_for_inner_RLOF", "check_for_inner_RLOF", "check_for_inner_RLOF", - default_value = False + default_value=False, ) object.add_method_parameter( "get_check_for_outer_RLOF", "set_check_for_outer_RLOF", "check_for_outer_RLOF", "check_for_outer_RLOF", - default_value = False - ) + default_value=False, + ) object.add_method_parameter( "get_include_quadrupole_terms", "set_include_quadrupole_terms", "include_quadrupole_terms", - "Whether or not to include quadrupole terms in the secular equations of motion", - default_value = True - ) + "Whether or not to include quadrupole terms in the secular equations of motion", + default_value=True, + ) object.add_method_parameter( "get_include_octupole_terms", "set_include_octupole_terms", "include_octupole_terms", - "Whether or not to include octupole terms in the secular equations of motion", - default_value = True + "Whether or not to include octupole terms in the secular equations of motion", + default_value=True, ) object.add_method_parameter( "get_include_1PN_inner_terms", "set_include_1PN_inner_terms", "include_1PN_inner_terms", - "Include 1PN inner binary terms in the equations of motion", - default_value = False + "Include 1PN inner binary terms in the equations of motion", + default_value=False, ) object.add_method_parameter( "get_include_1PN_outer_terms", "set_include_1PN_outer_terms", "include_1PN_outer_terms", - "Include 1PN outer binary terms in the equations of motion", - default_value = False - ) + "Include 1PN outer binary terms in the equations of motion", + default_value=False, + ) object.add_method_parameter( "get_include_1PN_inner_outer_terms", "set_include_1PN_inner_outer_terms", "include_1PN_inner_outer_terms", - "Include 1PN interaction terms in the equations of motion", - default_value = False - ) + "Include 1PN interaction terms in the equations of motion", + default_value=False, + ) object.add_method_parameter( "get_include_25PN_inner_terms", "set_include_25PN_inner_terms", "include_25PN_inner_terms", - "Include 25PN inner binary terms in the equations of motion", - default_value = False + "Include 25PN inner binary terms in the equations of motion", + default_value=False, ) object.add_method_parameter( "get_include_25PN_outer_terms", "set_include_25PN_outer_terms", "include_25PN_outer_terms", - "Include 25PN outer binary terms in the equations of motion", - default_value = False + "Include 25PN outer binary terms in the equations of motion", + default_value=False, ) object.add_method_parameter( "get_ignore_tertiary", "set_ignore_tertiary", "ignore_tertiary", - "", - default_value = False - ) + "", + default_value=False, + ) object.add_method_parameter( "get_include_inner_tidal_terms", "set_include_inner_tidal_terms", "include_inner_tidal_terms", - "Whether or not to include the effects of tides in the inner binary system", - default_value = False - ) + "Whether or not to include the effects of tides in the inner binary system", + default_value=False, + ) object.add_method_parameter( "get_include_outer_tidal_terms", "set_include_outer_tidal_terms", "include_outer_tidal_terms", - "Whether or not to include the effects of tides in the outer binary system", - default_value = False + "Whether or not to include the effects of tides in the outer binary system", + default_value=False, ) object.add_method_parameter( "get_include_inner_wind_terms", "set_include_inner_wind_terms", "include_inner_wind_terms", - "..", - default_value = False + "..", + default_value=False, ) object.add_method_parameter( "get_include_outer_wind_terms", "set_include_outer_wind_terms", "include_outer_wind_terms", - "..", - default_value = False + "..", + default_value=False, ) object.add_method_parameter( "get_include_magnetic_braking_terms", "set_include_magnetic_braking_terms", "include_magnetic_braking_terms", - "..", - default_value = False - ) + "..", + default_value=False, + ) object.add_method_parameter( "get_include_spin_radius_mass_coupling_terms_star1", "set_include_spin_radius_mass_coupling_terms_star1", "include_spin_radius_mass_coupling_terms_star1", - "..", - default_value = False + "..", + default_value=False, ) object.add_method_parameter( "get_include_spin_radius_mass_coupling_terms_star2", "set_include_spin_radius_mass_coupling_terms_star2", "include_spin_radius_mass_coupling_terms_star2", - "..", - default_value = False - ) + "..", + default_value=False, + ) object.add_method_parameter( "get_include_spin_radius_mass_coupling_terms_star3", "set_include_spin_radius_mass_coupling_terms_star3", "include_spin_radius_mass_coupling_terms_star3", - "..", - default_value = False - ) + "..", + default_value=False, + ) object.add_method_parameter( "get_include_inner_RLOF_terms", "set_include_inner_RLOF_terms", "include_inner_RLOF_terms", - "..", - default_value = False + "..", + default_value=False, ) object.add_method_parameter( "get_include_outer_RLOF_terms", "set_include_outer_RLOF_terms", "include_outer_RLOF_terms", - "..", - default_value = False - ) + "..", + default_value=False, + ) object.add_method_parameter( "get_include_linear_mass_change", "set_include_linear_mass_change", "include_linear_mass_change", - "..", - default_value = False - ) + "..", + default_value=False, + ) object.add_method_parameter( "get_include_linear_radius_change", "set_include_linear_radius_change", "include_linear_radius_change", - "..", - default_value = False - ) + "..", + default_value=False, + ) object.add_method_parameter( "get_check_for_dynamical_stability_at_initialisation", "set_check_for_dynamical_stability_at_initialisation", "check_for_dynamical_stability_at_initialisation", - "..", - default_value = True - ) + "..", + default_value=True, + ) object.add_method_parameter( "get_check_for_semisecular_regime_at_initialisation", "set_check_for_semisecular_regime_at_initialisation", "check_for_semisecular_regime_at_initialisation", - "..", - default_value = True - ) + "..", + default_value=True, + ) object.add_method_parameter( - "get_verbose", - "set_verbose", - "verbose", - "..", - default_value = True - ) - - - + "get_verbose", "set_verbose", "verbose", "..", default_value=True + ) + ### addition Jan 2017 ### object.add_method_parameter( "get_check_for_semisecular_regime_parameter", "set_check_for_semisecular_regime_parameter", "check_for_semisecular_regime_parameter", - "..", - default_value = 1 - ) + "..", + default_value=1, + ) object.add_method_parameter( "get_check_for_semisecular_regime", "set_check_for_semisecular_regime", "check_for_semisecular_regime", - "..", - default_value = False - ) + "..", + default_value=False, + ) + def define_methods(self, object): - unit_lum = unit_m*unit_l**2/(unit_t**3) + unit_lum = unit_m * unit_l**2 / (unit_t**3) object.add_method( "evolve", ( - units.stellar_type, ### stellar_type1 - units.stellar_type, ### stellar_type2 - units.stellar_type, ### stellar_type3 - unit_m, ### m1 - unit_m, ### m2 - unit_m, ### m3 - unit_m, ### m1_convective_envelope - unit_m, ### m2_convective_envelope - unit_m, ### m3_convective_envelope - unit_l, ### R1 - unit_l, ### R2 - unit_l, ### R3 - unit_l, ### R1_convective_envelope - unit_l, ### R2_convective_envelope - unit_l, ### R3_convective_envelope - unit_lum, ### luminosity_star1 - unit_lum, ### luminosity_star2 - unit_lum, ### luminosity_star3 - 1.0/unit_t, ### spin_angular_frequency1 - 1.0/unit_t, ### spin_angular_frequency2 - 1.0/unit_t, ### spin_angular_frequency3 - object.NO_UNIT, ### AMC_star1 - object.NO_UNIT, ### AMC_star2 - object.NO_UNIT, ### AMC_star3 - object.NO_UNIT, ### gyration_radius_star1 - object.NO_UNIT, ### gyration_radius_star2 - object.NO_UNIT, ### gyration_radius_star3 - unit_m*unit_l**2, ### moment_of_inertia_star1 - unit_m*unit_l**2, ### moment_of_inertia_star2 - unit_m*unit_l**2, ### moment_of_inertia_star3 - unit_m*unit_l**2/unit_t, ### moment_of_inertia_dot_star1 - unit_m*unit_l**2/unit_t, ### moment_of_inertia_dot_star2 - unit_m*unit_l**2/unit_t, ### moment_of_inertia_dot_star3 -# 1.0/units.s, ### k_div_T_tides_star1 -# 1.0/units.s, ### k_div_T_tides_star2 -# 1.0/units.s, ### k_div_T_tides_star3 - unit_l, ### a_in - unit_l, ### a_out - object.NO_UNIT, ### e_in - object.NO_UNIT, ### e_out - object.NO_UNIT, ### INCL_in - object.NO_UNIT, ### INCL_out - object.NO_UNIT, ### AP_in - object.NO_UNIT, ### AP_out - object.NO_UNIT, ### LAN_in - object.NO_UNIT, ### LAN_out - object.NO_UNIT, ### star1_is_donor - object.NO_UNIT, ### star2_is_donor - object.NO_UNIT, ### star3_is_donor - unit_m/unit_t, ### wind_mass_loss_rate_star1 - unit_m/unit_t, ### wind_mass_loss_rate_star2 - unit_m/unit_t, ### wind_mass_loss_rate_star3 - unit_l/unit_t, ### time_derivative_of_radius_star1 - unit_l/unit_t, ### time_derivative_of_radius_star2 - unit_l/unit_t, ### time_derivative_of_radius_star3 - unit_m/unit_t, ### inner_mass_transfer_rate - unit_m/unit_t, ### outer_mass_transfer_rate - object.NO_UNIT, ### inner_accretion_efficiency_wind_child1_to_child2 - object.NO_UNIT, ### inner_accretion_efficiency_wind_child2_to_child1 - object.NO_UNIT, ### outer_accretion_efficiency_wind_child1_to_child2 - object.NO_UNIT, ### outer_accretion_efficiency_wind_child2_to_child1 - object.NO_UNIT, ### inner_accretion_efficiency_mass_transfer - object.NO_UNIT, ### outer_accretion_efficiency_mass_transfer - object.NO_UNIT, ### inner_specific_AM_loss_mass_transfer - object.NO_UNIT, ### outer_specific_AM_loss_mass_transfer - object.NO_UNIT, ### inner_spin_angular_momentum_wind_accretion_efficiency_child1_to_child2 - object.NO_UNIT, ### inner_spin_angular_momentum_wind_accretion_efficiency_child2_to_child1 - unit_t, ### t - unit_t, ### dt + units.stellar_type, ### stellar_type1 + units.stellar_type, ### stellar_type2 + units.stellar_type, ### stellar_type3 + unit_m, ### m1 + unit_m, ### m2 + unit_m, ### m3 + unit_m, ### m1_convective_envelope + unit_m, ### m2_convective_envelope + unit_m, ### m3_convective_envelope + unit_l, ### R1 + unit_l, ### R2 + unit_l, ### R3 + unit_l, ### R1_convective_envelope + unit_l, ### R2_convective_envelope + unit_l, ### R3_convective_envelope + unit_lum, ### luminosity_star1 + unit_lum, ### luminosity_star2 + unit_lum, ### luminosity_star3 + 1.0 / unit_t, ### spin_angular_frequency1 + 1.0 / unit_t, ### spin_angular_frequency2 + 1.0 / unit_t, ### spin_angular_frequency3 + object.NO_UNIT, ### AMC_star1 + object.NO_UNIT, ### AMC_star2 + object.NO_UNIT, ### AMC_star3 + object.NO_UNIT, ### gyration_radius_star1 + object.NO_UNIT, ### gyration_radius_star2 + object.NO_UNIT, ### gyration_radius_star3 + unit_m * unit_l**2, ### moment_of_inertia_star1 + unit_m * unit_l**2, ### moment_of_inertia_star2 + unit_m * unit_l**2, ### moment_of_inertia_star3 + unit_m * unit_l**2 / unit_t, ### moment_of_inertia_dot_star1 + unit_m * unit_l**2 / unit_t, ### moment_of_inertia_dot_star2 + unit_m * unit_l**2 / unit_t, ### moment_of_inertia_dot_star3 + # 1.0/units.s, ### k_div_T_tides_star1 + # 1.0/units.s, ### k_div_T_tides_star2 + # 1.0/units.s, ### k_div_T_tides_star3 + unit_l, ### a_in + unit_l, ### a_out + object.NO_UNIT, ### e_in + object.NO_UNIT, ### e_out + object.NO_UNIT, ### INCL_in + object.NO_UNIT, ### INCL_out + object.NO_UNIT, ### AP_in + object.NO_UNIT, ### AP_out + object.NO_UNIT, ### LAN_in + object.NO_UNIT, ### LAN_out + object.NO_UNIT, ### star1_is_donor + object.NO_UNIT, ### star2_is_donor + object.NO_UNIT, ### star3_is_donor + unit_m / unit_t, ### wind_mass_loss_rate_star1 + unit_m / unit_t, ### wind_mass_loss_rate_star2 + unit_m / unit_t, ### wind_mass_loss_rate_star3 + unit_l / unit_t, ### time_derivative_of_radius_star1 + unit_l / unit_t, ### time_derivative_of_radius_star2 + unit_l / unit_t, ### time_derivative_of_radius_star3 + unit_m / unit_t, ### inner_mass_transfer_rate + unit_m / unit_t, ### outer_mass_transfer_rate + object.NO_UNIT, ### inner_accretion_efficiency_wind_child1_to_child2 + object.NO_UNIT, ### inner_accretion_efficiency_wind_child2_to_child1 + object.NO_UNIT, ### outer_accretion_efficiency_wind_child1_to_child2 + object.NO_UNIT, ### outer_accretion_efficiency_wind_child2_to_child1 + object.NO_UNIT, ### inner_accretion_efficiency_mass_transfer + object.NO_UNIT, ### outer_accretion_efficiency_mass_transfer + object.NO_UNIT, ### inner_specific_AM_loss_mass_transfer + object.NO_UNIT, ### outer_specific_AM_loss_mass_transfer + object.NO_UNIT, ### inner_spin_angular_momentum_wind_accretion_efficiency_child1_to_child2 + object.NO_UNIT, ### inner_spin_angular_momentum_wind_accretion_efficiency_child2_to_child1 + unit_t, ### t + unit_t, ### dt ), ( - unit_m, ### m1_output - unit_m, ### m2_output - unit_m, ### m3_output - unit_l, ### R1_output - unit_l, ### R2_output - unit_l, ### R3_output - 1.0/unit_t, ### spin_angular_frequency1_output - 1.0/unit_t, ### spin_angular_frequency2_output - 1.0/unit_t, ### spin_angular_frequency3_output - unit_l, ### a_in_output - unit_l, ### a_out_output - object.NO_UNIT, ### e_in_output - object.NO_UNIT, ### e_out_output - object.NO_UNIT, ### delta_e_in_output - object.NO_UNIT, ### INCL_in_output - object.NO_UNIT, ### INCL_out_output - object.NO_UNIT, ### INCL_in_out_output - object.NO_UNIT, ### AP_in_output - object.NO_UNIT, ### AP_out_output - object.NO_UNIT, ### LAN_in_output - object.NO_UNIT, ### LAN_out_output - unit_t, ### t_output - object.NO_UNIT, ### CVODE_flag - object.NO_UNIT, ### root_finding_flag + unit_m, ### m1_output + unit_m, ### m2_output + unit_m, ### m3_output + unit_l, ### R1_output + unit_l, ### R2_output + unit_l, ### R3_output + 1.0 / unit_t, ### spin_angular_frequency1_output + 1.0 / unit_t, ### spin_angular_frequency2_output + 1.0 / unit_t, ### spin_angular_frequency3_output + unit_l, ### a_in_output + unit_l, ### a_out_output + object.NO_UNIT, ### e_in_output + object.NO_UNIT, ### e_out_output + object.NO_UNIT, ### delta_e_in_output + object.NO_UNIT, ### INCL_in_output + object.NO_UNIT, ### INCL_out_output + object.NO_UNIT, ### INCL_in_out_output + object.NO_UNIT, ### AP_in_output + object.NO_UNIT, ### AP_out_output + object.NO_UNIT, ### LAN_in_output + object.NO_UNIT, ### LAN_out_output + unit_t, ### t_output + object.NO_UNIT, ### CVODE_flag + object.NO_UNIT, ### root_finding_flag object.ERROR_CODE, - ) + ), ) object.add_method( "compute_orbital_vectors_from_orbital_elements", ( - unit_m, ### m1 - unit_m, ### m2 - unit_m, ### m3 - unit_l, ### a1 - unit_l, ### a2 - object.NO_UNIT, ### e1 - object.NO_UNIT, ### e2 - object.NO_UNIT, ### INCL_rel - object.NO_UNIT, ### AP1 - object.NO_UNIT, ### AP2 - object.NO_UNIT, ### LAN1 - object.NO_UNIT, ### LAN2 + unit_m, ### m1 + unit_m, ### m2 + unit_m, ### m3 + unit_l, ### a1 + unit_l, ### a2 + object.NO_UNIT, ### e1 + object.NO_UNIT, ### e2 + object.NO_UNIT, ### INCL_rel + object.NO_UNIT, ### AP1 + object.NO_UNIT, ### AP2 + object.NO_UNIT, ### LAN1 + object.NO_UNIT, ### LAN2 ), ( - object.NO_UNIT, ### e1_vec_x - object.NO_UNIT, ### e1_vec_y - object.NO_UNIT, ### e1_vec_z - object.NO_UNIT, ### e2_vec_x - object.NO_UNIT, ### e2_vec_y - object.NO_UNIT, ### e2_vec_z - unit_h, ### h1_vec_x - unit_h, ### h1_vec_y - unit_h, ### h1_vec_z - unit_h, ### h2_vec_x - unit_h, ### h2_vec_y - unit_h, ### h2_vec_z + object.NO_UNIT, ### e1_vec_x + object.NO_UNIT, ### e1_vec_y + object.NO_UNIT, ### e1_vec_z + object.NO_UNIT, ### e2_vec_x + object.NO_UNIT, ### e2_vec_y + object.NO_UNIT, ### e2_vec_z + unit_h, ### h1_vec_x + unit_h, ### h1_vec_y + unit_h, ### h1_vec_z + unit_h, ### h2_vec_x + unit_h, ### h2_vec_y + unit_h, ### h2_vec_z object.ERROR_CODE, - ) + ), ) object.add_method( "compute_orbital_elements_from_orbital_vectors", ( - unit_m, ### m1 - unit_m, ### m2 - unit_m, ### m3 - object.NO_UNIT, ### e1_vec_x - object.NO_UNIT, ### e1_vec_y - object.NO_UNIT, ### e1_vec_z - object.NO_UNIT, ### e2_vec_x - object.NO_UNIT, ### e2_vec_y - object.NO_UNIT, ### e2_vec_z - unit_h, ### h1_vec_x - unit_h, ### h1_vec_y - unit_h, ### h1_vec_z - unit_h, ### h2_vec_x - unit_h, ### h2_vec_y - unit_h, ### h2_vec_z + unit_m, ### m1 + unit_m, ### m2 + unit_m, ### m3 + object.NO_UNIT, ### e1_vec_x + object.NO_UNIT, ### e1_vec_y + object.NO_UNIT, ### e1_vec_z + object.NO_UNIT, ### e2_vec_x + object.NO_UNIT, ### e2_vec_y + object.NO_UNIT, ### e2_vec_z + unit_h, ### h1_vec_x + unit_h, ### h1_vec_y + unit_h, ### h1_vec_z + unit_h, ### h2_vec_x + unit_h, ### h2_vec_y + unit_h, ### h2_vec_z ), ( - unit_l, ### a1 - unit_l, ### a2 - object.NO_UNIT, ### e1 - object.NO_UNIT, ### e2 - object.NO_UNIT, ### INCL_rel - object.NO_UNIT, ### AP1 - object.NO_UNIT, ### AP2 - object.NO_UNIT, ### LAN1 - object.NO_UNIT, ### LAN2 + unit_l, ### a1 + unit_l, ### a2 + object.NO_UNIT, ### e1 + object.NO_UNIT, ### e2 + object.NO_UNIT, ### INCL_rel + object.NO_UNIT, ### AP1 + object.NO_UNIT, ### AP2 + object.NO_UNIT, ### LAN1 + object.NO_UNIT, ### LAN2 object.ERROR_CODE, - ) + ), ) object.add_method( "compute_effect_of_SN_on_orbital_vectors", ( - unit_m, ### m1 - unit_m, ### m2 - unit_m, ### m3 - object.NO_UNIT, ### e1_vec_x - object.NO_UNIT, ### e1_vec_y - object.NO_UNIT, ### e1_vec_z - object.NO_UNIT, ### e2_vec_x - object.NO_UNIT, ### e2_vec_y - object.NO_UNIT, ### e2_vec_z - unit_h, ### h1_vec_x - unit_h, ### h1_vec_y - unit_h, ### h1_vec_z - unit_h, ### h2_vec_x - unit_h, ### h2_vec_y - unit_h, ### h2_vec_z - unit_l/unit_t, ### Vkick1_vec_x - unit_l/unit_t, ### Vkick1_vec_y - unit_l/unit_t, ### Vkick1_vec_z - unit_l/unit_t, ### Vkick2_vec_x - unit_l/unit_t, ### Vkick2_vec_y - unit_l/unit_t, ### Vkick2_vec_z - unit_l/unit_t, ### Vkick3_vec_x - unit_l/unit_t, ### Vkick3_vec_y - unit_l/unit_t, ### Vkick3_vec_z - unit_m, ### delta_m1 - unit_m, ### delta_m2 - unit_m, ### delta_m3 - object.NO_UNIT, ### f1 - object.NO_UNIT, ### f2 + unit_m, ### m1 + unit_m, ### m2 + unit_m, ### m3 + object.NO_UNIT, ### e1_vec_x + object.NO_UNIT, ### e1_vec_y + object.NO_UNIT, ### e1_vec_z + object.NO_UNIT, ### e2_vec_x + object.NO_UNIT, ### e2_vec_y + object.NO_UNIT, ### e2_vec_z + unit_h, ### h1_vec_x + unit_h, ### h1_vec_y + unit_h, ### h1_vec_z + unit_h, ### h2_vec_x + unit_h, ### h2_vec_y + unit_h, ### h2_vec_z + unit_l / unit_t, ### Vkick1_vec_x + unit_l / unit_t, ### Vkick1_vec_y + unit_l / unit_t, ### Vkick1_vec_z + unit_l / unit_t, ### Vkick2_vec_x + unit_l / unit_t, ### Vkick2_vec_y + unit_l / unit_t, ### Vkick2_vec_z + unit_l / unit_t, ### Vkick3_vec_x + unit_l / unit_t, ### Vkick3_vec_y + unit_l / unit_t, ### Vkick3_vec_z + unit_m, ### delta_m1 + unit_m, ### delta_m2 + unit_m, ### delta_m3 + object.NO_UNIT, ### f1 + object.NO_UNIT, ### f2 ), ( - unit_l/unit_t, ### V1_prime_x - unit_l/unit_t, ### V1_prime_y - unit_l/unit_t, ### V1_prime_z - unit_l/unit_t, ### V2_prime_x - unit_l/unit_t, ### V2_prime_y - unit_l/unit_t, ### V2_prime_z - unit_l/unit_t, ### V3_prime_x - unit_l/unit_t, ### V3_prime_y - unit_l/unit_t, ### V3_prime_z - object.NO_UNIT, ### e1_vec_x_p - object.NO_UNIT, ### e1_vec_y_p - object.NO_UNIT, ### e1_vec_z_p - object.NO_UNIT, ### e2_vec_x_p - object.NO_UNIT, ### e2_vec_y_p - object.NO_UNIT, ### e2_vec_z_p - unit_h, ### h1_vec_x_p - unit_h, ### h1_vec_y_p - unit_h, ### h1_vec_z_p - unit_h, ### h2_vec_x_p - unit_h, ### h2_vec_y_p - unit_h, ### h2_vec_z_p - object.NO_UNIT, ### cos_phi1 - object.NO_UNIT, ### cos_phi2 - unit_l, ### R - unit_l/unit_t, ### v_sys - unit_l*unit_l/unit_t, ### r1dotvk - unit_l*unit_l/unit_t, ### r1dotv1 - unit_l**2/(unit_t**2), ### v1dotvk - unit_l*unit_l/unit_t, ### r1dotvsys - unit_l**2/(unit_t**2), ### v1dotvsys - unit_l*unit_l/unit_t, ### r2dotv2 - unit_l*unit_l/unit_t, ### r2dotvsys - unit_l**2/(unit_t**2), ### v2dotvsys - unit_l**2, ### r1dotr2 - unit_l**2/unit_t, ### r1dotv2 + unit_l / unit_t, ### V1_prime_x + unit_l / unit_t, ### V1_prime_y + unit_l / unit_t, ### V1_prime_z + unit_l / unit_t, ### V2_prime_x + unit_l / unit_t, ### V2_prime_y + unit_l / unit_t, ### V2_prime_z + unit_l / unit_t, ### V3_prime_x + unit_l / unit_t, ### V3_prime_y + unit_l / unit_t, ### V3_prime_z + object.NO_UNIT, ### e1_vec_x_p + object.NO_UNIT, ### e1_vec_y_p + object.NO_UNIT, ### e1_vec_z_p + object.NO_UNIT, ### e2_vec_x_p + object.NO_UNIT, ### e2_vec_y_p + object.NO_UNIT, ### e2_vec_z_p + unit_h, ### h1_vec_x_p + unit_h, ### h1_vec_y_p + unit_h, ### h1_vec_z_p + unit_h, ### h2_vec_x_p + unit_h, ### h2_vec_y_p + unit_h, ### h2_vec_z_p + object.NO_UNIT, ### cos_phi1 + object.NO_UNIT, ### cos_phi2 + unit_l, ### R + unit_l / unit_t, ### v_sys + unit_l * unit_l / unit_t, ### r1dotvk + unit_l * unit_l / unit_t, ### r1dotv1 + unit_l**2 / (unit_t**2), ### v1dotvk + unit_l * unit_l / unit_t, ### r1dotvsys + unit_l**2 / (unit_t**2), ### v1dotvsys + unit_l * unit_l / unit_t, ### r2dotv2 + unit_l * unit_l / unit_t, ### r2dotvsys + unit_l**2 / (unit_t**2), ### v2dotvsys + unit_l**2, ### r1dotr2 + unit_l**2 / unit_t, ### r1dotv2 object.ERROR_CODE, - ) + ), ) - + object.add_method( "a_out_div_a_in_dynamical_stability", ( - unit_m, ### m1 - unit_m, ### m2 - unit_m, ### m3 - unit_l, ### a_in - unit_l, ### a_out - object.NO_UNIT, ### e_in - object.NO_UNIT, ### e_out - object.NO_UNIT, ### itot -- NOTE: should be in radians - object.NO_UNIT, ### stability_limit_specification - + unit_m, ### m1 + unit_m, ### m2 + unit_m, ### m3 + unit_l, ### a_in + unit_l, ### a_out + object.NO_UNIT, ### e_in + object.NO_UNIT, ### e_out + object.NO_UNIT, ### itot -- NOTE: should be in radians + object.NO_UNIT, ### stability_limit_specification ), - ( - object.NO_UNIT, ### a_out/a_in for dynamical stability - ) + (object.NO_UNIT,), ### a_out/a_in for dynamical stability ) object.add_method( "a_out_div_a_in_semisecular_regime", ( - unit_m, ### m1 - unit_m, ### m2 - unit_m, ### m3 - object.NO_UNIT, ### e_in - object.NO_UNIT, ### e_out - object.NO_UNIT, ### check_for_semisecular_regime_parameter + unit_m, ### m1 + unit_m, ### m2 + unit_m, ### m3 + object.NO_UNIT, ### e_in + object.NO_UNIT, ### e_out + object.NO_UNIT, ### check_for_semisecular_regime_parameter ), - ( - object.NO_UNIT, ### a_out/a_in for semisecular regime - ) + (object.NO_UNIT,), ### a_out/a_in for semisecular regime ) - object.add_method( "roche_radius", ( - unit_l, ### rp - object.NO_UNIT, ### q - object.NO_UNIT, ### e - object.NO_UNIT, ### f - object.NO_UNIT, ### roche_radius_specification + unit_l, ### rp + object.NO_UNIT, ### q + object.NO_UNIT, ### e + object.NO_UNIT, ### f + object.NO_UNIT, ### roche_radius_specification ), - ( - unit_l, ### Roche radius - ) + (unit_l,), ### Roche radius ) """ @@ -1586,13 +2086,14 @@ def define_methods(self, object): (object.ERROR_CODE,) ) """ + def before_get_parameter(self): """ Called everytime just before a parameter is retrieved in using:: instance.parameter.name """ pass - + def before_set_parameter(self): """ Called everytime just before a parameter is updated in using:: @@ -1600,19 +2101,57 @@ def before_set_parameter(self): """ pass - def define_particle_sets(self,object): - object.define_inmemory_set('triples') + def define_particle_sets(self, object): + object.define_inmemory_set("triples") def check_for_dynamical_stability(self): for index_triple, triple in enumerate(self.triples): - inner_binary,outer_binary,star1,star2,star3 = give_binaries_and_stars(self,triple) - m1,m2,m3,R1,R2,R3,a_in,a_out,e_in,e_out,INCL_in,INCL_out,AP_in,AP_out,LAN_in,LAN_out = give_stellar_masses_radii_and_binary_parameters(self,star1,star2,star3,inner_binary,outer_binary,triple) - - a_out_div_a_in_dynamical_stability = self.a_out_div_a_in_dynamical_stability(m1,m2,m3,a_in,a_out,e_in, e_out,triple.relative_inclination, self.parameters.stability_limit_specification) - if a_out/a_in <= a_out_div_a_in_dynamical_stability: + inner_binary, outer_binary, star1, star2, star3 = give_binaries_and_stars( + self, triple + ) + ( + m1, + m2, + m3, + R1, + R2, + R3, + a_in, + a_out, + e_in, + e_out, + INCL_in, + INCL_out, + AP_in, + AP_out, + LAN_in, + LAN_out, + ) = give_stellar_masses_radii_and_binary_parameters( + self, star1, star2, star3, inner_binary, outer_binary, triple + ) + + a_out_div_a_in_dynamical_stability = ( + self.a_out_div_a_in_dynamical_stability( + m1, + m2, + m3, + a_in, + a_out, + e_in, + e_out, + triple.relative_inclination, + self.parameters.stability_limit_specification, + ) + ) + if a_out / a_in <= a_out_div_a_in_dynamical_stability: if self.parameters.verbose == True: - print('SecularTriple -- triple system is dynamically unstable: a_out/a_in = ',a_out/a_in,', whereas for dynamical stability, a_out/a_in should be > ',a_out_div_a_in_dynamical_stability) + print( + "SecularTriple -- triple system is dynamically unstable: a_out/a_in = ", + a_out / a_in, + ", whereas for dynamical stability, a_out/a_in should be > ", + a_out_div_a_in_dynamical_stability, + ) triple.dynamical_instability = True else: triple.dynamical_instability = False @@ -1620,50 +2159,125 @@ def check_for_dynamical_stability(self): def check_for_semisecular_regime(self): for index_triple, triple in enumerate(self.triples): - inner_binary,outer_binary,star1,star2,star3 = give_binaries_and_stars(self,triple) - m1,m2,m3,R1,R2,R3,a_in,a_out,e_in,e_out,INCL_in,INCL_out,AP_in,AP_out,LAN_in,LAN_out = give_stellar_masses_radii_and_binary_parameters(self,star1,star2,star3,inner_binary,outer_binary,triple) - - check_for_semisecular_regime_parameter = self.parameters.check_for_semisecular_regime_parameter - a_out_div_a_in_semisecular_regime = self.a_out_div_a_in_semisecular_regime(m1,m2,m3,e_in,e_out,check_for_semisecular_regime_parameter) - if a_out/a_in <= a_out_div_a_in_semisecular_regime: + inner_binary, outer_binary, star1, star2, star3 = give_binaries_and_stars( + self, triple + ) + ( + m1, + m2, + m3, + R1, + R2, + R3, + a_in, + a_out, + e_in, + e_out, + INCL_in, + INCL_out, + AP_in, + AP_out, + LAN_in, + LAN_out, + ) = give_stellar_masses_radii_and_binary_parameters( + self, star1, star2, star3, inner_binary, outer_binary, triple + ) + + check_for_semisecular_regime_parameter = ( + self.parameters.check_for_semisecular_regime_parameter + ) + a_out_div_a_in_semisecular_regime = self.a_out_div_a_in_semisecular_regime( + m1, m2, m3, e_in, e_out, check_for_semisecular_regime_parameter + ) + if a_out / a_in <= a_out_div_a_in_semisecular_regime: if self.parameters.verbose == True: - print('SecularTriple -- triple system is within the semisecular regime: a_out/a_in = ',a_out/a_in,'; a_out/a_in for semisecular regime: ',a_out_div_a_in_semisecular_regime) + print( + "SecularTriple -- triple system is within the semisecular regime: a_out/a_in = ", + a_out / a_in, + "; a_out/a_in for semisecular regime: ", + a_out_div_a_in_semisecular_regime, + ) triple.semisecular_regime = True else: triple.semisecular_regime = False - - - def evolve_model(self,end_time): + def evolve_model(self, end_time): if end_time is None: if self.parameters.verbose == True: - print('SecularTriple -- please specify end time!') + print("SecularTriple -- please specify end time!") return parameters = self.parameters triples = self.triples - + for index_triple, triple in enumerate(triples): ### extract data from triple ### - self.time_step = end_time - self.model_time + self.time_step = end_time - self.model_time - inner_binary,outer_binary,star1,star2,star3 = give_binaries_and_stars(self,triple) - args,skip_integration = extract_data_and_give_args(self,triple,inner_binary,outer_binary,star1,star2,star3) - if skip_integration == True: + inner_binary, outer_binary, star1, star2, star3 = give_binaries_and_stars( + self, triple + ) + args, skip_integration = extract_data_and_give_args( + self, triple, inner_binary, outer_binary, star1, star2, star3 + ) + if skip_integration == True: continue ### solve system of ODEs ### - m1,m2,m3,R1,R2,R3, \ - spin_angular_frequency1,spin_angular_frequency2,spin_angular_frequency3, \ - a_in,a_out,e_in,e_out, delta_e_in, \ - INCL_in,INCL_out,INCL_in_out, \ - AP_in,AP_out,LAN_in,LAN_out, \ - end_time_cvode,CVODE_flag,root_finding_flag = self.evolve(*args) + ( + m1, + m2, + m3, + R1, + R2, + R3, + spin_angular_frequency1, + spin_angular_frequency2, + spin_angular_frequency3, + a_in, + a_out, + e_in, + e_out, + delta_e_in, + INCL_in, + INCL_out, + INCL_in_out, + AP_in, + AP_out, + LAN_in, + LAN_out, + end_time_cvode, + CVODE_flag, + root_finding_flag, + ) = self.evolve(*args) if self.parameters.verbose == True: - print('SecularTriple -- done; t/Myr = ', end_time.value_in(units.Myr),' a_in/AU=',a_in.value_in(units.AU),' a_out/AU=',a_out.value_in(units.AU),'; e_in=',e_in,'e_out=',e_out,' rel_INCL = ',INCL_in,' spin_freq1/day^{-1} = ',spin_angular_frequency1.value_in(1.0/units.day),'LAN_in',LAN_in,'LAN_out',LAN_out,'AP_in',AP_in,'AP_out',AP_out) - - print_CVODE_output(self,CVODE_flag) + print( + "SecularTriple -- done; t/Myr = ", + end_time.value_in(units.Myr), + " a_in/AU=", + a_in.value_in(units.AU), + " a_out/AU=", + a_out.value_in(units.AU), + "; e_in=", + e_in, + "e_out=", + e_out, + " rel_INCL = ", + INCL_in, + " spin_freq1/day^{-1} = ", + spin_angular_frequency1.value_in(1.0 / units.day), + "LAN_in", + LAN_in, + "LAN_out", + LAN_out, + "AP_in", + AP_in, + "AP_out", + AP_out, + ) + + print_CVODE_output(self, CVODE_flag) triple.error_flag_secular = CVODE_flag #################### @@ -1673,69 +2287,80 @@ def evolve_model(self,end_time): triple.inner_collision = False triple.outer_collision = False triple.semisecular_regime = False - + ### The secular code will stop the integration if a root is found. ### In some cases, it is desirable to, nevertheless, continue integrating ### until the end time originally specified from triple.py. ### In those cases, evolve_further_until_original_end_time is to be set to `True'. - if CVODE_flag==CV_ROOT_RETURN: - + if CVODE_flag == CV_ROOT_RETURN: + ### dynamical instability ### - if root_finding_flag==1: + if root_finding_flag == 1: if self.parameters.verbose == True: - print('SecularTriple -- triple dynamical instability') + print("SecularTriple -- triple dynamical instability") triple.dynamical_instability = True - + ### inner collision ### - if root_finding_flag==2: + if root_finding_flag == 2: triple.inner_collision = True if self.parameters.verbose == True: - print( 'SecularTriple --inner collision') + print("SecularTriple --inner collision") ### outer collision ### - if root_finding_flag==3: + if root_finding_flag == 3: triple.outer_collision = True if self.parameters.verbose == True: - print( 'SecularTriple --outer collision') - + print("SecularTriple --outer collision") + ### RLOF star1 ### - if root_finding_flag==4: + if root_finding_flag == 4: star1.is_donor = True if self.parameters.verbose == True: - print( 'SecularTriple -- star 1 has filled its Roche Lobe during secular integration') - if root_finding_flag==-4: + print( + "SecularTriple -- star 1 has filled its Roche Lobe during secular integration" + ) + if root_finding_flag == -4: star1.is_donor = False if self.parameters.verbose == True: - print( 'SecularTriple -- star 1 no longer fills its Roche Lobe during secular integration') + print( + "SecularTriple -- star 1 no longer fills its Roche Lobe during secular integration" + ) self.evolve_further_after_root_was_found = True - + ### RLOF star2 ### - if root_finding_flag==5: + if root_finding_flag == 5: star2.is_donor = True if self.parameters.verbose == True: - print( 'SecularTriple -- star 2 has filled its Roche Lobe during secular integration') - if root_finding_flag==-5: + print( + "SecularTriple -- star 2 has filled its Roche Lobe during secular integration" + ) + if root_finding_flag == -5: star2.is_donor = False if self.parameters.verbose == True: - print( 'SecularTriple -- star 2 no longer fills its Roche Lobe during secular integration') + print( + "SecularTriple -- star 2 no longer fills its Roche Lobe during secular integration" + ) self.evolve_further_after_root_was_found = True - + ### RLOF star3 ### - if root_finding_flag==6: + if root_finding_flag == 6: star3.is_donor = True if self.parameters.verbose == True: - print( 'SecularTriple -- star 3 has filled its Roche Lobe during secular integration') - if root_finding_flag==-6: + print( + "SecularTriple -- star 3 has filled its Roche Lobe during secular integration" + ) + if root_finding_flag == -6: star3.is_donor = False if self.parameters.verbose == True: - print( 'SecularTriple -- star 3 no longer fills its Roche Lobe during secular integration') + print( + "SecularTriple -- star 3 no longer fills its Roche Lobe during secular integration" + ) self.evolve_further_after_root_was_found = True - ### semisecular regime ### - if root_finding_flag==7: + if root_finding_flag == 7: if self.parameters.verbose == True: - print( 'SecularTriple -- semisecular regime') + print("SecularTriple -- semisecular regime") triple.semisecular_regime = True ### update model time ### @@ -1759,7 +2384,7 @@ def evolve_model(self,end_time): star2.spin_angular_frequency = spin_angular_frequency2 if parameters.include_spin_radius_mass_coupling_terms_star3 == True: star3.spin_angular_frequency = spin_angular_frequency3 - + inner_binary.semimajor_axis = a_in inner_binary.eccentricity = e_in outer_binary.semimajor_axis = a_out @@ -1772,133 +2397,382 @@ def evolve_model(self,end_time): inner_binary.delta_e_in = delta_e_in if self.evolve_further_after_root_was_found == True: - original_time_step = self.time_step ### time-step given from triple.py - old_secular_time_step = end_time_cvode ### time-step made by secular code until root was found - new_secular_time_step = original_time_step - old_secular_time_step ### the remaining time that the secular code should integrate for + original_time_step = self.time_step ### time-step given from triple.py + old_secular_time_step = end_time_cvode ### time-step made by secular code until root was found + new_secular_time_step = ( + original_time_step - old_secular_time_step + ) ### the remaining time that the secular code should integrate for new_end_time = self.model_time + new_secular_time_step - if self.take_into_account_RLOF_after_no_longer_filling_Roche_lobe == False: + if ( + self.take_into_account_RLOF_after_no_longer_filling_Roche_lobe + == False + ): string = "NOT" else: string = "" if self.parameters.verbose == True: - print( 'SecularTriple -- root was found at t = ',self.model_time,'; integrating further until end time t = ',new_end_time,', specified from triple.py; RLOF is ',string,' taken into account.') - + print( + "SecularTriple -- root was found at t = ", + self.model_time, + "; integrating further until end time t = ", + new_end_time, + ", specified from triple.py; RLOF is ", + string, + " taken into account.", + ) + ### In the remaining time, do not check for RLOF. ### However, for consistency with the stellar/binary evolution code, if the latter assumed RLOF from the beginning of the time-step, do take into account effect of RLOF on the orbit. - if root_finding_flag==-4: - parameters.check_for_inner_RLOF = False - if self.take_into_account_RLOF_after_no_longer_filling_Roche_lobe == True: - star1.is_donor = True - if root_finding_flag==-5: + if root_finding_flag == -4: + parameters.check_for_inner_RLOF = False + if ( + self.take_into_account_RLOF_after_no_longer_filling_Roche_lobe + == True + ): + star1.is_donor = True + if root_finding_flag == -5: parameters.check_for_inner_RLOF = False - if self.take_into_account_RLOF_after_no_longer_filling_Roche_lobe == True: + if ( + self.take_into_account_RLOF_after_no_longer_filling_Roche_lobe + == True + ): star2.is_donor = True - if root_finding_flag==-6: + if root_finding_flag == -6: parameters.check_for_outer_RLOF = False - if self.take_into_account_RLOF_after_no_longer_filling_Roche_lobe == True: + if ( + self.take_into_account_RLOF_after_no_longer_filling_Roche_lobe + == True + ): star3.is_donor = True self.evolve_further_after_root_was_found = False self.evolve_model(new_end_time) ### Check for RLOF again in the next call by triple.py -- this parameter must originally have been True, otherwise a root could never have been found in the first place. ### Set is_donor to False for next call by triple.py. - if root_finding_flag==-4: - parameters.check_for_inner_RLOF = True + if root_finding_flag == -4: + parameters.check_for_inner_RLOF = True star1.is_donor = False - if root_finding_flag==-5: + if root_finding_flag == -5: parameters.check_for_inner_RLOF = True star2.is_donor = False - if root_finding_flag==-6: + if root_finding_flag == -6: parameters.check_for_outer_RLOF = True star3.is_donor = False - def give_roche_radii(self,triple): + def give_roche_radii(self, triple): if triple is None: if self.parameters.verbose == True: - print( 'SecularTriple -- please give triple particle') + print("SecularTriple -- please give triple particle") return - inner_binary,outer_binary,star1,star2,star3 = give_binaries_and_stars(self,triple) - m1,m2,m3,R1,R2,R3,a_in,a_out,e_in,e_out,INCL_in,INCL_out,AP_in,AP_out,LAN_in,LAN_out = give_stellar_masses_radii_and_binary_parameters(self,star1,star2,star3,inner_binary,outer_binary,triple) + inner_binary, outer_binary, star1, star2, star3 = give_binaries_and_stars( + self, triple + ) + ( + m1, + m2, + m3, + R1, + R2, + R3, + a_in, + a_out, + e_in, + e_out, + INCL_in, + INCL_out, + AP_in, + AP_out, + LAN_in, + LAN_out, + ) = give_stellar_masses_radii_and_binary_parameters( + self, star1, star2, star3, inner_binary, outer_binary, triple + ) spin_angular_frequency1 = star1.spin_angular_frequency spin_angular_frequency2 = star2.spin_angular_frequency spin_angular_frequency3 = star3.spin_angular_frequency - rp_in = a_in*(1.0-e_in) - rp_out = a_out*(1.0-e_out) + rp_in = a_in * (1.0 - e_in) + rp_out = a_out * (1.0 - e_out) - spin_angular_frequency_inner_orbit_periapse = numpy.sqrt( constants.G*(m1+m2)*(1.0+e_in)/(rp_in**3) ) - spin_angular_frequency_outer_orbit_periapse = numpy.sqrt( constants.G*(m1+m2+m3)*(1.0+e_out)/(rp_out**3) ) + spin_angular_frequency_inner_orbit_periapse = numpy.sqrt( + constants.G * (m1 + m2) * (1.0 + e_in) / (rp_in**3) + ) + spin_angular_frequency_outer_orbit_periapse = numpy.sqrt( + constants.G * (m1 + m2 + m3) * (1.0 + e_out) / (rp_out**3) + ) - f1 = spin_angular_frequency1/spin_angular_frequency_inner_orbit_periapse - f2 = spin_angular_frequency2/spin_angular_frequency_inner_orbit_periapse - f3 = spin_angular_frequency3/spin_angular_frequency_outer_orbit_periapse + f1 = spin_angular_frequency1 / spin_angular_frequency_inner_orbit_periapse + f2 = spin_angular_frequency2 / spin_angular_frequency_inner_orbit_periapse + f3 = spin_angular_frequency3 / spin_angular_frequency_outer_orbit_periapse - R_L_star1 = self.roche_radius(rp_in,m1/m2,e_in,f1, self.parameters.roche_radius_specification) - R_L_star2 = self.roche_radius(rp_in,m2/m1,e_in,f2, self.parameters.roche_radius_specification) - R_L_star3 = self.roche_radius(rp_out,m3/(m1+m2),e_out,f3, self.parameters.roche_radius_specification) - - return R_L_star1,R_L_star2,R_L_star3 + R_L_star1 = self.roche_radius( + rp_in, m1 / m2, e_in, f1, self.parameters.roche_radius_specification + ) + R_L_star2 = self.roche_radius( + rp_in, m2 / m1, e_in, f2, self.parameters.roche_radius_specification + ) + R_L_star3 = self.roche_radius( + rp_out, + m3 / (m1 + m2), + e_out, + f3, + self.parameters.roche_radius_specification, + ) - def compute_effect_of_SN_on_triple(self,Vkick_1,Vkick_2,Vkick_3,delta_m_1,delta_m_2,delta_m_3,inner_true_anomaly,outer_true_anomaly): + return R_L_star1, R_L_star2, R_L_star3 + + def compute_effect_of_SN_on_triple( + self, + Vkick_1, + Vkick_2, + Vkick_3, + delta_m_1, + delta_m_2, + delta_m_3, + inner_true_anomaly, + outer_true_anomaly, + ): triples = self.triples - - + ################################################# ### convention: new mass = old mass - delta_m ### ### i.e., delta_m>0 for mass loss ### ################################################# - + for index_triple, triple in enumerate(triples): - inner_binary,outer_binary,star1,star2,star3 = give_binaries_and_stars(self,triple) - m1,m2,m3,R1,R2,R3,a_in,a_out,e_in,e_out,INCL_in,INCL_out,AP_in,AP_out,LAN_in,LAN_out = give_stellar_masses_radii_and_binary_parameters(self,star1,star2,star3,inner_binary,outer_binary,triple) - + inner_binary, outer_binary, star1, star2, star3 = give_binaries_and_stars( + self, triple + ) + ( + m1, + m2, + m3, + R1, + R2, + R3, + a_in, + a_out, + e_in, + e_out, + INCL_in, + INCL_out, + AP_in, + AP_out, + LAN_in, + LAN_out, + ) = give_stellar_masses_radii_and_binary_parameters( + self, star1, star2, star3, inner_binary, outer_binary, triple + ) + if self.parameters.verbose == True: - print( 'PRE orb',a_in.value_in(units.AU),a_out.value_in(units.AU),e_in,e_out,INCL_in,AP_in,AP_out,LAN_in,LAN_out) - + print( + "PRE orb", + a_in.value_in(units.AU), + a_out.value_in(units.AU), + e_in, + e_out, + INCL_in, + AP_in, + AP_out, + LAN_in, + LAN_out, + ) + ### pre-SN -- from orbital elements to orbital vectors ### - e_in_vec_x,e_in_vec_y,e_in_vec_z,e_out_vec_x,e_out_vec_y,e_out_vec_z,h_in_vec_x,h_in_vec_y,h_in_vec_z,h_out_vec_x,h_out_vec_y,h_out_vec_z = self.compute_orbital_vectors_from_orbital_elements(m1,m2,m3,a_in,a_out,e_in,e_out,INCL_in,AP_in,AP_out,LAN_in,LAN_out) - + ( + e_in_vec_x, + e_in_vec_y, + e_in_vec_z, + e_out_vec_x, + e_out_vec_y, + e_out_vec_z, + h_in_vec_x, + h_in_vec_y, + h_in_vec_z, + h_out_vec_x, + h_out_vec_y, + h_out_vec_z, + ) = self.compute_orbital_vectors_from_orbital_elements( + m1, + m2, + m3, + a_in, + a_out, + e_in, + e_out, + INCL_in, + AP_in, + AP_out, + LAN_in, + LAN_out, + ) + if self.parameters.verbose == True: - print( 'PRE vec',e_in_vec_x,e_in_vec_y,e_in_vec_z,e_out_vec_x,e_out_vec_y,e_out_vec_z,h_in_vec_x,h_in_vec_y,h_in_vec_z,h_out_vec_x,h_out_vec_y,h_out_vec_z) - + print( + "PRE vec", + e_in_vec_x, + e_in_vec_y, + e_in_vec_z, + e_out_vec_x, + e_out_vec_y, + e_out_vec_z, + h_in_vec_x, + h_in_vec_y, + h_in_vec_z, + h_out_vec_x, + h_out_vec_y, + h_out_vec_z, + ) + ### effect of SN on orbital vectors ### - V1_prime_x,V1_prime_y,V1_prime_z, \ - V2_prime_x,V2_prime_y,V2_prime_z, \ - V3_prime_x,V3_prime_y,V3_prime_z, \ - e_in_vec_x_prime,e_in_vec_y_prime,e_in_vec_z_prime,e_out_vec_x_prime,e_out_vec_y_prime,e_out_vec_z_prime, \ - h_in_vec_x_prime,h_in_vec_y_prime,h_in_vec_z_prime,h_out_vec_x_prime,h_out_vec_y_prime,h_out_vec_z_prime, \ - cos_phi1,cos_phi2,R,v_sys, \ - r1dotv1, r1dotvk, v1dotvk, \ - r1dotvsys, v1dotvsys, r2dotv2, r2dotvsys, v2dotvsys, r1dotr2, r1dotv2 = \ - self.compute_effect_of_SN_on_orbital_vectors(m1,m2,m3, \ - e_in_vec_x,e_in_vec_y,e_in_vec_z,e_out_vec_x,e_out_vec_y,e_out_vec_z, \ - h_in_vec_x,h_in_vec_y,h_in_vec_z,h_out_vec_x,h_out_vec_y,h_out_vec_z, \ - Vkick_1[0],Vkick_1[1],Vkick_1[2],Vkick_2[0],Vkick_2[1],Vkick_2[2],Vkick_3[0],Vkick_3[1],Vkick_3[2], - delta_m_1,delta_m_2,delta_m_3,inner_true_anomaly,outer_true_anomaly) - - unit_v = unit_l/unit_t - V1_prime = [V1_prime_x.value_in(unit_v),V1_prime_y.value_in(unit_v),V1_prime_z.value_in(unit_v)] | unit_v - V2_prime = [V2_prime_x.value_in(unit_v),V2_prime_y.value_in(unit_v),V2_prime_z.value_in(unit_v)] | unit_v - V3_prime = [V3_prime_x.value_in(unit_v),V3_prime_y.value_in(unit_v),V3_prime_z.value_in(unit_v)] | unit_v - + ( + V1_prime_x, + V1_prime_y, + V1_prime_z, + V2_prime_x, + V2_prime_y, + V2_prime_z, + V3_prime_x, + V3_prime_y, + V3_prime_z, + e_in_vec_x_prime, + e_in_vec_y_prime, + e_in_vec_z_prime, + e_out_vec_x_prime, + e_out_vec_y_prime, + e_out_vec_z_prime, + h_in_vec_x_prime, + h_in_vec_y_prime, + h_in_vec_z_prime, + h_out_vec_x_prime, + h_out_vec_y_prime, + h_out_vec_z_prime, + cos_phi1, + cos_phi2, + R, + v_sys, + r1dotv1, + r1dotvk, + v1dotvk, + r1dotvsys, + v1dotvsys, + r2dotv2, + r2dotvsys, + v2dotvsys, + r1dotr2, + r1dotv2, + ) = self.compute_effect_of_SN_on_orbital_vectors( + m1, + m2, + m3, + e_in_vec_x, + e_in_vec_y, + e_in_vec_z, + e_out_vec_x, + e_out_vec_y, + e_out_vec_z, + h_in_vec_x, + h_in_vec_y, + h_in_vec_z, + h_out_vec_x, + h_out_vec_y, + h_out_vec_z, + Vkick_1[0], + Vkick_1[1], + Vkick_1[2], + Vkick_2[0], + Vkick_2[1], + Vkick_2[2], + Vkick_3[0], + Vkick_3[1], + Vkick_3[2], + delta_m_1, + delta_m_2, + delta_m_3, + inner_true_anomaly, + outer_true_anomaly, + ) + + unit_v = unit_l / unit_t + V1_prime = [ + V1_prime_x.value_in(unit_v), + V1_prime_y.value_in(unit_v), + V1_prime_z.value_in(unit_v), + ] | unit_v + V2_prime = [ + V2_prime_x.value_in(unit_v), + V2_prime_y.value_in(unit_v), + V2_prime_z.value_in(unit_v), + ] | unit_v + V3_prime = [ + V3_prime_x.value_in(unit_v), + V3_prime_y.value_in(unit_v), + V3_prime_z.value_in(unit_v), + ] | unit_v + if self.parameters.verbose == True: - print( 'POST vec',e_in_vec_x_prime,e_in_vec_y_prime,e_in_vec_z_prime,e_out_vec_x_prime,e_out_vec_y_prime,e_out_vec_z_prime, \ - h_in_vec_x_prime,h_in_vec_y_prime,h_in_vec_z_prime,h_out_vec_x_prime,h_out_vec_y_prime,h_out_vec_z_prime) - + print( + "POST vec", + e_in_vec_x_prime, + e_in_vec_y_prime, + e_in_vec_z_prime, + e_out_vec_x_prime, + e_out_vec_y_prime, + e_out_vec_z_prime, + h_in_vec_x_prime, + h_in_vec_y_prime, + h_in_vec_z_prime, + h_out_vec_x_prime, + h_out_vec_y_prime, + h_out_vec_z_prime, + ) + ### post-SN -- from orbital vectors to orbital elements (with new reference frame) ### - a_in_prime,a_out_prime,e_in_prime,e_out_prime,INCL_rel_prime,AP_in_prime,AP_out_prime,LAN_in_prime,LAN_out_prime = \ - self.compute_orbital_elements_from_orbital_vectors(m1-delta_m_1, m2-delta_m_2, m3-delta_m_3, \ - e_in_vec_x_prime,e_in_vec_y_prime,e_in_vec_z_prime, \ - e_out_vec_x_prime,e_out_vec_y_prime,e_out_vec_z_prime, \ - h_in_vec_x_prime,h_in_vec_y_prime,h_in_vec_z_prime, \ - h_out_vec_x_prime,h_out_vec_y_prime,h_out_vec_z_prime) - + ( + a_in_prime, + a_out_prime, + e_in_prime, + e_out_prime, + INCL_rel_prime, + AP_in_prime, + AP_out_prime, + LAN_in_prime, + LAN_out_prime, + ) = self.compute_orbital_elements_from_orbital_vectors( + m1 - delta_m_1, + m2 - delta_m_2, + m3 - delta_m_3, + e_in_vec_x_prime, + e_in_vec_y_prime, + e_in_vec_z_prime, + e_out_vec_x_prime, + e_out_vec_y_prime, + e_out_vec_z_prime, + h_in_vec_x_prime, + h_in_vec_y_prime, + h_in_vec_z_prime, + h_out_vec_x_prime, + h_out_vec_y_prime, + h_out_vec_z_prime, + ) + if self.parameters.verbose == True: - print( 'POST orb',a_in_prime.value_in(units.AU),a_out_prime.value_in(units.AU),e_in_prime,e_out_prime,INCL_rel_prime,AP_in_prime,AP_out_prime,LAN_in_prime,LAN_out_prime) - + print( + "POST orb", + a_in_prime.value_in(units.AU), + a_out_prime.value_in(units.AU), + e_in_prime, + e_out_prime, + INCL_rel_prime, + AP_in_prime, + AP_out_prime, + LAN_in_prime, + LAN_out_prime, + ) + inner_binary.semimajor_axis = a_in_prime inner_binary.eccentricity = e_in_prime outer_binary.semimajor_axis = a_out_prime @@ -1909,68 +2783,83 @@ def compute_effect_of_SN_on_triple(self,Vkick_1,Vkick_2,Vkick_3,delta_m_1,delta_ inner_binary.longitude_of_ascending_node = LAN_in_prime outer_binary.longitude_of_ascending_node = LAN_out_prime - #return V1_prime,V2_prime,V3_prime,cos_phi1,cos_phi2,R,v_sys,r1dotv1, r1dotvk, v1dotvk, r1dotvsys, v1dotvsys, r2dotv2, r2dotvsys, v2dotvsys, r1dotr2, r1dotv2 - return V1_prime,V2_prime,V3_prime - -def print_CVODE_output(self,CVODE_flag): - if self.parameters.verbose == False: return - - if CVODE_flag==CV_SUCCESS: - print( "SecularTriple -- ODE integration proceeded successfully.") - elif CVODE_flag==CV_ROOT_RETURN: - print( "SecularTriple -- root was found during ODE integration.") - elif CVODE_flag==CV_WARNING: - print( "SecularTriple -- (recoverable) warnings occurred during ODE integration.") - if CVODE_flag<0: - if CVODE_flag==CV_TOO_MUCH_WORK: + # return V1_prime,V2_prime,V3_prime,cos_phi1,cos_phi2,R,v_sys,r1dotv1, r1dotvk, v1dotvk, r1dotvsys, v1dotvsys, r2dotv2, r2dotvsys, v2dotvsys, r1dotr2, r1dotv2 + return V1_prime, V2_prime, V3_prime + + +def print_CVODE_output(self, CVODE_flag): + if self.parameters.verbose == False: + return + + if CVODE_flag == CV_SUCCESS: + print("SecularTriple -- ODE integration proceeded successfully.") + elif CVODE_flag == CV_ROOT_RETURN: + print("SecularTriple -- root was found during ODE integration.") + elif CVODE_flag == CV_WARNING: + print( + "SecularTriple -- (recoverable) warnings occurred during ODE integration." + ) + if CVODE_flag < 0: + if CVODE_flag == CV_TOO_MUCH_WORK: message = "too many steps were taken during ODE integration." - elif CVODE_flag==CV_TOO_MUCH_ACC: + elif CVODE_flag == CV_TOO_MUCH_ACC: message = "required accuracy could not be obtained." - elif CVODE_flag==CV_ERR_FAILURE: + elif CVODE_flag == CV_ERR_FAILURE: message = "error test failures occurred too many times during one internal time-step or minimum step size was reached." - elif CVODE_flag==CV_CONV_FAILURE: + elif CVODE_flag == CV_CONV_FAILURE: message = "convergence test failures occurred too many times during one internal time-step or minimum step size was reached." - elif CVODE_flag==CV_LINIT_FAIL: + elif CVODE_flag == CV_LINIT_FAIL: message = "the linear solver's initialization function failed." - elif CVODE_flag==CV_LSETUP_FAIL: - message = "the linear solver's setup function failed in an unrecoverable manner." - elif CVODE_flag==CV_LSOLVE_FAIL: - message = "the linear solver's solve function failed in an unrecoverable manner." - elif CVODE_flag==CV_RHSFUNC_FAIL: + elif CVODE_flag == CV_LSETUP_FAIL: + message = ( + "the linear solver's setup function failed in an unrecoverable manner." + ) + elif CVODE_flag == CV_LSOLVE_FAIL: + message = ( + "the linear solver's solve function failed in an unrecoverable manner." + ) + elif CVODE_flag == CV_RHSFUNC_FAIL: message = "the right-hand side function failed in an unrecoverable manner." - elif CVODE_flag==CV_FIRST_RHSFUNC_ERR: + elif CVODE_flag == CV_FIRST_RHSFUNC_ERR: message = "the right-hand side function failed at the first call." - elif CVODE_flag==CV_REPTD_RHSFUNC_ERR: + elif CVODE_flag == CV_REPTD_RHSFUNC_ERR: message = "the right-hand side function had repetead recoverable errors." - elif CVODE_flag==CV_UNREC_RHSFUNC_ERR: + elif CVODE_flag == CV_UNREC_RHSFUNC_ERR: message = "the right-hand side function had a recoverable error, but no recovery is possible." - elif CVODE_flag==CV_RTFUNC_FAIL: + elif CVODE_flag == CV_RTFUNC_FAIL: message = "the rootfinding function failed in an unrecoverable manner." - elif CVODE_flag==CV_MEM_FAIL: + elif CVODE_flag == CV_MEM_FAIL: message = "a memory allocation failed." - elif CVODE_flag==CV_MEM_NULL: + elif CVODE_flag == CV_MEM_NULL: message = "the cvode mem argument was NULL." - elif CVODE_flag==CV_ILL_INPUT: + elif CVODE_flag == CV_ILL_INPUT: message = "one of the function inputs is illegal." - elif CVODE_flag==CV_NO_MALLOC: - message = "the cvode memory block was not allocated by a call to CVodeMalloc." - elif CVODE_flag==CV_BAD_K: + elif CVODE_flag == CV_NO_MALLOC: + message = ( + "the cvode memory block was not allocated by a call to CVodeMalloc." + ) + elif CVODE_flag == CV_BAD_K: message = "the derivative order k is larger than the order used." - elif CVODE_flag==CV_BAD_T: + elif CVODE_flag == CV_BAD_T: message = "the time t is outside the last step taken." - elif CVODE_flag==CV_BAD_DKY: + elif CVODE_flag == CV_BAD_DKY: message = "the output derivative vector is NULL." - elif CVODE_flag==CV_TOO_CLOSE: + elif CVODE_flag == CV_TOO_CLOSE: message = "the output and initial times are too close to each other." else: message = "unknown error." - print( "SecularTriple -- unrecoverable error occurred during secular integration (CVODE_flag ",str(CVODE_flag),"): ",message) + print( + "SecularTriple -- unrecoverable error occurred during secular integration (CVODE_flag ", + str(CVODE_flag), + "): ", + message, + ) -def give_binaries_and_stars(self,triple): +def give_binaries_and_stars(self, triple): ### the 'old' method ### -# inner_binary = triple.child1 -# outer_binary = triple.child2 + # inner_binary = triple.child1 + # outer_binary = triple.child2 ### the 'new' method -- removes the superflous 'triple' layer ### inner_binary = triple.child2 @@ -1978,12 +2867,15 @@ def give_binaries_and_stars(self,triple): star1 = inner_binary.child1 star2 = inner_binary.child2 - star3 = outer_binary.child1 + star3 = outer_binary.child1 - return inner_binary,outer_binary,star1,star2,star3 + return inner_binary, outer_binary, star1, star2, star3 + + +def give_stellar_masses_radii_and_binary_parameters( + self, star1, star2, star3, inner_binary, outer_binary, triple=None +): -def give_stellar_masses_radii_and_binary_parameters(self,star1,star2,star3,inner_binary,outer_binary,triple=None): - ### stellar parameters ### m1 = star1.mass m2 = star2.mass @@ -1991,149 +2883,270 @@ def give_stellar_masses_radii_and_binary_parameters(self,star1,star2,star3,inner R1 = star1.radius R2 = star2.radius - R3 = star3.radius - + R3 = star3.radius + ### binary parameters a_in = inner_binary.semimajor_axis a_out = outer_binary.semimajor_axis e_in = inner_binary.eccentricity e_out = outer_binary.eccentricity - if triple==None: + if triple == None: INCL_in = 0.0 if self.parameters.verbose == True: - print( 'SecularTriple -- warning: relative inclination is being set zero in method give_stellar_masses_radii_and_binary_parameters') + print( + "SecularTriple -- warning: relative inclination is being set zero in method give_stellar_masses_radii_and_binary_parameters" + ) else: - INCL_in = triple.relative_inclination ### in radians + INCL_in = triple.relative_inclination ### in radians INCL_out = 0.0 AP_in = inner_binary.argument_of_pericenter AP_out = outer_binary.argument_of_pericenter LAN_in = inner_binary.longitude_of_ascending_node LAN_out = outer_binary.longitude_of_ascending_node - - return m1,m2,m3,R1,R2,R3,a_in,a_out,e_in,e_out,INCL_in,INCL_out,AP_in,AP_out,LAN_in,LAN_out -def extract_data_and_give_args(self,triple,inner_binary,outer_binary,star1,star2,star3): + return ( + m1, + m2, + m3, + R1, + R2, + R3, + a_in, + a_out, + e_in, + e_out, + INCL_in, + INCL_out, + AP_in, + AP_out, + LAN_in, + LAN_out, + ) + + +def extract_data_and_give_args( + self, triple, inner_binary, outer_binary, star1, star2, star3 +): parameters = self.parameters - skip_integration = False ### if True, no integration will be done in evolve function - - m1,m2,m3,R1,R2,R3,a_in,a_out,e_in,e_out,INCL_in,INCL_out,AP_in,AP_out,LAN_in,LAN_out = give_stellar_masses_radii_and_binary_parameters(self,star1,star2,star3,inner_binary,outer_binary,triple) - + skip_integration = ( + False ### if True, no integration will be done in evolve function + ) + + ( + m1, + m2, + m3, + R1, + R2, + R3, + a_in, + a_out, + e_in, + e_out, + INCL_in, + INCL_out, + AP_in, + AP_out, + LAN_in, + LAN_out, + ) = give_stellar_masses_radii_and_binary_parameters( + self, star1, star2, star3, inner_binary, outer_binary, triple + ) + ### By default, RLOF is taken into account for the remaining integration time if ### a root is found corresponding to the Roche lobe no longer being filled. ### However, in the latter case, if initially R>RL and is_donor = False, then RLOF is not taken into account during the remaining integration. self.take_into_account_RLOF_after_no_longer_filling_Roche_lobe = True - RL1,RL2,RL3 = self.give_roche_radii(triple) - if (R1>=RL1 and star1.is_donor == False): + RL1, RL2, RL3 = self.give_roche_radii(triple) + if R1 >= RL1 and star1.is_donor == False: if self.parameters.verbose == True: - print( 'SecularTriple -- warning: R1>=RL1 at initialisation while star1.is_donor = False; effects of mass transfer on the orbit will not be taken into account.') + print( + "SecularTriple -- warning: R1>=RL1 at initialisation while star1.is_donor = False; effects of mass transfer on the orbit will not be taken into account." + ) self.take_into_account_RLOF_after_no_longer_filling_Roche_lobe = False - if (R2>=RL2 and star2.is_donor == False): + if R2 >= RL2 and star2.is_donor == False: if self.parameters.verbose == True: - print( 'SecularTriple -- warning: R2>=RL2 at initialisation while star2.is_donor = False; effects of mass transfer on the orbit will not be taken into account.') + print( + "SecularTriple -- warning: R2>=RL2 at initialisation while star2.is_donor = False; effects of mass transfer on the orbit will not be taken into account." + ) self.take_into_account_RLOF_after_no_longer_filling_Roche_lobe = False - if (R3>=RL3 and star3.is_donor == False): + if R3 >= RL3 and star3.is_donor == False: if self.parameters.verbose == True: - print( 'SecularTriple -- warning: R3>=RL3 at initialisation while star3.is_donor = False; effects of mass transfer on the orbit will not be taken into account.') - self.take_into_account_RLOF_after_no_longer_filling_Roche_lobe = False + print( + "SecularTriple -- warning: R3>=RL3 at initialisation while star3.is_donor = False; effects of mass transfer on the orbit will not be taken into account." + ) + self.take_into_account_RLOF_after_no_longer_filling_Roche_lobe = False ### if enabled, check for dynamical stability at initialisation ### if parameters.check_for_dynamical_stability_at_initialisation == True: - a_out_div_a_in_dynamical_stability = self.a_out_div_a_in_dynamical_stability(m1,m2,m3,a_in,a_out,e_in,e_out,triple.relative_inclination, self.parameters.stability_limit_specification) - if a_out/a_in <= a_out_div_a_in_dynamical_stability: + a_out_div_a_in_dynamical_stability = self.a_out_div_a_in_dynamical_stability( + m1, + m2, + m3, + a_in, + a_out, + e_in, + e_out, + triple.relative_inclination, + self.parameters.stability_limit_specification, + ) + if a_out / a_in <= a_out_div_a_in_dynamical_stability: if self.parameters.verbose == True: - print( 'SecularTriple -- code parameter "check_for_dynamical_stability_at_initialisation" = True') - print( 'SecularTriple -- given system is initially dynamically unstable: a_out/a_in = ',a_out/a_in,', whereas for dynamical stability, a_out/a_in should be > ',a_out_div_a_in_dynamical_stability) - print( 'SecularTriple -- no integration will be carried out') + print( + 'SecularTriple -- code parameter "check_for_dynamical_stability_at_initialisation" = True' + ) + print( + "SecularTriple -- given system is initially dynamically unstable: a_out/a_in = ", + a_out / a_in, + ", whereas for dynamical stability, a_out/a_in should be > ", + a_out_div_a_in_dynamical_stability, + ) + print("SecularTriple -- no integration will be carried out") skip_integration = True triple.dynamical_instability = True ### if enabled, check for semisecular regime at initialisation ### if parameters.check_for_semisecular_regime_at_initialisation == True: - check_for_semisecular_regime_parameter = self.parameters.check_for_semisecular_regime_parameter - a_out_div_a_in_semisecular_regime = self.a_out_div_a_in_semisecular_regime(m1,m2,m3,e_in,e_out,check_for_semisecular_regime_parameter) - if a_out/a_in <= a_out_div_a_in_semisecular_regime: + check_for_semisecular_regime_parameter = ( + self.parameters.check_for_semisecular_regime_parameter + ) + a_out_div_a_in_semisecular_regime = self.a_out_div_a_in_semisecular_regime( + m1, m2, m3, e_in, e_out, check_for_semisecular_regime_parameter + ) + if a_out / a_in <= a_out_div_a_in_semisecular_regime: if self.parameters.verbose == True: - print( 'SecularTriple -- code parameter "check_for_semisecular_regime_at_initialisation" = True') - print( 'SecularTriple -- given system is initially in semisecular regime: a_out/a_in = ',a_out/a_in,'; a_out/a_in for semisecular regime: ',a_out_div_a_in_semisecular_regime) - print( 'SecularTriple -- no integration will be carried out') + print( + 'SecularTriple -- code parameter "check_for_semisecular_regime_at_initialisation" = True' + ) + print( + "SecularTriple -- given system is initially in semisecular regime: a_out/a_in = ", + a_out / a_in, + "; a_out/a_in for semisecular regime: ", + a_out_div_a_in_semisecular_regime, + ) + print("SecularTriple -- no integration will be carried out") skip_integration = True triple.semisecular_regime = True - wind_mass_loss_rate_star1 = wind_mass_loss_rate_star2 = wind_mass_loss_rate_star3 = 0.0 | units.MSun/units.yr + wind_mass_loss_rate_star1 = wind_mass_loss_rate_star2 = ( + wind_mass_loss_rate_star3 + ) = (0.0 | units.MSun / units.yr) if parameters.include_linear_mass_change == True: try: wind_mass_loss_rate_star1 = star1.wind_mass_loss_rate wind_mass_loss_rate_star2 = star2.wind_mass_loss_rate wind_mass_loss_rate_star3 = star3.wind_mass_loss_rate except AttributeError: - sys.exit('SecularTriple -- mass time_derivative_of_mass is needed for all three stars if include_linear_mass_change==True! exiting') - time_derivative_of_radius_star1=time_derivative_of_radius_star2=time_derivative_of_radius_star3 = 0.0 | units.RSun/units.s + sys.exit( + "SecularTriple -- mass time_derivative_of_mass is needed for all three stars if include_linear_mass_change==True! exiting" + ) + time_derivative_of_radius_star1 = time_derivative_of_radius_star2 = ( + time_derivative_of_radius_star3 + ) = (0.0 | units.RSun / units.s) if parameters.include_linear_radius_change == True: try: time_derivative_of_radius_star1 = star1.time_derivative_of_radius time_derivative_of_radius_star2 = star2.time_derivative_of_radius time_derivative_of_radius_star3 = star3.time_derivative_of_radius except AttributeError: - sys.exit('SecularTriple -- time_derivative_of_radius is needed for all three stars if include_linear_radius_change==True! exiting') + sys.exit( + "SecularTriple -- time_derivative_of_radius is needed for all three stars if include_linear_radius_change==True! exiting" + ) ### mass variation parameters ### star1_is_donor = star2_is_donor = star3_is_donor = False - inner_mass_transfer_rate = outer_mass_transfer_rate = 0.0 | units.MSun/units.yr - inner_accretion_efficiency_wind_child1_to_child2 = inner_accretion_efficiency_wind_child2_to_child1 = 0.0 - outer_accretion_efficiency_wind_child1_to_child2 = outer_accretion_efficiency_wind_child2_to_child1 = 0.0 - inner_accretion_efficiency_mass_transfer = outer_accretion_efficiency_mass_transfer = 0.0 + inner_mass_transfer_rate = outer_mass_transfer_rate = 0.0 | units.MSun / units.yr + inner_accretion_efficiency_wind_child1_to_child2 = ( + inner_accretion_efficiency_wind_child2_to_child1 + ) = 0.0 + outer_accretion_efficiency_wind_child1_to_child2 = ( + outer_accretion_efficiency_wind_child2_to_child1 + ) = 0.0 + inner_accretion_efficiency_mass_transfer = ( + outer_accretion_efficiency_mass_transfer + ) = 0.0 inner_specific_AM_loss_mass_transfer = outer_specific_AM_loss_mass_transfer = 0.0 if parameters.include_inner_wind_terms == True: try: wind_mass_loss_rate_star1 = star1.wind_mass_loss_rate wind_mass_loss_rate_star2 = star2.wind_mass_loss_rate - inner_accretion_efficiency_wind_child1_to_child2 = inner_binary.accretion_efficiency_wind_child1_to_child2 - inner_accretion_efficiency_wind_child2_to_child1 = inner_binary.accretion_efficiency_wind_child2_to_child1 + inner_accretion_efficiency_wind_child1_to_child2 = ( + inner_binary.accretion_efficiency_wind_child1_to_child2 + ) + inner_accretion_efficiency_wind_child2_to_child1 = ( + inner_binary.accretion_efficiency_wind_child2_to_child1 + ) except AttributeError: - sys.exit("SecularTriple -- more attributes required for inner wind! exiting") + sys.exit( + "SecularTriple -- more attributes required for inner wind! exiting" + ) if parameters.include_outer_wind_terms == True: try: wind_mass_loss_rate_star3 = star3.wind_mass_loss_rate inner_mass_transfer_rate = inner_binary.mass_transfer_rate - outer_accretion_efficiency_wind_child1_to_child2 = outer_binary.accretion_efficiency_wind_child1_to_child2 - outer_accretion_efficiency_wind_child2_to_child1 = outer_binary.accretion_efficiency_wind_child2_to_child1 - + outer_accretion_efficiency_wind_child1_to_child2 = ( + outer_binary.accretion_efficiency_wind_child1_to_child2 + ) + outer_accretion_efficiency_wind_child2_to_child1 = ( + outer_binary.accretion_efficiency_wind_child2_to_child1 + ) + except AttributeError: - sys.exit("SecularTriple -- more attributes required for outer wind! exiting") + sys.exit( + "SecularTriple -- more attributes required for outer wind! exiting" + ) if parameters.include_inner_RLOF_terms == True: try: star1_is_donor = star1.is_donor star2_is_donor = star2.is_donor inner_mass_transfer_rate = inner_binary.mass_transfer_rate - inner_accretion_efficiency_mass_transfer = inner_binary.accretion_efficiency_mass_transfer - inner_specific_AM_loss_mass_transfer = inner_binary.specific_AM_loss_mass_transfer + inner_accretion_efficiency_mass_transfer = ( + inner_binary.accretion_efficiency_mass_transfer + ) + inner_specific_AM_loss_mass_transfer = ( + inner_binary.specific_AM_loss_mass_transfer + ) except AttributeError: - sys.exit("SecularTriple -- more attributes required for inner RLOF! exiting") + sys.exit( + "SecularTriple -- more attributes required for inner RLOF! exiting" + ) if parameters.include_outer_RLOF_terms == True: try: - star3_is_donor = star3.is_donor + star3_is_donor = star3.is_donor outer_mass_transfer_rate = outer_binary.mass_transfer_rate - outer_accretion_efficiency_mass_transfer = outer_binary.accretion_efficiency_mass_transfer - outer_specific_AM_loss_mass_transfer = outer_binary.specific_AM_loss_mass_transfer + outer_accretion_efficiency_mass_transfer = ( + outer_binary.accretion_efficiency_mass_transfer + ) + outer_specific_AM_loss_mass_transfer = ( + outer_binary.specific_AM_loss_mass_transfer + ) except AttributeError: - sys.exit("SecularTriple -- more attributes required for outer RLOF! exiting") + sys.exit( + "SecularTriple -- more attributes required for outer RLOF! exiting" + ) ### RLOF checks ### - spin_angular_frequency1 = spin_angular_frequency2 = spin_angular_frequency3 = 0.0 | 1.0/units.s + spin_angular_frequency1 = spin_angular_frequency2 = spin_angular_frequency3 = ( + 0.0 | 1.0 / units.s + ) gyration_radius_star1 = gyration_radius_star2 = gyration_radius_star3 = 0.0 if parameters.check_for_inner_RLOF == True: try: spin_angular_frequency1 = star1.spin_angular_frequency spin_angular_frequency2 = star2.spin_angular_frequency except AttributeError: - sys.exit( "SecularTriple -- more attributes required for inner RLOF check! exiting") + sys.exit( + "SecularTriple -- more attributes required for inner RLOF check! exiting" + ) if parameters.check_for_outer_RLOF == True: try: spin_angular_frequency3 = star3.spin_angular_frequency except AttributeError: - sys.exit("SecularTriple -- more attributes required for outer RLOF check! exiting") + sys.exit( + "SecularTriple -- more attributes required for outer RLOF check! exiting" + ) ### magnetic braking ### if parameters.include_magnetic_braking_terms == True: @@ -2145,18 +3158,30 @@ def extract_data_and_give_args(self,triple,inner_binary,outer_binary,star1,star2 wind_mass_loss_rate_star2 = star2.wind_mass_loss_rate wind_mass_loss_rate_star3 = star3.wind_mass_loss_rate gyration_radius_star1 = star1.gyration_radius - gyration_radius_star2 = star2.gyration_radius - gyration_radius_star3 = star3.gyration_radius + gyration_radius_star2 = star2.gyration_radius + gyration_radius_star3 = star3.gyration_radius except AttributeError: - sys.exit("SecularTriple -- more attributes required for magnetic braking terms! exiting") + sys.exit( + "SecularTriple -- more attributes required for magnetic braking terms! exiting" + ) ### spin-radius-mass coupling ### - moment_of_inertia_star1 = moment_of_inertia_star2 = moment_of_inertia_star3 = 0.0 | units.MSun*units.RSun**2 - moment_of_inertia_dot_star1 = moment_of_inertia_dot_star2 = moment_of_inertia_dot_star3 = 0.0 | units.MSun*units.RSun**2/units.yr -# moment_of_inertia_star1 = moment_of_inertia_star2 = moment_of_inertia_star3 = 1.0e8 | units.MSun*units.RSun**2 -# moment_of_inertia_dot_star1 = moment_of_inertia_dot_star2 = moment_of_inertia_dot_star3 = 0.0 | units.MSun*units.RSun**2/units.yr - inner_spin_angular_momentum_wind_accretion_efficiency_child1_to_child2 = inner_spin_angular_momentum_wind_accretion_efficiency_child2_to_child1 = 0.0 - if parameters.include_spin_radius_mass_coupling_terms_star1 == True or parameters.include_spin_radius_mass_coupling_terms_star2 == True or parameters.include_spin_radius_mass_coupling_terms_star3 == True: + moment_of_inertia_star1 = moment_of_inertia_star2 = moment_of_inertia_star3 = ( + 0.0 | units.MSun * units.RSun**2 + ) + moment_of_inertia_dot_star1 = moment_of_inertia_dot_star2 = ( + moment_of_inertia_dot_star3 + ) = (0.0 | units.MSun * units.RSun**2 / units.yr) + # moment_of_inertia_star1 = moment_of_inertia_star2 = moment_of_inertia_star3 = 1.0e8 | units.MSun*units.RSun**2 + # moment_of_inertia_dot_star1 = moment_of_inertia_dot_star2 = moment_of_inertia_dot_star3 = 0.0 | units.MSun*units.RSun**2/units.yr + inner_spin_angular_momentum_wind_accretion_efficiency_child1_to_child2 = ( + inner_spin_angular_momentum_wind_accretion_efficiency_child2_to_child1 + ) = 0.0 + if ( + parameters.include_spin_radius_mass_coupling_terms_star1 == True + or parameters.include_spin_radius_mass_coupling_terms_star2 == True + or parameters.include_spin_radius_mass_coupling_terms_star3 == True + ): try: spin_angular_frequency1 = star1.spin_angular_frequency spin_angular_frequency2 = star2.spin_angular_frequency @@ -2173,20 +3198,25 @@ def extract_data_and_give_args(self,triple,inner_binary,outer_binary,star1,star2 moment_of_inertia_dot_star1 = star1.time_derivative_of_moment_of_inertia moment_of_inertia_dot_star2 = star2.time_derivative_of_moment_of_inertia moment_of_inertia_dot_star3 = star3.time_derivative_of_moment_of_inertia -# inner_spin_angular_momentum_wind_accretion_efficiency_child1_to_child2 = inner_binary.spin_angular_momentum_wind_accretion_efficiency_child1_to_child2 -# inner_spin_angular_momentum_wind_accretion_efficiency_child2_to_child1 = inner_binary.spin_angular_momentum_wind_accretion_efficiency_child2_to_child1 + # inner_spin_angular_momentum_wind_accretion_efficiency_child1_to_child2 = inner_binary.spin_angular_momentum_wind_accretion_efficiency_child1_to_child2 + # inner_spin_angular_momentum_wind_accretion_efficiency_child2_to_child1 = inner_binary.spin_angular_momentum_wind_accretion_efficiency_child2_to_child1 except AttributeError: - sys.exit( "SecularTriple -- more attributes required for spin-radius-mass coupling terms! exiting") - + sys.exit( + "SecularTriple -- more attributes required for spin-radius-mass coupling terms! exiting" + ) ### tides ### stellar_type1 = stellar_type2 = stellar_type3 = 0 | units.stellar_type - m1_convective_envelope = m2_convective_envelope = m3_convective_envelope = 0.0 | units.MSun - R1_convective_envelope = R2_convective_envelope = R3_convective_envelope = 0.0 | units.RSun + m1_convective_envelope = m2_convective_envelope = m3_convective_envelope = ( + 0.0 | units.MSun + ) + R1_convective_envelope = R2_convective_envelope = R3_convective_envelope = ( + 0.0 | units.RSun + ) luminosity_star1 = luminosity_star2 = luminosity_star3 = 0.0 | units.LSun AMC_star1 = AMC_star2 = AMC_star3 = 0.0 -# k_div_T_tides_star1 = k_div_T_tides_star2 = k_div_T_tides_star3 = 0.0 | 1.0/units.s - + # k_div_T_tides_star1 = k_div_T_tides_star2 = k_div_T_tides_star3 = 0.0 | 1.0/units.s + if parameters.include_inner_tidal_terms == True: try: stellar_type1 = star1.stellar_type @@ -2197,7 +3227,7 @@ def extract_data_and_give_args(self,triple,inner_binary,outer_binary,star1,star2 m3_convective_envelope = star3.convective_envelope_mass R1_convective_envelope = star1.convective_envelope_radius R2_convective_envelope = star2.convective_envelope_radius - R3_convective_envelope = star3.convective_envelope_radius + R3_convective_envelope = star3.convective_envelope_radius luminosity_star1 = star1.luminosity luminosity_star2 = star2.luminosity luminosity_star3 = star3.luminosity @@ -2212,59 +3242,122 @@ def extract_data_and_give_args(self,triple,inner_binary,outer_binary,star1,star2 spin_angular_frequency3 = star3.spin_angular_frequency ### TODO: implement checks for unphysical input values ### - - + except AttributeError: sys.exit("SecularTriple -- more attributes required for tides! exiting") - if (m1_convective_envelope.value_in(unit_m)<0): - sys.exit('SecularTriple -- m1_convective_envelope must be positive! exiting') - if (m2_convective_envelope.value_in(unit_m)<0): - sys.exit('SecularTriple -- m2_convective_envelope must be positive! exiting') - if (m3_convective_envelope.value_in(unit_m)<0): - sys.exit('SecularTriple -- m3_convective_envelope must be positive! exiting') + if m1_convective_envelope.value_in(unit_m) < 0: + sys.exit( + "SecularTriple -- m1_convective_envelope must be positive! exiting" + ) + if m2_convective_envelope.value_in(unit_m) < 0: + sys.exit( + "SecularTriple -- m2_convective_envelope must be positive! exiting" + ) + if m3_convective_envelope.value_in(unit_m) < 0: + sys.exit( + "SecularTriple -- m3_convective_envelope must be positive! exiting" + ) - if (R1_convective_envelope.value_in(unit_l)<0): - sys.exit('SecularTriple -- R1_convective_envelope must be positive! exiting') - if (R2_convective_envelope.value_in(unit_l)<0): - sys.exit('SecularTriple -- R2_convective_envelope must be positive! exiting') - if (R3_convective_envelope.value_in(unit_l)<0): - sys.exit('SecularTriple -- R3_convective_envelope must be positive! exiting') + if R1_convective_envelope.value_in(unit_l) < 0: + sys.exit( + "SecularTriple -- R1_convective_envelope must be positive! exiting" + ) + if R2_convective_envelope.value_in(unit_l) < 0: + sys.exit( + "SecularTriple -- R2_convective_envelope must be positive! exiting" + ) + if R3_convective_envelope.value_in(unit_l) < 0: + sys.exit( + "SecularTriple -- R3_convective_envelope must be positive! exiting" + ) if self.parameters.verbose == True: - print( 'SecularTriple -- initialization; a_in/AU=',a_in.value_in(units.AU),'; e_in=',e_in,'e_out=',e_out,' rel_INCL = ',INCL_in) - - if ((star1.is_donor == False) and (star2.is_donor == False)): - inner_mass_transfer_rate = 0.0 | units.MSun/units.yr - - if (star3.is_donor == False): - outer_mass_transfer_rate = 0.0 | units.MSun/units.yr - - args = [stellar_type1,stellar_type2,stellar_type3, - m1,m2,m3, - m1_convective_envelope,m2_convective_envelope,m3_convective_envelope, - R1,R2,R3, - R1_convective_envelope,R2_convective_envelope,R3_convective_envelope, - luminosity_star1,luminosity_star2,luminosity_star3, - spin_angular_frequency1,spin_angular_frequency2,spin_angular_frequency3, - AMC_star1,AMC_star2,AMC_star3, - gyration_radius_star1,gyration_radius_star2,gyration_radius_star3, - moment_of_inertia_star1,moment_of_inertia_star2,moment_of_inertia_star3, - moment_of_inertia_dot_star1,moment_of_inertia_dot_star2,moment_of_inertia_dot_star3, -# k_div_T_tides_star1,k_div_T_tides_star2,k_div_T_tides_star3, - a_in,a_out, - e_in,e_out, - INCL_in,INCL_out, - AP_in,AP_out,LAN_in,LAN_out, - star1_is_donor,star2_is_donor,star3_is_donor, - wind_mass_loss_rate_star1,wind_mass_loss_rate_star2,wind_mass_loss_rate_star3, - time_derivative_of_radius_star1,time_derivative_of_radius_star2,time_derivative_of_radius_star3, - inner_mass_transfer_rate,outer_mass_transfer_rate, - inner_accretion_efficiency_wind_child1_to_child2,inner_accretion_efficiency_wind_child2_to_child1, - outer_accretion_efficiency_wind_child1_to_child2,outer_accretion_efficiency_wind_child2_to_child1, - inner_accretion_efficiency_mass_transfer,outer_accretion_efficiency_mass_transfer, - inner_specific_AM_loss_mass_transfer,outer_specific_AM_loss_mass_transfer, - inner_spin_angular_momentum_wind_accretion_efficiency_child1_to_child2,inner_spin_angular_momentum_wind_accretion_efficiency_child2_to_child1, - self.model_time,self.time_step] ### NOTE: only time_step is used at the moment - - return args,skip_integration + print( + "SecularTriple -- initialization; a_in/AU=", + a_in.value_in(units.AU), + "; e_in=", + e_in, + "e_out=", + e_out, + " rel_INCL = ", + INCL_in, + ) + + if (star1.is_donor == False) and (star2.is_donor == False): + inner_mass_transfer_rate = 0.0 | units.MSun / units.yr + + if star3.is_donor == False: + outer_mass_transfer_rate = 0.0 | units.MSun / units.yr + + args = [ + stellar_type1, + stellar_type2, + stellar_type3, + m1, + m2, + m3, + m1_convective_envelope, + m2_convective_envelope, + m3_convective_envelope, + R1, + R2, + R3, + R1_convective_envelope, + R2_convective_envelope, + R3_convective_envelope, + luminosity_star1, + luminosity_star2, + luminosity_star3, + spin_angular_frequency1, + spin_angular_frequency2, + spin_angular_frequency3, + AMC_star1, + AMC_star2, + AMC_star3, + gyration_radius_star1, + gyration_radius_star2, + gyration_radius_star3, + moment_of_inertia_star1, + moment_of_inertia_star2, + moment_of_inertia_star3, + moment_of_inertia_dot_star1, + moment_of_inertia_dot_star2, + moment_of_inertia_dot_star3, + # k_div_T_tides_star1,k_div_T_tides_star2,k_div_T_tides_star3, + a_in, + a_out, + e_in, + e_out, + INCL_in, + INCL_out, + AP_in, + AP_out, + LAN_in, + LAN_out, + star1_is_donor, + star2_is_donor, + star3_is_donor, + wind_mass_loss_rate_star1, + wind_mass_loss_rate_star2, + wind_mass_loss_rate_star3, + time_derivative_of_radius_star1, + time_derivative_of_radius_star2, + time_derivative_of_radius_star3, + inner_mass_transfer_rate, + outer_mass_transfer_rate, + inner_accretion_efficiency_wind_child1_to_child2, + inner_accretion_efficiency_wind_child2_to_child1, + outer_accretion_efficiency_wind_child1_to_child2, + outer_accretion_efficiency_wind_child2_to_child1, + inner_accretion_efficiency_mass_transfer, + outer_accretion_efficiency_mass_transfer, + inner_specific_AM_loss_mass_transfer, + outer_specific_AM_loss_mass_transfer, + inner_spin_angular_momentum_wind_accretion_efficiency_child1_to_child2, + inner_spin_angular_momentum_wind_accretion_efficiency_child2_to_child1, + self.model_time, + self.time_step, + ] ### NOTE: only time_step is used at the moment + + return args, skip_integration diff --git a/src/tres/seculartriple_TPS/tidal_friction_constant.py b/src/tres/seculartriple_TPS/tidal_friction_constant.py index c56dfd1..5d0e662 100644 --- a/src/tres/seculartriple_TPS/tidal_friction_constant.py +++ b/src/tres/seculartriple_TPS/tidal_friction_constant.py @@ -1,4 +1,4 @@ -#not used - file should be removed +# not used - file should be removed """ Routine that calculates the ratio k/T for tidal friction, where k is the apsidal motion constant and T the tidal friction time scale as they appear in Hut (1981; 1981A&A....99..126H). The entire routine has been copied directly from c-code that is part of binary_c and converted to Python. @@ -7,102 +7,153 @@ Adrian Hamers 16-06-2014 """ -#define USE_RADIATIVE_DAMPING (((stardata->star[star_number].stellar_type==MAIN_SEQUENCE)&&(MORE_OR_EQUAL(stardata->star[star_number].mass,1.25)))||(stardata->star[star_number].stellar_type==CHeB)||(stardata->star[star_number].stellar_type==HeMS)) +# define USE_RADIATIVE_DAMPING (((stardata->star[star_number].stellar_type==MAIN_SEQUENCE)&&(MORE_OR_EQUAL(stardata->star[star_number].mass,1.25)))||(stardata->star[star_number].stellar_type==CHeB)||(stardata->star[star_number].stellar_type==HeMS)) -#define USE_CONVECTIVE_DAMPING (stardata->star[star_number].stellar_typestar[star_number].stellar_type= MINIMUM_MASS_FOR_RADIATIVE_DAMPING_MSUN): +def check_for_radiative_damping(stellar_type, mass): + if ( + stellar_type == MAIN_SEQUENCE + and mass.value_in(units.MSun) >= MINIMUM_MASS_FOR_RADIATIVE_DAMPING_MSUN + ): return True - elif (stellar_type == CHeB or stellar_type == HeMS): + elif stellar_type == CHeB or stellar_type == HeMS: return True else: return False - -def check_for_convective_damping(stellar_type): + + +def check_for_convective_damping(stellar_type): if stellar_type < HeWD or stellar_type == PREMS: return True else: return False -def tidal_friction_constant(stellar_type,mass,companion_mass,semimajor_axis,radius,convective_envelope_mass,convective_envelope_radius,luminosity,spin_angular_frequency, gyration_radius, amc): - - USE_RADIATIVE_DAMPING = check_for_radiative_damping(stellar_type,mass) + +def tidal_friction_constant( + stellar_type, + mass, + companion_mass, + semimajor_axis, + radius, + convective_envelope_mass, + convective_envelope_radius, + luminosity, + spin_angular_frequency, + gyration_radius, + amc, +): + + USE_RADIATIVE_DAMPING = check_for_radiative_damping(stellar_type, mass) USE_CONVECTIVE_DAMPING = check_for_convective_damping(stellar_type) - - if USE_RADIATIVE_DAMPING: ### radiative damping ### - E2 = 1.592e-09*pow(mass.value_in(units.MSun),2.84) ### Hurley prescription; Zahn, 1977, A&A, 57, 383 and 1975, A&A, 41, 329. ### - - k_div_T_tides = E2*pow(1.0 + companion_mass/mass,5.0/6.0)*radius*numpy.sqrt(constants.G*mass/(semimajor_axis**5)) -# print('radiative damping', mass, k_div_T_tides) + + if USE_RADIATIVE_DAMPING: ### radiative damping ### + E2 = 1.592e-09 * pow( + mass.value_in(units.MSun), 2.84 + ) ### Hurley prescription; Zahn, 1977, A&A, 57, 383 and 1975, A&A, 41, 329. ### + + k_div_T_tides = ( + E2 + * pow(1.0 + companion_mass / mass, 5.0 / 6.0) + * radius + * numpy.sqrt(constants.G * mass / (semimajor_axis**5)) + ) + # print('radiative damping', mass, k_div_T_tides) return k_div_T_tides - -# kTradiative_damping = 1.9782e+04*sqrt((mass.value_in(units.MSun)*(radius.value_in(units.RSun))**2))/((semimajor_axis.value_in(units.AU))**5))*E2*pow(1.0+companion_mass/mass,5.0/6.0) -# kTradiative_damping = kTradiative_damping/YEAR_LENGTH_IN_SECONDS; /* This converts (k/T) to units of s^-1 */ - - elif USE_CONVECTIVE_DAMPING: ### convective damping ### - P_orb = 2.0*numpy.pi*numpy.sqrt((semimajor_axis**3)/(constants.G*(mass + companion_mass))) - if spin_angular_frequency.value_in(1.0/units.s) == 0.0: + + # kTradiative_damping = 1.9782e+04*sqrt((mass.value_in(units.MSun)*(radius.value_in(units.RSun))**2))/((semimajor_axis.value_in(units.AU))**5))*E2*pow(1.0+companion_mass/mass,5.0/6.0) + # kTradiative_damping = kTradiative_damping/YEAR_LENGTH_IN_SECONDS; /* This converts (k/T) to units of s^-1 */ + + elif USE_CONVECTIVE_DAMPING: ### convective damping ### + P_orb = ( + 2.0 + * numpy.pi + * numpy.sqrt((semimajor_axis**3) / (constants.G * (mass + companion_mass))) + ) + if spin_angular_frequency.value_in(1.0 / units.s) == 0.0: P_tid = P_orb else: - P_spin = 2.0*numpy.pi/spin_angular_frequency - P_tid_s = 1.0/( 1e-10 + numpy.fabs( 1.0/(P_orb.value_in(units.s)) - 1.0/(P_spin.value_in(units.s)) ) ) + P_spin = 2.0 * numpy.pi / spin_angular_frequency + P_tid_s = 1.0 / ( + 1e-10 + + numpy.fabs( + 1.0 / (P_orb.value_in(units.s)) - 1.0 / (P_spin.value_in(units.s)) + ) + ) P_tid = P_tid_s | units.s - tau_convective = pow( (convective_envelope_mass*convective_envelope_radius*(radius - (1.0/2.0)*convective_envelope_radius))/(3.0*luminosity), 1.0/3.0) -# print 'tau',envelope_mass,envelope_mass*envelope_radius*(radius - (1.0/2.0)*envelope_radius)/(3.0*luminosity) - - #print 'tau convective',tau_convective - f_convective = (P_tid/(2.0*tau_convective))**2 - - f_convective = numpy.amin([1.0,f_convective]) - - k_div_T_tides = (2.0/21.0)*(f_convective/tau_convective)*(convective_envelope_mass/mass) -# print('convective damping', mass, k_div_T_tides) + tau_convective = pow( + ( + convective_envelope_mass + * convective_envelope_radius + * (radius - (1.0 / 2.0) * convective_envelope_radius) + ) + / (3.0 * luminosity), + 1.0 / 3.0, + ) + # print 'tau',envelope_mass,envelope_mass*envelope_radius*(radius - (1.0/2.0)*envelope_radius)/(3.0*luminosity) + + # print 'tau convective',tau_convective + f_convective = (P_tid / (2.0 * tau_convective)) ** 2 + + f_convective = numpy.amin([1.0, f_convective]) + + k_div_T_tides = ( + (2.0 / 21.0) + * (f_convective / tau_convective) + * (convective_envelope_mass / mass) + ) + # print('convective damping', mass, k_div_T_tides) return k_div_T_tides - elif stellar_type==NS or stellar_type==BH: + elif stellar_type == NS or stellar_type == BH: ### no tides for NS or BH - k_div_T_tides = 0 -# print('ns/bh tides', k_div_T_tides, stellar_type) - return k_div_T_tides - elif stellar_type==PLANET or stellar_type==BD: #based on Fabrycky & Tremaine 2007, appendix - T_viscous = 0.001|units.yr - return amc/T_viscous - else: ### degenerate damping -- 1984MNRAS.207..433C ### - tau_degenerate = 1.3e7 | units.yr - k_div_T_tides = (1.0/(3.0*tau_degenerate))*gyration_radius**2*pow(luminosity.value_in(units.LSun)/mass.value_in(units.MSun),5.0/7.0) -# print('degenerate damping', k_div_T_tides) -# print('degenerate damping ', k_div_T_tides, gyration_radius_star1, luminosity.value_in(units.LSun),mass.value_in(units.MSun)) + k_div_T_tides = 0 + # print('ns/bh tides', k_div_T_tides, stellar_type) + return k_div_T_tides + elif ( + stellar_type == PLANET or stellar_type == BD + ): # based on Fabrycky & Tremaine 2007, appendix + T_viscous = 0.001 | units.yr + return amc / T_viscous + else: ### degenerate damping -- 1984MNRAS.207..433C ### + tau_degenerate = 1.3e7 | units.yr + k_div_T_tides = ( + (1.0 / (3.0 * tau_degenerate)) + * gyration_radius**2 + * pow( + luminosity.value_in(units.LSun) / mass.value_in(units.MSun), 5.0 / 7.0 + ) + ) + # print('degenerate damping', k_div_T_tides) + # print('degenerate damping ', k_div_T_tides, gyration_radius_star1, luminosity.value_in(units.LSun),mass.value_in(units.MSun)) return k_div_T_tides From b9d409dd8c5908290d325053aba6ff8b305e5cea Mon Sep 17 00:00:00 2001 From: Steven Rieder Date: Mon, 4 Nov 2024 13:51:48 +0100 Subject: [PATCH 19/30] Add alias to follow AMUSE standard for community codes --- src/tres/seculartriple_TPS/__init__.py | 1 + src/tres/seculartriple_TPS/interface.py | 2 ++ 2 files changed, 3 insertions(+) diff --git a/src/tres/seculartriple_TPS/__init__.py b/src/tres/seculartriple_TPS/__init__.py index e69de29..4d10e0c 100644 --- a/src/tres/seculartriple_TPS/__init__.py +++ b/src/tres/seculartriple_TPS/__init__.py @@ -0,0 +1 @@ +from .interface import Seculartriple diff --git a/src/tres/seculartriple_TPS/interface.py b/src/tres/seculartriple_TPS/interface.py index 8010a20..74aa926 100644 --- a/src/tres/seculartriple_TPS/interface.py +++ b/src/tres/seculartriple_TPS/interface.py @@ -3361,3 +3361,5 @@ def extract_data_and_give_args( ] ### NOTE: only time_step is used at the moment return args, skip_integration + +Seculartriple = SecularTriple From bd718b9fd5c5b6dfdd01ab2c7bd89e72770af641 Mon Sep 17 00:00:00 2001 From: Steven Rieder Date: Tue, 5 Nov 2024 12:03:17 +0100 Subject: [PATCH 20/30] move seculartriple to amuse-style location --- .../seculartriple_TPS => amuse/community/seculartriple}/Makefile | 0 .../community/seculartriple}/Makefile_old | 0 .../community/seculartriple}/__init__.py | 0 .../community/seculartriple}/interface.py | 0 .../community/seculartriple}/src/ODE_system.c | 0 .../community/seculartriple}/src/ODE_system.h | 0 .../community/seculartriple}/src/cvode/cvode.c | 0 .../community/seculartriple}/src/cvode/cvode.h | 0 .../community/seculartriple}/src/cvode/cvode_band.c | 0 .../community/seculartriple}/src/cvode/cvode_band.h | 0 .../community/seculartriple}/src/cvode/cvode_bandpre.h | 0 .../community/seculartriple}/src/cvode/cvode_dense.c | 0 .../community/seculartriple}/src/cvode/cvode_dense.h | 0 .../community/seculartriple}/src/cvode/cvode_diag.c | 0 .../community/seculartriple}/src/cvode/cvode_diag.h | 0 .../community/seculartriple}/src/cvode/cvode_diag_impl.h | 0 .../community/seculartriple}/src/cvode/cvode_direct.c | 0 .../community/seculartriple}/src/cvode/cvode_direct.h | 0 .../community/seculartriple}/src/cvode/cvode_direct_impl.h | 0 .../community/seculartriple}/src/cvode/cvode_impl.h | 0 .../community/seculartriple}/src/cvode/cvode_io.c | 0 .../community/seculartriple}/src/cvode/cvode_spbcgs.c | 0 .../community/seculartriple}/src/cvode/cvode_spbcgs.h | 0 .../community/seculartriple}/src/cvode/cvode_spgmr.c | 0 .../community/seculartriple}/src/cvode/cvode_spgmr.h | 0 .../community/seculartriple}/src/cvode/cvode_spils.c | 0 .../community/seculartriple}/src/cvode/cvode_spils.h | 0 .../community/seculartriple}/src/cvode/cvode_spils_impl.h | 0 .../community/seculartriple}/src/cvode/cvode_sptfqmr.c | 0 .../community/seculartriple}/src/cvode/cvode_sptfqmr.h | 0 .../community/seculartriple}/src/cvode/nvector_serial.c | 0 .../community/seculartriple}/src/cvode/nvector_serial.h | 0 .../community/seculartriple}/src/cvode/sundials_band.c | 0 .../community/seculartriple}/src/cvode/sundials_band.h | 0 .../community/seculartriple}/src/cvode/sundials_config.h | 0 .../community/seculartriple}/src/cvode/sundials_dense.c | 0 .../community/seculartriple}/src/cvode/sundials_dense.h | 0 .../community/seculartriple}/src/cvode/sundials_direct.c | 0 .../community/seculartriple}/src/cvode/sundials_direct.h | 0 .../community/seculartriple}/src/cvode/sundials_iterative.c | 0 .../community/seculartriple}/src/cvode/sundials_iterative.h | 0 .../community/seculartriple}/src/cvode/sundials_math.c | 0 .../community/seculartriple}/src/cvode/sundials_math.h | 0 .../community/seculartriple}/src/cvode/sundials_nvector.c | 0 .../community/seculartriple}/src/cvode/sundials_nvector.h | 0 .../community/seculartriple}/src/cvode/sundials_spbcgs.c | 0 .../community/seculartriple}/src/cvode/sundials_spbcgs.h | 0 .../community/seculartriple}/src/cvode/sundials_spgmr.c | 0 .../community/seculartriple}/src/cvode/sundials_spgmr.h | 0 .../community/seculartriple}/src/cvode/sundials_sptfqmr.c | 0 .../community/seculartriple}/src/cvode/sundials_sptfqmr.h | 0 .../community/seculartriple}/src/cvode/sundials_types.h | 0 .../community/seculartriple}/src/helper_routines.c | 0 .../community/seculartriple}/src/helper_routines.h | 0 .../community/seculartriple}/src/main_code.c | 0 .../community/seculartriple}/src/main_code.h | 0 .../community/seculartriple}/src/tidal_friction_parameters.c | 0 .../community/seculartriple}/src/tidal_friction_parameters.h | 0 .../community/seculartriple}/tidal_friction_constant.py | 0 59 files changed, 0 insertions(+), 0 deletions(-) rename src/{tres/seculartriple_TPS => amuse/community/seculartriple}/Makefile (100%) rename src/{tres/seculartriple_TPS => amuse/community/seculartriple}/Makefile_old (100%) rename src/{tres/seculartriple_TPS => amuse/community/seculartriple}/__init__.py (100%) rename src/{tres/seculartriple_TPS => amuse/community/seculartriple}/interface.py (100%) rename src/{tres/seculartriple_TPS => amuse/community/seculartriple}/src/ODE_system.c (100%) rename src/{tres/seculartriple_TPS => amuse/community/seculartriple}/src/ODE_system.h (100%) rename src/{tres/seculartriple_TPS => amuse/community/seculartriple}/src/cvode/cvode.c (100%) rename src/{tres/seculartriple_TPS => amuse/community/seculartriple}/src/cvode/cvode.h (100%) rename src/{tres/seculartriple_TPS => amuse/community/seculartriple}/src/cvode/cvode_band.c (100%) rename src/{tres/seculartriple_TPS => amuse/community/seculartriple}/src/cvode/cvode_band.h (100%) rename src/{tres/seculartriple_TPS => amuse/community/seculartriple}/src/cvode/cvode_bandpre.h (100%) rename src/{tres/seculartriple_TPS => amuse/community/seculartriple}/src/cvode/cvode_dense.c (100%) rename src/{tres/seculartriple_TPS => amuse/community/seculartriple}/src/cvode/cvode_dense.h (100%) rename src/{tres/seculartriple_TPS => amuse/community/seculartriple}/src/cvode/cvode_diag.c (100%) rename src/{tres/seculartriple_TPS => amuse/community/seculartriple}/src/cvode/cvode_diag.h (100%) rename src/{tres/seculartriple_TPS => amuse/community/seculartriple}/src/cvode/cvode_diag_impl.h (100%) rename src/{tres/seculartriple_TPS => amuse/community/seculartriple}/src/cvode/cvode_direct.c (100%) rename src/{tres/seculartriple_TPS => amuse/community/seculartriple}/src/cvode/cvode_direct.h (100%) rename src/{tres/seculartriple_TPS => amuse/community/seculartriple}/src/cvode/cvode_direct_impl.h (100%) rename src/{tres/seculartriple_TPS => amuse/community/seculartriple}/src/cvode/cvode_impl.h (100%) rename src/{tres/seculartriple_TPS => amuse/community/seculartriple}/src/cvode/cvode_io.c (100%) rename src/{tres/seculartriple_TPS => amuse/community/seculartriple}/src/cvode/cvode_spbcgs.c (100%) rename src/{tres/seculartriple_TPS => amuse/community/seculartriple}/src/cvode/cvode_spbcgs.h (100%) rename src/{tres/seculartriple_TPS => amuse/community/seculartriple}/src/cvode/cvode_spgmr.c (100%) rename src/{tres/seculartriple_TPS => amuse/community/seculartriple}/src/cvode/cvode_spgmr.h (100%) rename src/{tres/seculartriple_TPS => amuse/community/seculartriple}/src/cvode/cvode_spils.c (100%) rename src/{tres/seculartriple_TPS => amuse/community/seculartriple}/src/cvode/cvode_spils.h (100%) rename src/{tres/seculartriple_TPS => amuse/community/seculartriple}/src/cvode/cvode_spils_impl.h (100%) rename src/{tres/seculartriple_TPS => amuse/community/seculartriple}/src/cvode/cvode_sptfqmr.c (100%) rename src/{tres/seculartriple_TPS => amuse/community/seculartriple}/src/cvode/cvode_sptfqmr.h (100%) rename src/{tres/seculartriple_TPS => amuse/community/seculartriple}/src/cvode/nvector_serial.c (100%) rename src/{tres/seculartriple_TPS => amuse/community/seculartriple}/src/cvode/nvector_serial.h (100%) rename src/{tres/seculartriple_TPS => amuse/community/seculartriple}/src/cvode/sundials_band.c (100%) rename src/{tres/seculartriple_TPS => amuse/community/seculartriple}/src/cvode/sundials_band.h (100%) rename src/{tres/seculartriple_TPS => amuse/community/seculartriple}/src/cvode/sundials_config.h (100%) rename src/{tres/seculartriple_TPS => amuse/community/seculartriple}/src/cvode/sundials_dense.c (100%) rename src/{tres/seculartriple_TPS => amuse/community/seculartriple}/src/cvode/sundials_dense.h (100%) rename src/{tres/seculartriple_TPS => amuse/community/seculartriple}/src/cvode/sundials_direct.c (100%) rename src/{tres/seculartriple_TPS => amuse/community/seculartriple}/src/cvode/sundials_direct.h (100%) rename src/{tres/seculartriple_TPS => amuse/community/seculartriple}/src/cvode/sundials_iterative.c (100%) rename src/{tres/seculartriple_TPS => amuse/community/seculartriple}/src/cvode/sundials_iterative.h (100%) rename src/{tres/seculartriple_TPS => amuse/community/seculartriple}/src/cvode/sundials_math.c (100%) rename src/{tres/seculartriple_TPS => amuse/community/seculartriple}/src/cvode/sundials_math.h (100%) rename src/{tres/seculartriple_TPS => amuse/community/seculartriple}/src/cvode/sundials_nvector.c (100%) rename src/{tres/seculartriple_TPS => amuse/community/seculartriple}/src/cvode/sundials_nvector.h (100%) rename src/{tres/seculartriple_TPS => amuse/community/seculartriple}/src/cvode/sundials_spbcgs.c (100%) rename src/{tres/seculartriple_TPS => amuse/community/seculartriple}/src/cvode/sundials_spbcgs.h (100%) rename src/{tres/seculartriple_TPS => amuse/community/seculartriple}/src/cvode/sundials_spgmr.c (100%) rename src/{tres/seculartriple_TPS => amuse/community/seculartriple}/src/cvode/sundials_spgmr.h (100%) rename src/{tres/seculartriple_TPS => amuse/community/seculartriple}/src/cvode/sundials_sptfqmr.c (100%) rename src/{tres/seculartriple_TPS => amuse/community/seculartriple}/src/cvode/sundials_sptfqmr.h (100%) rename src/{tres/seculartriple_TPS => amuse/community/seculartriple}/src/cvode/sundials_types.h (100%) rename src/{tres/seculartriple_TPS => amuse/community/seculartriple}/src/helper_routines.c (100%) rename src/{tres/seculartriple_TPS => amuse/community/seculartriple}/src/helper_routines.h (100%) rename src/{tres/seculartriple_TPS => amuse/community/seculartriple}/src/main_code.c (100%) rename src/{tres/seculartriple_TPS => amuse/community/seculartriple}/src/main_code.h (100%) rename src/{tres/seculartriple_TPS => amuse/community/seculartriple}/src/tidal_friction_parameters.c (100%) rename src/{tres/seculartriple_TPS => amuse/community/seculartriple}/src/tidal_friction_parameters.h (100%) rename src/{tres/seculartriple_TPS => amuse/community/seculartriple}/tidal_friction_constant.py (100%) diff --git a/src/tres/seculartriple_TPS/Makefile b/src/amuse/community/seculartriple/Makefile similarity index 100% rename from src/tres/seculartriple_TPS/Makefile rename to src/amuse/community/seculartriple/Makefile diff --git a/src/tres/seculartriple_TPS/Makefile_old b/src/amuse/community/seculartriple/Makefile_old similarity index 100% rename from src/tres/seculartriple_TPS/Makefile_old rename to src/amuse/community/seculartriple/Makefile_old diff --git a/src/tres/seculartriple_TPS/__init__.py b/src/amuse/community/seculartriple/__init__.py similarity index 100% rename from src/tres/seculartriple_TPS/__init__.py rename to src/amuse/community/seculartriple/__init__.py diff --git a/src/tres/seculartriple_TPS/interface.py b/src/amuse/community/seculartriple/interface.py similarity index 100% rename from src/tres/seculartriple_TPS/interface.py rename to src/amuse/community/seculartriple/interface.py diff --git a/src/tres/seculartriple_TPS/src/ODE_system.c b/src/amuse/community/seculartriple/src/ODE_system.c similarity index 100% rename from src/tres/seculartriple_TPS/src/ODE_system.c rename to src/amuse/community/seculartriple/src/ODE_system.c diff --git a/src/tres/seculartriple_TPS/src/ODE_system.h b/src/amuse/community/seculartriple/src/ODE_system.h similarity index 100% rename from src/tres/seculartriple_TPS/src/ODE_system.h rename to src/amuse/community/seculartriple/src/ODE_system.h diff --git a/src/tres/seculartriple_TPS/src/cvode/cvode.c b/src/amuse/community/seculartriple/src/cvode/cvode.c similarity index 100% rename from src/tres/seculartriple_TPS/src/cvode/cvode.c rename to src/amuse/community/seculartriple/src/cvode/cvode.c diff --git a/src/tres/seculartriple_TPS/src/cvode/cvode.h b/src/amuse/community/seculartriple/src/cvode/cvode.h similarity index 100% rename from src/tres/seculartriple_TPS/src/cvode/cvode.h rename to src/amuse/community/seculartriple/src/cvode/cvode.h diff --git a/src/tres/seculartriple_TPS/src/cvode/cvode_band.c b/src/amuse/community/seculartriple/src/cvode/cvode_band.c similarity index 100% rename from src/tres/seculartriple_TPS/src/cvode/cvode_band.c rename to src/amuse/community/seculartriple/src/cvode/cvode_band.c diff --git a/src/tres/seculartriple_TPS/src/cvode/cvode_band.h b/src/amuse/community/seculartriple/src/cvode/cvode_band.h similarity index 100% rename from src/tres/seculartriple_TPS/src/cvode/cvode_band.h rename to src/amuse/community/seculartriple/src/cvode/cvode_band.h diff --git a/src/tres/seculartriple_TPS/src/cvode/cvode_bandpre.h b/src/amuse/community/seculartriple/src/cvode/cvode_bandpre.h similarity index 100% rename from src/tres/seculartriple_TPS/src/cvode/cvode_bandpre.h rename to src/amuse/community/seculartriple/src/cvode/cvode_bandpre.h diff --git a/src/tres/seculartriple_TPS/src/cvode/cvode_dense.c b/src/amuse/community/seculartriple/src/cvode/cvode_dense.c similarity index 100% rename from src/tres/seculartriple_TPS/src/cvode/cvode_dense.c rename to src/amuse/community/seculartriple/src/cvode/cvode_dense.c diff --git a/src/tres/seculartriple_TPS/src/cvode/cvode_dense.h b/src/amuse/community/seculartriple/src/cvode/cvode_dense.h similarity index 100% rename from src/tres/seculartriple_TPS/src/cvode/cvode_dense.h rename to src/amuse/community/seculartriple/src/cvode/cvode_dense.h diff --git a/src/tres/seculartriple_TPS/src/cvode/cvode_diag.c b/src/amuse/community/seculartriple/src/cvode/cvode_diag.c similarity index 100% rename from src/tres/seculartriple_TPS/src/cvode/cvode_diag.c rename to src/amuse/community/seculartriple/src/cvode/cvode_diag.c diff --git a/src/tres/seculartriple_TPS/src/cvode/cvode_diag.h b/src/amuse/community/seculartriple/src/cvode/cvode_diag.h similarity index 100% rename from src/tres/seculartriple_TPS/src/cvode/cvode_diag.h rename to src/amuse/community/seculartriple/src/cvode/cvode_diag.h diff --git a/src/tres/seculartriple_TPS/src/cvode/cvode_diag_impl.h b/src/amuse/community/seculartriple/src/cvode/cvode_diag_impl.h similarity index 100% rename from src/tres/seculartriple_TPS/src/cvode/cvode_diag_impl.h rename to src/amuse/community/seculartriple/src/cvode/cvode_diag_impl.h diff --git a/src/tres/seculartriple_TPS/src/cvode/cvode_direct.c b/src/amuse/community/seculartriple/src/cvode/cvode_direct.c similarity index 100% rename from src/tres/seculartriple_TPS/src/cvode/cvode_direct.c rename to src/amuse/community/seculartriple/src/cvode/cvode_direct.c diff --git a/src/tres/seculartriple_TPS/src/cvode/cvode_direct.h b/src/amuse/community/seculartriple/src/cvode/cvode_direct.h similarity index 100% rename from src/tres/seculartriple_TPS/src/cvode/cvode_direct.h rename to src/amuse/community/seculartriple/src/cvode/cvode_direct.h diff --git a/src/tres/seculartriple_TPS/src/cvode/cvode_direct_impl.h b/src/amuse/community/seculartriple/src/cvode/cvode_direct_impl.h similarity index 100% rename from src/tres/seculartriple_TPS/src/cvode/cvode_direct_impl.h rename to src/amuse/community/seculartriple/src/cvode/cvode_direct_impl.h diff --git a/src/tres/seculartriple_TPS/src/cvode/cvode_impl.h b/src/amuse/community/seculartriple/src/cvode/cvode_impl.h similarity index 100% rename from src/tres/seculartriple_TPS/src/cvode/cvode_impl.h rename to src/amuse/community/seculartriple/src/cvode/cvode_impl.h diff --git a/src/tres/seculartriple_TPS/src/cvode/cvode_io.c b/src/amuse/community/seculartriple/src/cvode/cvode_io.c similarity index 100% rename from src/tres/seculartriple_TPS/src/cvode/cvode_io.c rename to src/amuse/community/seculartriple/src/cvode/cvode_io.c diff --git a/src/tres/seculartriple_TPS/src/cvode/cvode_spbcgs.c b/src/amuse/community/seculartriple/src/cvode/cvode_spbcgs.c similarity index 100% rename from src/tres/seculartriple_TPS/src/cvode/cvode_spbcgs.c rename to src/amuse/community/seculartriple/src/cvode/cvode_spbcgs.c diff --git a/src/tres/seculartriple_TPS/src/cvode/cvode_spbcgs.h b/src/amuse/community/seculartriple/src/cvode/cvode_spbcgs.h similarity index 100% rename from src/tres/seculartriple_TPS/src/cvode/cvode_spbcgs.h rename to src/amuse/community/seculartriple/src/cvode/cvode_spbcgs.h diff --git a/src/tres/seculartriple_TPS/src/cvode/cvode_spgmr.c b/src/amuse/community/seculartriple/src/cvode/cvode_spgmr.c similarity index 100% rename from src/tres/seculartriple_TPS/src/cvode/cvode_spgmr.c rename to src/amuse/community/seculartriple/src/cvode/cvode_spgmr.c diff --git a/src/tres/seculartriple_TPS/src/cvode/cvode_spgmr.h b/src/amuse/community/seculartriple/src/cvode/cvode_spgmr.h similarity index 100% rename from src/tres/seculartriple_TPS/src/cvode/cvode_spgmr.h rename to src/amuse/community/seculartriple/src/cvode/cvode_spgmr.h diff --git a/src/tres/seculartriple_TPS/src/cvode/cvode_spils.c b/src/amuse/community/seculartriple/src/cvode/cvode_spils.c similarity index 100% rename from src/tres/seculartriple_TPS/src/cvode/cvode_spils.c rename to src/amuse/community/seculartriple/src/cvode/cvode_spils.c diff --git a/src/tres/seculartriple_TPS/src/cvode/cvode_spils.h b/src/amuse/community/seculartriple/src/cvode/cvode_spils.h similarity index 100% rename from src/tres/seculartriple_TPS/src/cvode/cvode_spils.h rename to src/amuse/community/seculartriple/src/cvode/cvode_spils.h diff --git a/src/tres/seculartriple_TPS/src/cvode/cvode_spils_impl.h b/src/amuse/community/seculartriple/src/cvode/cvode_spils_impl.h similarity index 100% rename from src/tres/seculartriple_TPS/src/cvode/cvode_spils_impl.h rename to src/amuse/community/seculartriple/src/cvode/cvode_spils_impl.h diff --git a/src/tres/seculartriple_TPS/src/cvode/cvode_sptfqmr.c b/src/amuse/community/seculartriple/src/cvode/cvode_sptfqmr.c similarity index 100% rename from src/tres/seculartriple_TPS/src/cvode/cvode_sptfqmr.c rename to src/amuse/community/seculartriple/src/cvode/cvode_sptfqmr.c diff --git a/src/tres/seculartriple_TPS/src/cvode/cvode_sptfqmr.h b/src/amuse/community/seculartriple/src/cvode/cvode_sptfqmr.h similarity index 100% rename from src/tres/seculartriple_TPS/src/cvode/cvode_sptfqmr.h rename to src/amuse/community/seculartriple/src/cvode/cvode_sptfqmr.h diff --git a/src/tres/seculartriple_TPS/src/cvode/nvector_serial.c b/src/amuse/community/seculartriple/src/cvode/nvector_serial.c similarity index 100% rename from src/tres/seculartriple_TPS/src/cvode/nvector_serial.c rename to src/amuse/community/seculartriple/src/cvode/nvector_serial.c diff --git a/src/tres/seculartriple_TPS/src/cvode/nvector_serial.h b/src/amuse/community/seculartriple/src/cvode/nvector_serial.h similarity index 100% rename from src/tres/seculartriple_TPS/src/cvode/nvector_serial.h rename to src/amuse/community/seculartriple/src/cvode/nvector_serial.h diff --git a/src/tres/seculartriple_TPS/src/cvode/sundials_band.c b/src/amuse/community/seculartriple/src/cvode/sundials_band.c similarity index 100% rename from src/tres/seculartriple_TPS/src/cvode/sundials_band.c rename to src/amuse/community/seculartriple/src/cvode/sundials_band.c diff --git a/src/tres/seculartriple_TPS/src/cvode/sundials_band.h b/src/amuse/community/seculartriple/src/cvode/sundials_band.h similarity index 100% rename from src/tres/seculartriple_TPS/src/cvode/sundials_band.h rename to src/amuse/community/seculartriple/src/cvode/sundials_band.h diff --git a/src/tres/seculartriple_TPS/src/cvode/sundials_config.h b/src/amuse/community/seculartriple/src/cvode/sundials_config.h similarity index 100% rename from src/tres/seculartriple_TPS/src/cvode/sundials_config.h rename to src/amuse/community/seculartriple/src/cvode/sundials_config.h diff --git a/src/tres/seculartriple_TPS/src/cvode/sundials_dense.c b/src/amuse/community/seculartriple/src/cvode/sundials_dense.c similarity index 100% rename from src/tres/seculartriple_TPS/src/cvode/sundials_dense.c rename to src/amuse/community/seculartriple/src/cvode/sundials_dense.c diff --git a/src/tres/seculartriple_TPS/src/cvode/sundials_dense.h b/src/amuse/community/seculartriple/src/cvode/sundials_dense.h similarity index 100% rename from src/tres/seculartriple_TPS/src/cvode/sundials_dense.h rename to src/amuse/community/seculartriple/src/cvode/sundials_dense.h diff --git a/src/tres/seculartriple_TPS/src/cvode/sundials_direct.c b/src/amuse/community/seculartriple/src/cvode/sundials_direct.c similarity index 100% rename from src/tres/seculartriple_TPS/src/cvode/sundials_direct.c rename to src/amuse/community/seculartriple/src/cvode/sundials_direct.c diff --git a/src/tres/seculartriple_TPS/src/cvode/sundials_direct.h b/src/amuse/community/seculartriple/src/cvode/sundials_direct.h similarity index 100% rename from src/tres/seculartriple_TPS/src/cvode/sundials_direct.h rename to src/amuse/community/seculartriple/src/cvode/sundials_direct.h diff --git a/src/tres/seculartriple_TPS/src/cvode/sundials_iterative.c b/src/amuse/community/seculartriple/src/cvode/sundials_iterative.c similarity index 100% rename from src/tres/seculartriple_TPS/src/cvode/sundials_iterative.c rename to src/amuse/community/seculartriple/src/cvode/sundials_iterative.c diff --git a/src/tres/seculartriple_TPS/src/cvode/sundials_iterative.h b/src/amuse/community/seculartriple/src/cvode/sundials_iterative.h similarity index 100% rename from src/tres/seculartriple_TPS/src/cvode/sundials_iterative.h rename to src/amuse/community/seculartriple/src/cvode/sundials_iterative.h diff --git a/src/tres/seculartriple_TPS/src/cvode/sundials_math.c b/src/amuse/community/seculartriple/src/cvode/sundials_math.c similarity index 100% rename from src/tres/seculartriple_TPS/src/cvode/sundials_math.c rename to src/amuse/community/seculartriple/src/cvode/sundials_math.c diff --git a/src/tres/seculartriple_TPS/src/cvode/sundials_math.h b/src/amuse/community/seculartriple/src/cvode/sundials_math.h similarity index 100% rename from src/tres/seculartriple_TPS/src/cvode/sundials_math.h rename to src/amuse/community/seculartriple/src/cvode/sundials_math.h diff --git a/src/tres/seculartriple_TPS/src/cvode/sundials_nvector.c b/src/amuse/community/seculartriple/src/cvode/sundials_nvector.c similarity index 100% rename from src/tres/seculartriple_TPS/src/cvode/sundials_nvector.c rename to src/amuse/community/seculartriple/src/cvode/sundials_nvector.c diff --git a/src/tres/seculartriple_TPS/src/cvode/sundials_nvector.h b/src/amuse/community/seculartriple/src/cvode/sundials_nvector.h similarity index 100% rename from src/tres/seculartriple_TPS/src/cvode/sundials_nvector.h rename to src/amuse/community/seculartriple/src/cvode/sundials_nvector.h diff --git a/src/tres/seculartriple_TPS/src/cvode/sundials_spbcgs.c b/src/amuse/community/seculartriple/src/cvode/sundials_spbcgs.c similarity index 100% rename from src/tres/seculartriple_TPS/src/cvode/sundials_spbcgs.c rename to src/amuse/community/seculartriple/src/cvode/sundials_spbcgs.c diff --git a/src/tres/seculartriple_TPS/src/cvode/sundials_spbcgs.h b/src/amuse/community/seculartriple/src/cvode/sundials_spbcgs.h similarity index 100% rename from src/tres/seculartriple_TPS/src/cvode/sundials_spbcgs.h rename to src/amuse/community/seculartriple/src/cvode/sundials_spbcgs.h diff --git a/src/tres/seculartriple_TPS/src/cvode/sundials_spgmr.c b/src/amuse/community/seculartriple/src/cvode/sundials_spgmr.c similarity index 100% rename from src/tres/seculartriple_TPS/src/cvode/sundials_spgmr.c rename to src/amuse/community/seculartriple/src/cvode/sundials_spgmr.c diff --git a/src/tres/seculartriple_TPS/src/cvode/sundials_spgmr.h b/src/amuse/community/seculartriple/src/cvode/sundials_spgmr.h similarity index 100% rename from src/tres/seculartriple_TPS/src/cvode/sundials_spgmr.h rename to src/amuse/community/seculartriple/src/cvode/sundials_spgmr.h diff --git a/src/tres/seculartriple_TPS/src/cvode/sundials_sptfqmr.c b/src/amuse/community/seculartriple/src/cvode/sundials_sptfqmr.c similarity index 100% rename from src/tres/seculartriple_TPS/src/cvode/sundials_sptfqmr.c rename to src/amuse/community/seculartriple/src/cvode/sundials_sptfqmr.c diff --git a/src/tres/seculartriple_TPS/src/cvode/sundials_sptfqmr.h b/src/amuse/community/seculartriple/src/cvode/sundials_sptfqmr.h similarity index 100% rename from src/tres/seculartriple_TPS/src/cvode/sundials_sptfqmr.h rename to src/amuse/community/seculartriple/src/cvode/sundials_sptfqmr.h diff --git a/src/tres/seculartriple_TPS/src/cvode/sundials_types.h b/src/amuse/community/seculartriple/src/cvode/sundials_types.h similarity index 100% rename from src/tres/seculartriple_TPS/src/cvode/sundials_types.h rename to src/amuse/community/seculartriple/src/cvode/sundials_types.h diff --git a/src/tres/seculartriple_TPS/src/helper_routines.c b/src/amuse/community/seculartriple/src/helper_routines.c similarity index 100% rename from src/tres/seculartriple_TPS/src/helper_routines.c rename to src/amuse/community/seculartriple/src/helper_routines.c diff --git a/src/tres/seculartriple_TPS/src/helper_routines.h b/src/amuse/community/seculartriple/src/helper_routines.h similarity index 100% rename from src/tres/seculartriple_TPS/src/helper_routines.h rename to src/amuse/community/seculartriple/src/helper_routines.h diff --git a/src/tres/seculartriple_TPS/src/main_code.c b/src/amuse/community/seculartriple/src/main_code.c similarity index 100% rename from src/tres/seculartriple_TPS/src/main_code.c rename to src/amuse/community/seculartriple/src/main_code.c diff --git a/src/tres/seculartriple_TPS/src/main_code.h b/src/amuse/community/seculartriple/src/main_code.h similarity index 100% rename from src/tres/seculartriple_TPS/src/main_code.h rename to src/amuse/community/seculartriple/src/main_code.h diff --git a/src/tres/seculartriple_TPS/src/tidal_friction_parameters.c b/src/amuse/community/seculartriple/src/tidal_friction_parameters.c similarity index 100% rename from src/tres/seculartriple_TPS/src/tidal_friction_parameters.c rename to src/amuse/community/seculartriple/src/tidal_friction_parameters.c diff --git a/src/tres/seculartriple_TPS/src/tidal_friction_parameters.h b/src/amuse/community/seculartriple/src/tidal_friction_parameters.h similarity index 100% rename from src/tres/seculartriple_TPS/src/tidal_friction_parameters.h rename to src/amuse/community/seculartriple/src/tidal_friction_parameters.h diff --git a/src/tres/seculartriple_TPS/tidal_friction_constant.py b/src/amuse/community/seculartriple/tidal_friction_constant.py similarity index 100% rename from src/tres/seculartriple_TPS/tidal_friction_constant.py rename to src/amuse/community/seculartriple/tidal_friction_constant.py From 1e3c6059b5b4d7436e13e90571a90f36fae99f21 Mon Sep 17 00:00:00 2001 From: Steven Rieder Date: Tue, 5 Nov 2024 12:17:37 +0100 Subject: [PATCH 21/30] fix line endings --- example/examples_TRES_AMUSE_book.py | 432 ++++++++++++++-------------- 1 file changed, 216 insertions(+), 216 deletions(-) diff --git a/example/examples_TRES_AMUSE_book.py b/example/examples_TRES_AMUSE_book.py index e66f4dc..2a67f86 100644 --- a/example/examples_TRES_AMUSE_book.py +++ b/example/examples_TRES_AMUSE_book.py @@ -1,125 +1,125 @@ -import numpy as np +import numpy as np import matplotlib.pyplot as plt -from amuse.datamodel import Particles -from amuse.units import units -from amuse.community.seba.interface import SeBa +from amuse.datamodel import Particles +from amuse.units import units +from amuse.community.seba.interface import SeBa import sys, os sys.path.append(os.path.dirname(os.getcwd())) -import TRES as TRES -from seculartriple_TPS.interface import SecularTriple - - -bin_type = { 'all': -1, - 'unknown': 0, - 'merger': 1, - 'disintegrated': 2, - 'dynamical_instability': 3, - 'detached': 4, - 'contact': 5, - 'collision': 6, - 'semisecular': 7, - 'rlof': 8, #only used for stopping conditions - 'olof': 9, #only used for stopping conditions - 'stable_mass_transfer': 10, - 'common_envelope': 11, - 'common_envelope_energy_balance': 12, - 'common_envelope_angular_momentum_balance': 13, - 'double_common_envelope': 14, +import TRES as TRES +from seculartriple_TPS.interface import SecularTriple + + +bin_type = { 'all': -1, + 'unknown': 0, + 'merger': 1, + 'disintegrated': 2, + 'dynamical_instability': 3, + 'detached': 4, + 'contact': 5, + 'collision': 6, + 'semisecular': 7, + 'rlof': 8, #only used for stopping conditions + 'olof': 9, #only used for stopping conditions + 'stable_mass_transfer': 10, + 'common_envelope': 11, + 'common_envelope_energy_balance': 12, + 'common_envelope_angular_momentum_balance': 13, + 'double_common_envelope': 14, } - - -#simplest way of running TRES -def example_1(): + + +#simplest way of running TRES +def example_1(): print('TRES example 1') - tr = TRES.main() - print(tr.triple.eccentricity, tr.triple.child2.eccentricity) - - tr.stellar_code.stop() - tr.secular_code.stop() - - -#simple way of running TRES with adjusting input parameters -#possible parameters: -#inner_primary_mass, inner_secondary_mass, outer_mass, -#inner_semimajor_axis, outer_semimajor_axis, inner_eccentricity, outer_eccentricity, -#relative_inclination, inner_argument_of_pericenter, outer_argument_of_pericenter, inner_longitude_of_ascending_node, -#metallicity, -#tend, tinit, -#number #id number of (first) triple -# -#possible stopping conditions: -#stop_at_mass_transfer, stop_at_init_mass_transfer,stop_at_outer_mass_transfer, -#stop_at_stable_mass_transfer, stop_at_eccentric_stable_mass_transfer, + tr = TRES.main() + print(tr.triple.eccentricity, tr.triple.child2.eccentricity) + + tr.stellar_code.stop() + tr.secular_code.stop() + + +#simple way of running TRES with adjusting input parameters +#possible parameters: +#inner_primary_mass, inner_secondary_mass, outer_mass, +#inner_semimajor_axis, outer_semimajor_axis, inner_eccentricity, outer_eccentricity, +#relative_inclination, inner_argument_of_pericenter, outer_argument_of_pericenter, inner_longitude_of_ascending_node, +#metallicity, +#tend, tinit, +#number #id number of (first) triple +# +#possible stopping conditions: +#stop_at_mass_transfer, stop_at_init_mass_transfer,stop_at_outer_mass_transfer, +#stop_at_stable_mass_transfer, stop_at_eccentric_stable_mass_transfer, #stop_at_unstable_mass_transfer, stop_at_eccentric_unstable_mass_transfer, -#stop_at_no_CHE, include_CHE, -#stop_at_merger, stop_at_disintegrated, -#stop_at_inner_collision, stop_at_outer_collision, -#stop_at_dynamical_instability, -#stop_at_semisecular_regime, -#stop_at_SN, SN_kick_distr, -# -#possible settings: -#impulse_kick_for_black_holes, -#fallback_kick_for_black_holes, -#which_common_envelope, -#stop_at_CPU_time, -#max_CPU_time, -#file_name, file_type, dir_plots - -def example_2(): +#stop_at_no_CHE, include_CHE, +#stop_at_merger, stop_at_disintegrated, +#stop_at_inner_collision, stop_at_outer_collision, +#stop_at_dynamical_instability, +#stop_at_semisecular_regime, +#stop_at_SN, SN_kick_distr, +# +#possible settings: +#impulse_kick_for_black_holes, +#fallback_kick_for_black_holes, +#which_common_envelope, +#stop_at_CPU_time, +#max_CPU_time, +#file_name, file_type, dir_plots + +def example_2(): print('TRES example 2') - - M1 = 1.5|units.MSun - M2 = 0.6|units.MSun - M3 = 0.6|units.MSun - ain = 150|units.RSun - aout = 15000|units.RSun - incl = 81.0*np.pi/180.0 - - tr = TRES.main(inner_primary_mass = M1, inner_secondary_mass = M2, outer_mass = M3, - inner_semimajor_axis = ain, outer_semimajor_axis = aout, relative_inclination = incl) + + M1 = 1.5|units.MSun + M2 = 0.6|units.MSun + M3 = 0.6|units.MSun + ain = 150|units.RSun + aout = 15000|units.RSun + incl = 81.0*np.pi/180.0 + + tr = TRES.main(inner_primary_mass = M1, inner_secondary_mass = M2, outer_mass = M3, + inner_semimajor_axis = ain, outer_semimajor_axis = aout, relative_inclination = incl) print('final outer eccentricity: ', tr.triple.eccentricity) - print('final inner eccentricity: ', tr.triple.child2.eccentricity) - - tr.stellar_code.stop() - tr.secular_code.stop() - - -# example of Kozai-Lidov cycles in a triple with plotting -# advanced level -# uses TRES.main_developer() in stead of TRES.main() + print('final inner eccentricity: ', tr.triple.child2.eccentricity) + + tr.stellar_code.stop() + tr.secular_code.stop() + + +# example of Kozai-Lidov cycles in a triple with plotting +# advanced level +# uses TRES.main_developer() in stead of TRES.main() def example_3(): print('TRES example 3') - - M1 = 1.3|units.MSun - M2 = 0.5|units.MSun - M3 = 0.5|units.MSun - Ain = 200|units.RSun - Aout = 20000|units.RSun - Ein = 0.1 - Eout = 0.5 - incl = 80.0*np.pi/180.0 - Gin = 0.1 - Gout = 0.5 - Oin = 0. - metallicity = 0.02 - - stars, bins, correct_params = TRES.make_particle_sets(M1,M2,M3, Ain, Aout, Ein, Eout, incl, Gin, Gout, Oin) - - stellar_code = SeBa() - stellar_code.parameters.metallicity = metallicity - # stellar_code.particles.add_particles(stars) - secular_code = SecularTriple() + + M1 = 1.3|units.MSun + M2 = 0.5|units.MSun + M3 = 0.5|units.MSun + Ain = 200|units.RSun + Aout = 20000|units.RSun + Ein = 0.1 + Eout = 0.5 + incl = 80.0*np.pi/180.0 + Gin = 0.1 + Gout = 0.5 + Oin = 0. + metallicity = 0.02 + + stars, bins, correct_params = TRES.make_particle_sets(M1,M2,M3, Ain, Aout, Ein, Eout, incl, Gin, Gout, Oin) - inner_eccentricity_array = [] + stellar_code = SeBa() + stellar_code.parameters.metallicity = metallicity + # stellar_code.particles.add_particles(stars) + secular_code = SecularTriple() + + inner_eccentricity_array = [] outer_eccentricity_array = [] n_steps = 150 - time_array = (np.arange(n_steps)+1)*5|units.Myr/n_steps + time_array = (np.arange(n_steps)+1)*5|units.Myr/n_steps #make triple object and evolve for small timestep - #needs to be bigger then 1e-4|units.Myr for secular code - tr = TRES.main_developer(stars, bins, correct_params, stellar_code, secular_code, incl, tend=1e-4|units.Myr) + #needs to be bigger then 1e-4|units.Myr for secular code + tr = TRES.main_developer(stars, bins, correct_params, stellar_code, secular_code, incl, tend=1e-4|units.Myr) for i in range(len(time_array)): tr.evolve_model(time_array[i]) @@ -139,41 +139,41 @@ def example_3(): plt.ylabel('eccentricity') plt.legend(loc=0) plt.show() - - tr.stellar_code.stop() - tr.secular_code.stop() - + + tr.stellar_code.stop() + tr.secular_code.stop() + # example of triple with wind mass loss leading to dynamical instability with plotting -# advanced level -# uses TRES.main_developer() in stead of TRES.main() +# advanced level +# uses TRES.main_developer() in stead of TRES.main() def example_4(): print('TRES example 4') - - M1 = 3.|units.MSun - M2 = 0.5|units.MSun - M3 = 0.5|units.MSun - Ain = 825|units.RSun - Aout = 6600|units.RSun - Ein = 0.0 - Eout = 0.5 + + M1 = 3.|units.MSun + M2 = 0.5|units.MSun + M3 = 0.5|units.MSun + Ain = 825|units.RSun + Aout = 6600|units.RSun + Ein = 0.0 + Eout = 0.5 incl = 0.0 - Gin = 0.1 - Gout = 0.5 - Oin = 0. - metallicity = 0.02 - - stars, bins, correct_params = TRES.make_particle_sets(M1,M2,M3, Ain, Aout, Ein, Eout, incl, Gin, Gout, Oin) - - stellar_code = SeBa() - stellar_code.parameters.metallicity = metallicity - # stellar_code.particles.add_particles(stars) - secular_code = SecularTriple() + Gin = 0.1 + Gout = 0.5 + Oin = 0. + metallicity = 0.02 + + stars, bins, correct_params = TRES.make_particle_sets(M1,M2,M3, Ain, Aout, Ein, Eout, incl, Gin, Gout, Oin) + + stellar_code = SeBa() + stellar_code.parameters.metallicity = metallicity + # stellar_code.particles.add_particles(stars) + secular_code = SecularTriple() - inner_semimajor_axis_array = np.array([]) + inner_semimajor_axis_array = np.array([]) outer_semimajor_axis_array = np.array([]) mass_primary_array = np.array([]) @@ -183,8 +183,8 @@ def example_4(): time_array = time_array|units.Myr #make triple object and evolve for small timestep - #needs to be bigger then 1e-4|units.Myr for secular code - tr = TRES.main_developer(stars, bins, correct_params, stellar_code, secular_code, incl, tend=1e-4|units.Myr) + #needs to be bigger then 1e-4|units.Myr for secular code + tr = TRES.main_developer(stars, bins, correct_params, stellar_code, secular_code, incl, tend=1e-4|units.Myr) for i in range(len(time_array)): tr.evolve_model(time_array[i]) @@ -221,40 +221,40 @@ def example_4(): plt.legend(loc=0) plt.show() - tr.stellar_code.stop() - tr.secular_code.stop() - - + tr.stellar_code.stop() + tr.secular_code.stop() + + # example of triple with wind mass loss & mass transfer with plotting -# advanced level -# uses TRES.main_developer() in stead of TRES.main() -def example_5(): +# advanced level +# uses TRES.main_developer() in stead of TRES.main() +def example_5(): print('TRES example 5') - M1 = 3.|units.MSun - M2 = 0.5|units.MSun - M3 = 0.5|units.MSun - Ain = 825|units.RSun - Aout = 80000|units.RSun - Ein = 0.0 - Eout = 0.5 + M1 = 3.|units.MSun + M2 = 0.5|units.MSun + M3 = 0.5|units.MSun + Ain = 825|units.RSun + Aout = 80000|units.RSun + Ein = 0.0 + Eout = 0.5 incl = 0.0 - Gin = 0.1 - Gout = 0.5 - Oin = 0. - metallicity = 0.02 - - stars, bins, correct_params = TRES.make_particle_sets(M1,M2,M3, Ain, Aout, Ein, Eout, incl, Gin, Gout, Oin) - - stellar_code = SeBa() - stellar_code.parameters.metallicity = metallicity - # stellar_code.particles.add_particles(stars) - secular_code = SecularTriple() + Gin = 0.1 + Gout = 0.5 + Oin = 0. + metallicity = 0.02 + + stars, bins, correct_params = TRES.make_particle_sets(M1,M2,M3, Ain, Aout, Ein, Eout, incl, Gin, Gout, Oin) + + stellar_code = SeBa() + stellar_code.parameters.metallicity = metallicity + # stellar_code.particles.add_particles(stars) + secular_code = SecularTriple() - inner_semimajor_axis_array = np.array([]) + inner_semimajor_axis_array = np.array([]) outer_semimajor_axis_array = np.array([]) radius_primary_array = np.array([]) stellar_type_primary_array = np.array([]) @@ -265,7 +265,7 @@ def example_5(): time_array = time_array|units.Myr #make triple object and evolve for small timestep - #needs to be bigger then 1e-4|units.Myr for secular code + #needs to be bigger then 1e-4|units.Myr for secular code tr = TRES.main_developer(stars, bins, correct_params, stellar_code, secular_code, incl, tend=1e-4|units.Myr, stop_at_mass_transfer=False) for i in range(len(time_array)): @@ -309,55 +309,55 @@ def example_5(): plt.show() - tr.stellar_code.stop() - tr.secular_code.stop() - - - -# most advanced level + tr.stellar_code.stop() + tr.secular_code.stop() + + + +# most advanced level # uses TRES.main_developer() in stead of TRES.main() # make a cataclysmic variable & start the simulation with a stellar type of your choice -# we make the triple but don't evolve it, only the stars to 4500 Myr at which we strip off the envelope to make a white dwarf +# we make the triple but don't evolve it, only the stars to 4500 Myr at which we strip off the envelope to make a white dwarf # afterwards pickup the triple evolution -def example_6(): +def example_6(): print('TRES example 6') - M1 = 1.3|units.MSun - M2 = 0.5|units.MSun - M3 = 0.5|units.MSun - Ain = 3.|units.RSun - Aout = 1000|units.RSun - Ein = 0. - Eout = 0. - incl = 0.0*np.pi/180.0 - Gin = 0.1 - Gout = 0.5 - Oin = 0. - metallicity = 0.02 - - stars, bins, correct_params = TRES.make_particle_sets(M1,M2,M3, Ain, Aout, Ein, Eout, incl, Gin, Gout, Oin) - - stellar_code = SeBa() - stellar_code.parameters.metallicity = metallicity - # stellar_code.particles.add_particles(stars) - secular_code = SecularTriple() - - #make triple object (evolve for small timestep) - #needs to be bigger then 1e-4|units.Myr for secular code - tr = TRES.main_developer(stars, bins, correct_params, stellar_code, secular_code, incl, tend=1e-4|units.Myr) + M1 = 1.3|units.MSun + M2 = 0.5|units.MSun + M3 = 0.5|units.MSun + Ain = 3.|units.RSun + Aout = 1000|units.RSun + Ein = 0. + Eout = 0. + incl = 0.0*np.pi/180.0 + Gin = 0.1 + Gout = 0.5 + Oin = 0. + metallicity = 0.02 + + stars, bins, correct_params = TRES.make_particle_sets(M1,M2,M3, Ain, Aout, Ein, Eout, incl, Gin, Gout, Oin) + + stellar_code = SeBa() + stellar_code.parameters.metallicity = metallicity + # stellar_code.particles.add_particles(stars) + secular_code = SecularTriple() + + #make triple object (evolve for small timestep) + #needs to be bigger then 1e-4|units.Myr for secular code + tr = TRES.main_developer(stars, bins, correct_params, stellar_code, secular_code, incl, tend=1e-4|units.Myr) #only evolve the stars until 4500Myr - goal_time = 4500|units.Myr - stellar_code.evolve_model(goal_time) - channel_from_stellar = stellar_code.particles.new_channel_to(stars) - channel_from_stellar.copy() - -# make modifications to stellar object -# in this case remove some mass of the envelope (without effect on triple) - donor_in_stellar_code = stars[0].as_set().get_intersecting_subset_in(stellar_code.particles)[0] + goal_time = 4500|units.Myr + stellar_code.evolve_model(goal_time) + channel_from_stellar = stellar_code.particles.new_channel_to(stars) + channel_from_stellar.copy() + +# make modifications to stellar object +# in this case remove some mass of the envelope (without effect on triple) + donor_in_stellar_code = stars[0].as_set().get_intersecting_subset_in(stellar_code.particles)[0] donor_in_stellar_code.change_mass((stars[0].core_mass-stars[0].mass), 0.|units.yr) - minimum_time_step = 1.e-9 |units.Myr + minimum_time_step = 1.e-9 |units.Myr stellar_code.evolve_model(goal_time+minimum_time_step) #to get updated radii channel_from_stellar.copy() @@ -371,24 +371,24 @@ def example_6(): tr.secular_code.model_time = goal_time + minimum_time_step #not redundant! # continue triple evolution until 5000Myr - tr.evolve_model(5000|units.Myr) + tr.evolve_model(5000|units.Myr) if tr.check_stopping_conditions()==False or tr.check_stopping_conditions_stellar()==False or tr.check_stopping_conditions_stellar_interaction()==False: print('stopping conditions reached') - - print(tr.triple.eccentricity, tr.triple.child2.eccentricity) - print(tr.triple.semimajor_axis, tr.triple.child2.semimajor_axis) - - tr.stellar_code.stop() - tr.secular_code.stop() - - - -example_1() -#example_2() + + print(tr.triple.eccentricity, tr.triple.child2.eccentricity) + print(tr.triple.semimajor_axis, tr.triple.child2.semimajor_axis) + + tr.stellar_code.stop() + tr.secular_code.stop() + + + +example_1() +#example_2() #example_3() -#example_4() -#example_5() -#example_6() +#example_4() +#example_5() +#example_6() From 0fe94478d343fd930a379b9d170c12e10a1b4250 Mon Sep 17 00:00:00 2001 From: Steven Rieder Date: Thu, 7 Nov 2024 17:48:46 +0100 Subject: [PATCH 22/30] moving things, renaming things, getting rid of "import *" [WIP] --- src/tres/__init__.py | 4 +- src/tres/interactions.py | 3 + .../community => tres}/seculartriple/Makefile | 0 .../seculartriple/Makefile_old | 0 .../seculartriple/__init__.py | 0 .../seculartriple/interface.py | 0 .../seculartriple/src/ODE_system.c | 0 .../seculartriple/src/ODE_system.h | 0 .../seculartriple/src/cvode/cvode.c | 0 .../seculartriple/src/cvode/cvode.h | 0 .../seculartriple/src/cvode/cvode_band.c | 0 .../seculartriple/src/cvode/cvode_band.h | 0 .../seculartriple/src/cvode/cvode_bandpre.h | 0 .../seculartriple/src/cvode/cvode_dense.c | 0 .../seculartriple/src/cvode/cvode_dense.h | 0 .../seculartriple/src/cvode/cvode_diag.c | 0 .../seculartriple/src/cvode/cvode_diag.h | 0 .../seculartriple/src/cvode/cvode_diag_impl.h | 0 .../seculartriple/src/cvode/cvode_direct.c | 0 .../seculartriple/src/cvode/cvode_direct.h | 0 .../src/cvode/cvode_direct_impl.h | 0 .../seculartriple/src/cvode/cvode_impl.h | 0 .../seculartriple/src/cvode/cvode_io.c | 0 .../seculartriple/src/cvode/cvode_spbcgs.c | 0 .../seculartriple/src/cvode/cvode_spbcgs.h | 0 .../seculartriple/src/cvode/cvode_spgmr.c | 0 .../seculartriple/src/cvode/cvode_spgmr.h | 0 .../seculartriple/src/cvode/cvode_spils.c | 0 .../seculartriple/src/cvode/cvode_spils.h | 0 .../src/cvode/cvode_spils_impl.h | 0 .../seculartriple/src/cvode/cvode_sptfqmr.c | 0 .../seculartriple/src/cvode/cvode_sptfqmr.h | 0 .../seculartriple/src/cvode/nvector_serial.c | 0 .../seculartriple/src/cvode/nvector_serial.h | 0 .../seculartriple/src/cvode/sundials_band.c | 0 .../seculartriple/src/cvode/sundials_band.h | 0 .../seculartriple/src/cvode/sundials_config.h | 0 .../seculartriple/src/cvode/sundials_dense.c | 0 .../seculartriple/src/cvode/sundials_dense.h | 0 .../seculartriple/src/cvode/sundials_direct.c | 0 .../seculartriple/src/cvode/sundials_direct.h | 0 .../src/cvode/sundials_iterative.c | 0 .../src/cvode/sundials_iterative.h | 0 .../seculartriple/src/cvode/sundials_math.c | 0 .../seculartriple/src/cvode/sundials_math.h | 0 .../src/cvode/sundials_nvector.c | 0 .../src/cvode/sundials_nvector.h | 0 .../seculartriple/src/cvode/sundials_spbcgs.c | 0 .../seculartriple/src/cvode/sundials_spbcgs.h | 0 .../seculartriple/src/cvode/sundials_spgmr.c | 0 .../seculartriple/src/cvode/sundials_spgmr.h | 0 .../src/cvode/sundials_sptfqmr.c | 0 .../src/cvode/sundials_sptfqmr.h | 0 .../seculartriple/src/cvode/sundials_types.h | 0 .../seculartriple/src/helper_routines.c | 0 .../seculartriple/src/helper_routines.h | 0 .../seculartriple/src/main_code.c | 0 .../seculartriple/src/main_code.h | 0 .../src/tidal_friction_parameters.c | 0 .../src/tidal_friction_parameters.h | 0 .../seculartriple/tidal_friction_constant.py | 0 src/tres/setup.py | 205 ++++++++++------ src/tres/tps.py | 1 - src/tres/tres.py | 101 ++++---- src/tres/triple_class.py | 221 +++++++++--------- 65 files changed, 316 insertions(+), 219 deletions(-) rename src/{amuse/community => tres}/seculartriple/Makefile (100%) rename src/{amuse/community => tres}/seculartriple/Makefile_old (100%) rename src/{amuse/community => tres}/seculartriple/__init__.py (100%) rename src/{amuse/community => tres}/seculartriple/interface.py (100%) rename src/{amuse/community => tres}/seculartriple/src/ODE_system.c (100%) rename src/{amuse/community => tres}/seculartriple/src/ODE_system.h (100%) rename src/{amuse/community => tres}/seculartriple/src/cvode/cvode.c (100%) rename src/{amuse/community => tres}/seculartriple/src/cvode/cvode.h (100%) rename src/{amuse/community => tres}/seculartriple/src/cvode/cvode_band.c (100%) rename src/{amuse/community => tres}/seculartriple/src/cvode/cvode_band.h (100%) rename src/{amuse/community => tres}/seculartriple/src/cvode/cvode_bandpre.h (100%) rename src/{amuse/community => tres}/seculartriple/src/cvode/cvode_dense.c (100%) rename src/{amuse/community => tres}/seculartriple/src/cvode/cvode_dense.h (100%) rename src/{amuse/community => tres}/seculartriple/src/cvode/cvode_diag.c (100%) rename src/{amuse/community => tres}/seculartriple/src/cvode/cvode_diag.h (100%) rename src/{amuse/community => tres}/seculartriple/src/cvode/cvode_diag_impl.h (100%) rename src/{amuse/community => tres}/seculartriple/src/cvode/cvode_direct.c (100%) rename src/{amuse/community => tres}/seculartriple/src/cvode/cvode_direct.h (100%) rename src/{amuse/community => tres}/seculartriple/src/cvode/cvode_direct_impl.h (100%) rename src/{amuse/community => tres}/seculartriple/src/cvode/cvode_impl.h (100%) rename src/{amuse/community => tres}/seculartriple/src/cvode/cvode_io.c (100%) rename src/{amuse/community => tres}/seculartriple/src/cvode/cvode_spbcgs.c (100%) rename src/{amuse/community => tres}/seculartriple/src/cvode/cvode_spbcgs.h (100%) rename src/{amuse/community => tres}/seculartriple/src/cvode/cvode_spgmr.c (100%) rename src/{amuse/community => tres}/seculartriple/src/cvode/cvode_spgmr.h (100%) rename src/{amuse/community => tres}/seculartriple/src/cvode/cvode_spils.c (100%) rename src/{amuse/community => tres}/seculartriple/src/cvode/cvode_spils.h (100%) rename src/{amuse/community => tres}/seculartriple/src/cvode/cvode_spils_impl.h (100%) rename src/{amuse/community => tres}/seculartriple/src/cvode/cvode_sptfqmr.c (100%) rename src/{amuse/community => tres}/seculartriple/src/cvode/cvode_sptfqmr.h (100%) rename src/{amuse/community => tres}/seculartriple/src/cvode/nvector_serial.c (100%) rename src/{amuse/community => tres}/seculartriple/src/cvode/nvector_serial.h (100%) rename src/{amuse/community => tres}/seculartriple/src/cvode/sundials_band.c (100%) rename src/{amuse/community => tres}/seculartriple/src/cvode/sundials_band.h (100%) rename src/{amuse/community => tres}/seculartriple/src/cvode/sundials_config.h (100%) rename src/{amuse/community => tres}/seculartriple/src/cvode/sundials_dense.c (100%) rename src/{amuse/community => tres}/seculartriple/src/cvode/sundials_dense.h (100%) rename src/{amuse/community => tres}/seculartriple/src/cvode/sundials_direct.c (100%) rename src/{amuse/community => tres}/seculartriple/src/cvode/sundials_direct.h (100%) rename src/{amuse/community => tres}/seculartriple/src/cvode/sundials_iterative.c (100%) rename src/{amuse/community => tres}/seculartriple/src/cvode/sundials_iterative.h (100%) rename src/{amuse/community => tres}/seculartriple/src/cvode/sundials_math.c (100%) rename src/{amuse/community => tres}/seculartriple/src/cvode/sundials_math.h (100%) rename src/{amuse/community => tres}/seculartriple/src/cvode/sundials_nvector.c (100%) rename src/{amuse/community => tres}/seculartriple/src/cvode/sundials_nvector.h (100%) rename src/{amuse/community => tres}/seculartriple/src/cvode/sundials_spbcgs.c (100%) rename src/{amuse/community => tres}/seculartriple/src/cvode/sundials_spbcgs.h (100%) rename src/{amuse/community => tres}/seculartriple/src/cvode/sundials_spgmr.c (100%) rename src/{amuse/community => tres}/seculartriple/src/cvode/sundials_spgmr.h (100%) rename src/{amuse/community => tres}/seculartriple/src/cvode/sundials_sptfqmr.c (100%) rename src/{amuse/community => tres}/seculartriple/src/cvode/sundials_sptfqmr.h (100%) rename src/{amuse/community => tres}/seculartriple/src/cvode/sundials_types.h (100%) rename src/{amuse/community => tres}/seculartriple/src/helper_routines.c (100%) rename src/{amuse/community => tres}/seculartriple/src/helper_routines.h (100%) rename src/{amuse/community => tres}/seculartriple/src/main_code.c (100%) rename src/{amuse/community => tres}/seculartriple/src/main_code.h (100%) rename src/{amuse/community => tres}/seculartriple/src/tidal_friction_parameters.c (100%) rename src/{amuse/community => tres}/seculartriple/src/tidal_friction_parameters.h (100%) rename src/{amuse/community => tres}/seculartriple/tidal_friction_constant.py (100%) diff --git a/src/tres/__init__.py b/src/tres/__init__.py index 3dcec34..9f4a940 100644 --- a/src/tres/__init__.py +++ b/src/tres/__init__.py @@ -1 +1,3 @@ -from .tres import main +from .tres import tres_main as main +from .tres import tres_main_developer as main_developer +from .tres import make_particle_sets, corotating_spin_angular_frequency_binary diff --git a/src/tres/interactions.py b/src/tres/interactions.py index 556ffe6..1b3c004 100644 --- a/src/tres/interactions.py +++ b/src/tres/interactions.py @@ -1,3 +1,6 @@ +""" +interactions module, but seems to contain mostly constants +""" import sys import numpy as np from scipy import integrate diff --git a/src/amuse/community/seculartriple/Makefile b/src/tres/seculartriple/Makefile similarity index 100% rename from src/amuse/community/seculartriple/Makefile rename to src/tres/seculartriple/Makefile diff --git a/src/amuse/community/seculartriple/Makefile_old b/src/tres/seculartriple/Makefile_old similarity index 100% rename from src/amuse/community/seculartriple/Makefile_old rename to src/tres/seculartriple/Makefile_old diff --git a/src/amuse/community/seculartriple/__init__.py b/src/tres/seculartriple/__init__.py similarity index 100% rename from src/amuse/community/seculartriple/__init__.py rename to src/tres/seculartriple/__init__.py diff --git a/src/amuse/community/seculartriple/interface.py b/src/tres/seculartriple/interface.py similarity index 100% rename from src/amuse/community/seculartriple/interface.py rename to src/tres/seculartriple/interface.py diff --git a/src/amuse/community/seculartriple/src/ODE_system.c b/src/tres/seculartriple/src/ODE_system.c similarity index 100% rename from src/amuse/community/seculartriple/src/ODE_system.c rename to src/tres/seculartriple/src/ODE_system.c diff --git a/src/amuse/community/seculartriple/src/ODE_system.h b/src/tres/seculartriple/src/ODE_system.h similarity index 100% rename from src/amuse/community/seculartriple/src/ODE_system.h rename to src/tres/seculartriple/src/ODE_system.h diff --git a/src/amuse/community/seculartriple/src/cvode/cvode.c b/src/tres/seculartriple/src/cvode/cvode.c similarity index 100% rename from src/amuse/community/seculartriple/src/cvode/cvode.c rename to src/tres/seculartriple/src/cvode/cvode.c diff --git a/src/amuse/community/seculartriple/src/cvode/cvode.h b/src/tres/seculartriple/src/cvode/cvode.h similarity index 100% rename from src/amuse/community/seculartriple/src/cvode/cvode.h rename to src/tres/seculartriple/src/cvode/cvode.h diff --git a/src/amuse/community/seculartriple/src/cvode/cvode_band.c b/src/tres/seculartriple/src/cvode/cvode_band.c similarity index 100% rename from src/amuse/community/seculartriple/src/cvode/cvode_band.c rename to src/tres/seculartriple/src/cvode/cvode_band.c diff --git a/src/amuse/community/seculartriple/src/cvode/cvode_band.h b/src/tres/seculartriple/src/cvode/cvode_band.h similarity index 100% rename from src/amuse/community/seculartriple/src/cvode/cvode_band.h rename to src/tres/seculartriple/src/cvode/cvode_band.h diff --git a/src/amuse/community/seculartriple/src/cvode/cvode_bandpre.h b/src/tres/seculartriple/src/cvode/cvode_bandpre.h similarity index 100% rename from src/amuse/community/seculartriple/src/cvode/cvode_bandpre.h rename to src/tres/seculartriple/src/cvode/cvode_bandpre.h diff --git a/src/amuse/community/seculartriple/src/cvode/cvode_dense.c b/src/tres/seculartriple/src/cvode/cvode_dense.c similarity index 100% rename from src/amuse/community/seculartriple/src/cvode/cvode_dense.c rename to src/tres/seculartriple/src/cvode/cvode_dense.c diff --git a/src/amuse/community/seculartriple/src/cvode/cvode_dense.h b/src/tres/seculartriple/src/cvode/cvode_dense.h similarity index 100% rename from src/amuse/community/seculartriple/src/cvode/cvode_dense.h rename to src/tres/seculartriple/src/cvode/cvode_dense.h diff --git a/src/amuse/community/seculartriple/src/cvode/cvode_diag.c b/src/tres/seculartriple/src/cvode/cvode_diag.c similarity index 100% rename from src/amuse/community/seculartriple/src/cvode/cvode_diag.c rename to src/tres/seculartriple/src/cvode/cvode_diag.c diff --git a/src/amuse/community/seculartriple/src/cvode/cvode_diag.h b/src/tres/seculartriple/src/cvode/cvode_diag.h similarity index 100% rename from src/amuse/community/seculartriple/src/cvode/cvode_diag.h rename to src/tres/seculartriple/src/cvode/cvode_diag.h diff --git a/src/amuse/community/seculartriple/src/cvode/cvode_diag_impl.h b/src/tres/seculartriple/src/cvode/cvode_diag_impl.h similarity index 100% rename from src/amuse/community/seculartriple/src/cvode/cvode_diag_impl.h rename to src/tres/seculartriple/src/cvode/cvode_diag_impl.h diff --git a/src/amuse/community/seculartriple/src/cvode/cvode_direct.c b/src/tres/seculartriple/src/cvode/cvode_direct.c similarity index 100% rename from src/amuse/community/seculartriple/src/cvode/cvode_direct.c rename to src/tres/seculartriple/src/cvode/cvode_direct.c diff --git a/src/amuse/community/seculartriple/src/cvode/cvode_direct.h b/src/tres/seculartriple/src/cvode/cvode_direct.h similarity index 100% rename from src/amuse/community/seculartriple/src/cvode/cvode_direct.h rename to src/tres/seculartriple/src/cvode/cvode_direct.h diff --git a/src/amuse/community/seculartriple/src/cvode/cvode_direct_impl.h b/src/tres/seculartriple/src/cvode/cvode_direct_impl.h similarity index 100% rename from src/amuse/community/seculartriple/src/cvode/cvode_direct_impl.h rename to src/tres/seculartriple/src/cvode/cvode_direct_impl.h diff --git a/src/amuse/community/seculartriple/src/cvode/cvode_impl.h b/src/tres/seculartriple/src/cvode/cvode_impl.h similarity index 100% rename from src/amuse/community/seculartriple/src/cvode/cvode_impl.h rename to src/tres/seculartriple/src/cvode/cvode_impl.h diff --git a/src/amuse/community/seculartriple/src/cvode/cvode_io.c b/src/tres/seculartriple/src/cvode/cvode_io.c similarity index 100% rename from src/amuse/community/seculartriple/src/cvode/cvode_io.c rename to src/tres/seculartriple/src/cvode/cvode_io.c diff --git a/src/amuse/community/seculartriple/src/cvode/cvode_spbcgs.c b/src/tres/seculartriple/src/cvode/cvode_spbcgs.c similarity index 100% rename from src/amuse/community/seculartriple/src/cvode/cvode_spbcgs.c rename to src/tres/seculartriple/src/cvode/cvode_spbcgs.c diff --git a/src/amuse/community/seculartriple/src/cvode/cvode_spbcgs.h b/src/tres/seculartriple/src/cvode/cvode_spbcgs.h similarity index 100% rename from src/amuse/community/seculartriple/src/cvode/cvode_spbcgs.h rename to src/tres/seculartriple/src/cvode/cvode_spbcgs.h diff --git a/src/amuse/community/seculartriple/src/cvode/cvode_spgmr.c b/src/tres/seculartriple/src/cvode/cvode_spgmr.c similarity index 100% rename from src/amuse/community/seculartriple/src/cvode/cvode_spgmr.c rename to src/tres/seculartriple/src/cvode/cvode_spgmr.c diff --git a/src/amuse/community/seculartriple/src/cvode/cvode_spgmr.h b/src/tres/seculartriple/src/cvode/cvode_spgmr.h similarity index 100% rename from src/amuse/community/seculartriple/src/cvode/cvode_spgmr.h rename to src/tres/seculartriple/src/cvode/cvode_spgmr.h diff --git a/src/amuse/community/seculartriple/src/cvode/cvode_spils.c b/src/tres/seculartriple/src/cvode/cvode_spils.c similarity index 100% rename from src/amuse/community/seculartriple/src/cvode/cvode_spils.c rename to src/tres/seculartriple/src/cvode/cvode_spils.c diff --git a/src/amuse/community/seculartriple/src/cvode/cvode_spils.h b/src/tres/seculartriple/src/cvode/cvode_spils.h similarity index 100% rename from src/amuse/community/seculartriple/src/cvode/cvode_spils.h rename to src/tres/seculartriple/src/cvode/cvode_spils.h diff --git a/src/amuse/community/seculartriple/src/cvode/cvode_spils_impl.h b/src/tres/seculartriple/src/cvode/cvode_spils_impl.h similarity index 100% rename from src/amuse/community/seculartriple/src/cvode/cvode_spils_impl.h rename to src/tres/seculartriple/src/cvode/cvode_spils_impl.h diff --git a/src/amuse/community/seculartriple/src/cvode/cvode_sptfqmr.c b/src/tres/seculartriple/src/cvode/cvode_sptfqmr.c similarity index 100% rename from src/amuse/community/seculartriple/src/cvode/cvode_sptfqmr.c rename to src/tres/seculartriple/src/cvode/cvode_sptfqmr.c diff --git a/src/amuse/community/seculartriple/src/cvode/cvode_sptfqmr.h b/src/tres/seculartriple/src/cvode/cvode_sptfqmr.h similarity index 100% rename from src/amuse/community/seculartriple/src/cvode/cvode_sptfqmr.h rename to src/tres/seculartriple/src/cvode/cvode_sptfqmr.h diff --git a/src/amuse/community/seculartriple/src/cvode/nvector_serial.c b/src/tres/seculartriple/src/cvode/nvector_serial.c similarity index 100% rename from src/amuse/community/seculartriple/src/cvode/nvector_serial.c rename to src/tres/seculartriple/src/cvode/nvector_serial.c diff --git a/src/amuse/community/seculartriple/src/cvode/nvector_serial.h b/src/tres/seculartriple/src/cvode/nvector_serial.h similarity index 100% rename from src/amuse/community/seculartriple/src/cvode/nvector_serial.h rename to src/tres/seculartriple/src/cvode/nvector_serial.h diff --git a/src/amuse/community/seculartriple/src/cvode/sundials_band.c b/src/tres/seculartriple/src/cvode/sundials_band.c similarity index 100% rename from src/amuse/community/seculartriple/src/cvode/sundials_band.c rename to src/tres/seculartriple/src/cvode/sundials_band.c diff --git a/src/amuse/community/seculartriple/src/cvode/sundials_band.h b/src/tres/seculartriple/src/cvode/sundials_band.h similarity index 100% rename from src/amuse/community/seculartriple/src/cvode/sundials_band.h rename to src/tres/seculartriple/src/cvode/sundials_band.h diff --git a/src/amuse/community/seculartriple/src/cvode/sundials_config.h b/src/tres/seculartriple/src/cvode/sundials_config.h similarity index 100% rename from src/amuse/community/seculartriple/src/cvode/sundials_config.h rename to src/tres/seculartriple/src/cvode/sundials_config.h diff --git a/src/amuse/community/seculartriple/src/cvode/sundials_dense.c b/src/tres/seculartriple/src/cvode/sundials_dense.c similarity index 100% rename from src/amuse/community/seculartriple/src/cvode/sundials_dense.c rename to src/tres/seculartriple/src/cvode/sundials_dense.c diff --git a/src/amuse/community/seculartriple/src/cvode/sundials_dense.h b/src/tres/seculartriple/src/cvode/sundials_dense.h similarity index 100% rename from src/amuse/community/seculartriple/src/cvode/sundials_dense.h rename to src/tres/seculartriple/src/cvode/sundials_dense.h diff --git a/src/amuse/community/seculartriple/src/cvode/sundials_direct.c b/src/tres/seculartriple/src/cvode/sundials_direct.c similarity index 100% rename from src/amuse/community/seculartriple/src/cvode/sundials_direct.c rename to src/tres/seculartriple/src/cvode/sundials_direct.c diff --git a/src/amuse/community/seculartriple/src/cvode/sundials_direct.h b/src/tres/seculartriple/src/cvode/sundials_direct.h similarity index 100% rename from src/amuse/community/seculartriple/src/cvode/sundials_direct.h rename to src/tres/seculartriple/src/cvode/sundials_direct.h diff --git a/src/amuse/community/seculartriple/src/cvode/sundials_iterative.c b/src/tres/seculartriple/src/cvode/sundials_iterative.c similarity index 100% rename from src/amuse/community/seculartriple/src/cvode/sundials_iterative.c rename to src/tres/seculartriple/src/cvode/sundials_iterative.c diff --git a/src/amuse/community/seculartriple/src/cvode/sundials_iterative.h b/src/tres/seculartriple/src/cvode/sundials_iterative.h similarity index 100% rename from src/amuse/community/seculartriple/src/cvode/sundials_iterative.h rename to src/tres/seculartriple/src/cvode/sundials_iterative.h diff --git a/src/amuse/community/seculartriple/src/cvode/sundials_math.c b/src/tres/seculartriple/src/cvode/sundials_math.c similarity index 100% rename from src/amuse/community/seculartriple/src/cvode/sundials_math.c rename to src/tres/seculartriple/src/cvode/sundials_math.c diff --git a/src/amuse/community/seculartriple/src/cvode/sundials_math.h b/src/tres/seculartriple/src/cvode/sundials_math.h similarity index 100% rename from src/amuse/community/seculartriple/src/cvode/sundials_math.h rename to src/tres/seculartriple/src/cvode/sundials_math.h diff --git a/src/amuse/community/seculartriple/src/cvode/sundials_nvector.c b/src/tres/seculartriple/src/cvode/sundials_nvector.c similarity index 100% rename from src/amuse/community/seculartriple/src/cvode/sundials_nvector.c rename to src/tres/seculartriple/src/cvode/sundials_nvector.c diff --git a/src/amuse/community/seculartriple/src/cvode/sundials_nvector.h b/src/tres/seculartriple/src/cvode/sundials_nvector.h similarity index 100% rename from src/amuse/community/seculartriple/src/cvode/sundials_nvector.h rename to src/tres/seculartriple/src/cvode/sundials_nvector.h diff --git a/src/amuse/community/seculartriple/src/cvode/sundials_spbcgs.c b/src/tres/seculartriple/src/cvode/sundials_spbcgs.c similarity index 100% rename from src/amuse/community/seculartriple/src/cvode/sundials_spbcgs.c rename to src/tres/seculartriple/src/cvode/sundials_spbcgs.c diff --git a/src/amuse/community/seculartriple/src/cvode/sundials_spbcgs.h b/src/tres/seculartriple/src/cvode/sundials_spbcgs.h similarity index 100% rename from src/amuse/community/seculartriple/src/cvode/sundials_spbcgs.h rename to src/tres/seculartriple/src/cvode/sundials_spbcgs.h diff --git a/src/amuse/community/seculartriple/src/cvode/sundials_spgmr.c b/src/tres/seculartriple/src/cvode/sundials_spgmr.c similarity index 100% rename from src/amuse/community/seculartriple/src/cvode/sundials_spgmr.c rename to src/tres/seculartriple/src/cvode/sundials_spgmr.c diff --git a/src/amuse/community/seculartriple/src/cvode/sundials_spgmr.h b/src/tres/seculartriple/src/cvode/sundials_spgmr.h similarity index 100% rename from src/amuse/community/seculartriple/src/cvode/sundials_spgmr.h rename to src/tres/seculartriple/src/cvode/sundials_spgmr.h diff --git a/src/amuse/community/seculartriple/src/cvode/sundials_sptfqmr.c b/src/tres/seculartriple/src/cvode/sundials_sptfqmr.c similarity index 100% rename from src/amuse/community/seculartriple/src/cvode/sundials_sptfqmr.c rename to src/tres/seculartriple/src/cvode/sundials_sptfqmr.c diff --git a/src/amuse/community/seculartriple/src/cvode/sundials_sptfqmr.h b/src/tres/seculartriple/src/cvode/sundials_sptfqmr.h similarity index 100% rename from src/amuse/community/seculartriple/src/cvode/sundials_sptfqmr.h rename to src/tres/seculartriple/src/cvode/sundials_sptfqmr.h diff --git a/src/amuse/community/seculartriple/src/cvode/sundials_types.h b/src/tres/seculartriple/src/cvode/sundials_types.h similarity index 100% rename from src/amuse/community/seculartriple/src/cvode/sundials_types.h rename to src/tres/seculartriple/src/cvode/sundials_types.h diff --git a/src/amuse/community/seculartriple/src/helper_routines.c b/src/tres/seculartriple/src/helper_routines.c similarity index 100% rename from src/amuse/community/seculartriple/src/helper_routines.c rename to src/tres/seculartriple/src/helper_routines.c diff --git a/src/amuse/community/seculartriple/src/helper_routines.h b/src/tres/seculartriple/src/helper_routines.h similarity index 100% rename from src/amuse/community/seculartriple/src/helper_routines.h rename to src/tres/seculartriple/src/helper_routines.h diff --git a/src/amuse/community/seculartriple/src/main_code.c b/src/tres/seculartriple/src/main_code.c similarity index 100% rename from src/amuse/community/seculartriple/src/main_code.c rename to src/tres/seculartriple/src/main_code.c diff --git a/src/amuse/community/seculartriple/src/main_code.h b/src/tres/seculartriple/src/main_code.h similarity index 100% rename from src/amuse/community/seculartriple/src/main_code.h rename to src/tres/seculartriple/src/main_code.h diff --git a/src/amuse/community/seculartriple/src/tidal_friction_parameters.c b/src/tres/seculartriple/src/tidal_friction_parameters.c similarity index 100% rename from src/amuse/community/seculartriple/src/tidal_friction_parameters.c rename to src/tres/seculartriple/src/tidal_friction_parameters.c diff --git a/src/amuse/community/seculartriple/src/tidal_friction_parameters.h b/src/tres/seculartriple/src/tidal_friction_parameters.h similarity index 100% rename from src/amuse/community/seculartriple/src/tidal_friction_parameters.h rename to src/tres/seculartriple/src/tidal_friction_parameters.h diff --git a/src/amuse/community/seculartriple/tidal_friction_constant.py b/src/tres/seculartriple/tidal_friction_constant.py similarity index 100% rename from src/amuse/community/seculartriple/tidal_friction_constant.py rename to src/tres/seculartriple/tidal_friction_constant.py diff --git a/src/tres/setup.py b/src/tres/setup.py index 7240745..13868c3 100644 --- a/src/tres/setup.py +++ b/src/tres/setup.py @@ -1,10 +1,11 @@ +import sys import numpy as np from amuse.community.seba import Seba from amuse.datamodel import Particles from amuse.units import units -from tres.seculartriple_TPS.interface import SecularTriple +from tres.seculartriple import Seculartriple from tres.options import max_mass, absolute_min_mass from tres.interactions import * from tres.tidal_friction_constant import * @@ -220,82 +221,148 @@ def setup_stellar_code(stellar_code, stars): return stellar_code -def setup_secular_code(triple, secular_code, stop_at_semisecular_regime): - triple_set = triple.as_set() - triple_time = triple_set.time - secular_code.triples.add_particles(triple_set) - secular_code.parameters.verbose = False - # secular_code.parameters.verbose = True - - # needed for initialisation in some circumstances - secular_code.model_time = triple_time - - secular_code.parameters.equations_of_motion_specification = 0 - secular_code.parameters.roche_radius_specification = 0 - # 0: eccentric eggleton, 1: sepinsky, 2: classical circular eggleton - secular_code.parameters.stability_limit_specification = 0 - # for stars 0, 5-6, for exoplanets 1-4 - # 0: mardling & aarseth 2001, 1:petrovich et al. 2015 simple, 2:petrovich et al. 2015 - # 3: holman et al. 98 s-type, 4: holman et al. 98 p-type, - # 5: vynatheya+ 22 - # 6: tory+ 22 - - secular_code.parameters.ignore_tertiary = False - - secular_code.parameters.include_quadrupole_terms = True - secular_code.parameters.include_octupole_terms = True - secular_code.parameters.include_inner_wind_terms = True - secular_code.parameters.include_outer_wind_terms = True - secular_code.parameters.include_inner_RLOF_terms = True - secular_code.parameters.include_outer_RLOF_terms = True - secular_code.parameters.include_magnetic_braking_terms = False # not tested - - secular_code.parameters.include_inner_tidal_terms = True - secular_code.parameters.include_outer_tidal_terms = True - - secular_code.parameters.include_1PN_inner_terms = True - secular_code.parameters.include_1PN_outer_terms = True - secular_code.parameters.include_1PN_inner_outer_terms = ( - False ### warning: probably broken - ) - secular_code.parameters.include_25PN_inner_terms = True - secular_code.parameters.include_25PN_outer_terms = True +def setup_secular_code( + triple, + secular_code, + stop_at_semisecular_regime, +): + code_module = secular_code.__module__.split('.')[-2] + print(f"Using code {code_module}") + + if code_module == "seculartriple": + triple_set = triple.as_set() + triple_time = triple_set.time + secular_code.triples.add_particles(triple_set) + secular_code.parameters.verbose = False + # secular_code.parameters.verbose = True + + # needed for initialisation in some circumstances + secular_code.model_time = triple_time + + secular_code.parameters.equations_of_motion_specification = 0 + secular_code.parameters.roche_radius_specification = 0 + # 0: eccentric eggleton, 1: sepinsky, 2: classical circular eggleton + secular_code.parameters.stability_limit_specification = 0 + # for stars 0, 5-6, for exoplanets 1-4 + # 0: mardling & aarseth 2001, 1:petrovich et al. 2015 simple, 2:petrovich et al. 2015 + # 3: holman et al. 98 s-type, 4: holman et al. 98 p-type, + # 5: vynatheya+ 22 + # 6: tory+ 22 + + secular_code.parameters.ignore_tertiary = False + + secular_code.parameters.include_quadrupole_terms = True + secular_code.parameters.include_octupole_terms = True + secular_code.parameters.include_inner_wind_terms = True + secular_code.parameters.include_outer_wind_terms = True + secular_code.parameters.include_inner_RLOF_terms = True + secular_code.parameters.include_outer_RLOF_terms = True + secular_code.parameters.include_magnetic_braking_terms = False # not tested + + secular_code.parameters.include_inner_tidal_terms = True + secular_code.parameters.include_outer_tidal_terms = True + + secular_code.parameters.include_1PN_inner_terms = True + secular_code.parameters.include_1PN_outer_terms = True + secular_code.parameters.include_1PN_inner_outer_terms = ( + False ### warning: probably broken + ) + secular_code.parameters.include_25PN_inner_terms = True + secular_code.parameters.include_25PN_outer_terms = True - secular_code.parameters.check_for_dynamical_stability = True - secular_code.parameters.check_for_dynamical_stability_at_initialisation = True + secular_code.parameters.check_for_dynamical_stability = True + secular_code.parameters.check_for_dynamical_stability_at_initialisation = True - secular_code.parameters.check_for_semisecular_regime = stop_at_semisecular_regime - secular_code.parameters.check_for_semisecular_regime_at_initialisation = ( - stop_at_semisecular_regime - ) + secular_code.parameters.check_for_semisecular_regime = ( + stop_at_semisecular_regime + ) + secular_code.parameters.check_for_semisecular_regime_at_initialisation = ( + stop_at_semisecular_regime + ) - secular_code.parameters.check_for_inner_collision = True - secular_code.parameters.check_for_outer_collision = True + secular_code.parameters.check_for_inner_collision = True + secular_code.parameters.check_for_outer_collision = True - secular_code.parameters.check_for_inner_RLOF = True - secular_code.parameters.check_for_outer_RLOF = True + secular_code.parameters.check_for_inner_RLOF = True + secular_code.parameters.check_for_outer_RLOF = True - secular_code.parameters.include_spin_radius_mass_coupling_terms_star1 = True - secular_code.parameters.include_spin_radius_mass_coupling_terms_star2 = True - secular_code.parameters.include_spin_radius_mass_coupling_terms_star3 = True + secular_code.parameters.include_spin_radius_mass_coupling_terms_star1 = True + secular_code.parameters.include_spin_radius_mass_coupling_terms_star2 = True + secular_code.parameters.include_spin_radius_mass_coupling_terms_star3 = True - # accuracy of secular code - # secular_code.parameters.input_precision = 1.0e-10#1.0e-5 - # secular_code.parameters.relative_tolerance = 1.0e-10 - # secular_code.parameters.threshold_value_of_e_in_for_setting_tidal_e_in_dot_zero = 1.0e-12 - secular_code.parameters.threshold_value_of_spin_angular_frequency_for_setting_spin_angular_frequency_dot_moment_of_inertia_plus_wind_changes_zero = ( - 1.0e-7 | units.Myr**-1 - ) + # accuracy of secular code + # secular_code.parameters.input_precision = 1.0e-10#1.0e-5 + # secular_code.parameters.relative_tolerance = 1.0e-10 + # secular_code.parameters.threshold_value_of_e_in_for_setting_tidal_e_in_dot_zero = 1.0e-12 + secular_code.parameters.threshold_value_of_spin_angular_frequency_for_setting_spin_angular_frequency_dot_moment_of_inertia_plus_wind_changes_zero = ( + 1.0e-7 | units.Myr**-1 + ) - secular_code.parameters.include_linear_mass_change = ( - True # needed for Jspin conservation - ) - secular_code.parameters.include_linear_radius_change = ( - True # needed for Jspin conservation - ) + secular_code.parameters.include_linear_mass_change = ( + True # needed for Jspin conservation + ) + secular_code.parameters.include_linear_radius_change = ( + True # needed for Jspin conservation + ) - # channel_from_secular = secular_code.triples.new_channel_to(triple_set) - # channel_to_secular = triple_set.new_channel_to(secular_code.triples) + # channel_from_secular = secular_code.triples.new_channel_to(triple_set) + # channel_to_secular = triple_set.new_channel_to(secular_code.triples) + + elif code_module == "secularmultiple": + def sectrip_to_secmul(p): + """ + Unpacks the triple into "binary" particles and "star" particles and + returns a Particles object of these. + """ + s = Particles() + if hasattr(p, "child1"): + s.add_particles( + sectrip_to_secmul(p.child1) + ) + p.is_binary = True + if hasattr(p, "child2"): + s.add_particles( + sectrip_to_secmul(p.child2) + ) + p.is_binary = True + s.add_particle(p) + return s + triple_set = sectrip_to_secmul(triple) + # triple_set = triple.as_set() + triple_time = triple_set.time + if not hasattr(triple_set, "inclination"): + triple_set.inclination = 0 + if not hasattr(triple_set, "include_pairwise_1PN_terms"): + triple_set.include_pairwise_1PN_terms = False + print(triple_set) + # filtered_set = Particles(keys=triple_set.key) + # triple_set.new_channel_to( + # filtered_set, + # attributes=[ + # "argument_of_pericenter", + # "child1", + # "child2", + # "eccentricity", + # "inclination", + # "include_pairwise_1PN_terms", + # "is_binary", + # "longitude_of_ascending_node", + # "mass", + # "semimajor_axis", + # ] + # ).copy() + # print(filtered_set) + secular_code.particles.add_particles(triple_set) + + # needed for initialisation in some circumstances + secular_code.model_time = triple_time + + secular_code.parameters.include_quadrupole_order_terms = True + secular_code.parameters.include_octupole_order_binary_pair_terms = True + secular_code.parameters.include_octupole_order_binary_triplet_terms = False + + # accuracy of secular code + # secular_code.parameters.relative_tolerance = 1.0e-10 return secular_code diff --git a/src/tres/tps.py b/src/tres/tps.py index 8e3548d..19ab5f6 100644 --- a/src/tres/tps.py +++ b/src/tres/tps.py @@ -148,7 +148,6 @@ ## -s random seed """ - import sys import numpy as np from scipy.interpolate import interp1d diff --git a/src/tres/tres.py b/src/tres/tres.py index f17ff09..5cc229b 100644 --- a/src/tres/tres.py +++ b/src/tres/tres.py @@ -11,11 +11,11 @@ from amuse.units import units from amuse.support.console import set_printing_strategy -from amuse.community.seba.interface import SeBa +from amuse.community.seba import Seba -from tres.seculartriple_TPS.interface import SecularTriple -from tres.triple_class import Triple_Class -from tres.plotting import plot_data_container, plot_function +from tres.seculartriple import Seculartriple +from tres.triple_class import Triple +from tres.plotting import PlotDataContainer, plot_function from tres.setup import make_particle_sets, setup_stellar_code from tres.options import ( REPORT_DEBUG, @@ -29,6 +29,7 @@ break_up_angular_frequency, criticial_angular_frequency_CHE, ) + # from interactions import * # from tidal_friction_constant import * @@ -72,7 +73,7 @@ def initialize_triple_class( dir_plots="", ): - triple = Triple_Class( + triple = Triple( stars, bins, correct_params, @@ -116,12 +117,12 @@ def initialize_triple_class( # ----- # for running TRES.py from other routines -def main( +def tres_main( inner_primary_mass=1.3 | units.MSun, inner_secondary_mass=0.5 | units.MSun, outer_mass=0.5 | units.MSun, - inner_semimajor_axis=1.0 | units.AU, - outer_semimajor_axis=100.0 | units.AU, + inner_semimajor_axis=1.0 | units.au, + outer_semimajor_axis=100.0 | units.au, inner_eccentricity=0.1, outer_eccentricity=0.5, relative_inclination=80.0 * np.pi / 180.0, @@ -195,19 +196,19 @@ def main( clean_up_stellar_code = False clean_up_secular_code = False if stellar_code is None: - stellar_code = SeBa() - # stellar_code = SeBa(redirection='none') - # stellar_code = SeBa(redirection='file', redirect_file='output_SeBa_TRES.txt') + stellar_code = Seba() + # stellar_code = Seba(redirection='none') + # stellar_code = Seba(redirection='file', redirect_file='output_SeBa_TRES.txt') clean_up_stellar_code = True stellar_code.parameters.metallicity = metallicity if secular_code is None: - secular_code = SecularTriple() - # secular_code = SecularTriple(redirection='none') - # secular_code = SecularTriple(redirection='file', redirect_file='output_SecularTriple_TRES.txt') + secular_code = Seculartriple() + # secular_code = Seculartriple(redirection='none') + # secular_code = Seculartriple(redirection='file', redirect_file='output_SecularTriple_TRES.txt') clean_up_secular_code = True - triple_class_object = Triple_Class( + triple_class_object = Triple( stars, bins, correct_params, @@ -295,7 +296,7 @@ def main( return triple_class_object -def main_developer( +def tres_main_developer( stars, bins, correct_params, @@ -351,7 +352,7 @@ def main_developer( bins.longitude_of_ascending_node[1] = float(bins.longitude_of_ascending_node[1]) relative_inclination = float(relative_inclination) - triple_class_object = Triple_Class( + triple_class_object = Triple( stars, bins, correct_params, @@ -392,31 +393,36 @@ def main_developer( if triple_class_object.correct_params is False: if REPORT_USER_WARNINGS: print( - "Choose a different system. The parameters of the given triple are incorrect." + "Choose a different system. The parameters of the given triple are " + "incorrect." ) return triple_class_object # no codes initialized yet - elif ( + if ( stop_at_semisecular_regime is True and triple_class_object.semisecular_regime_at_initialisation is True ): if REPORT_USER_WARNINGS: print( - "Choose a different system. The given triple is in the semisecular regime at initialization." + "Choose a different system. The given triple is in the semisecular " + "regime at initialization." ) elif triple_class_object.dynamical_instability_at_initialisation is True: if REPORT_USER_WARNINGS: print( - "Choose a different system. The given triple is dynamically unstable at initialization." + "Choose a different system. The given triple is dynamically unstable " + "at initialization." ) elif triple_class_object.mass_transfer_at_initialisation is True: if REPORT_USER_WARNINGS: print( - "Choose a different system. There is mass transfer in the given triple at initialization." + "Choose a different system. There is mass transfer in the given triple " + "at initialization." ) elif stop_at_no_CHE is True and triple_class_object.CHE_at_initialisation is False: if REPORT_USER_WARNINGS: print( - "Choose a different system. No chemically homogeneous evolution at initialization" + "Choose a different system. No chemically homogeneous evolution at " + "initialization" ) else: triple_class_object.evolve_model(tend) @@ -526,10 +532,14 @@ def parse_arguments(): default=0.0 | units.rad, help="inner longitude of ascending node [rad]", ) - ## outer longitude of ascending nodes = inner - pi - # parser.add_argument("-o", - # dest="outer_longitude_of_ascending_node", type=float, default = 0.0, - # help="outer longitude of ascending node [rad]") + # outer longitude of ascending nodes = inner - pi + # parser.add_argument( + # "-o", + # dest="outer_longitude_of_ascending_node", + # type=units.rad, + # default=0.0 | units.rad, + # help="outer longitude of ascending node" + # ) parser.add_argument( "-z", @@ -569,8 +579,13 @@ def parse_arguments(): help="maximum_radius_change_factor", ) - # parser.add_argument("--tidal", dest="tidal_terms", action="store_false", default = True, - # help="tidal terms included %unit") + # parser.add_argument( + # "--tidal", + # dest="tidal_terms", + # action="store_false", + # default=True, + # help="tidal terms included" + # ) parser.add_argument( "--no_stop_at_mass_transfer", @@ -594,7 +609,8 @@ def parse_arguments(): help="stop at triple mass transfer", ) - # if stop_at_mass_transfer is False, the following 4 stopping conditions can be used to further specify. + # if stop_at_mass_transfer is False, the following 4 stopping conditions + # can be used to further specify. # if stop_at_mass_transfer is True, the following 4 are ignored. parser.add_argument( "--stop_at_stable_mass_transfer", @@ -762,7 +778,7 @@ def parse_arguments(): "--dir_plots", dest="dir_plots", type=str, - default="", # "txt" + default="", help="directory for plots for debugging mode", ) @@ -770,7 +786,7 @@ def parse_arguments(): return args.__dict__ -if __name__ == "__main__": +def main(): arg = parse_arguments() set_printing_strategy( @@ -796,15 +812,15 @@ def parse_arguments(): arg["inner_longitude_of_ascending_node"], ) - stellar_code = SeBa() - # stellar_code = SeBa(redirection='none') - # stellar_code = SeBa(redirection='file', redirect_file='output_SeBa_TRES.txt') - stellar_code.parameters.metallicity = opt["metallicity"] - secular_code = SecularTriple() - # secular_code = SecularTriple(redirection='none') - # secular_code = SecularTriple(redirection='file', redirect_file='output_SecularTriple_TRES.txt') + stellar_code = Seba() + # stellar_code = Seba(redirection='none') + # stellar_code = Seba(redirection='file', redirect_file='output_SeBa_TRES.txt') + stellar_code.parameters.metallicity = arg["metallicity"] + secular_code = Seculartriple() + # secular_code = Seculartriple(redirection='none') + # secular_code = Seculartriple(redirection='file', redirect_file='output_SecularTriple_TRES.txt') - triple_class_object = Triple_Class( + triple_class_object = Triple( stars, bins, correct_params, @@ -892,3 +908,8 @@ def parse_arguments(): triple_class_object.stellar_code.stop() triple_class_object.secular_code.stop() + + +if __name__ == "__main__": + # main() + tres_main() diff --git a/src/tres/triple_class.py b/src/tres/triple_class.py index a98bc5f..2db58e9 100644 --- a/src/tres/triple_class.py +++ b/src/tres/triple_class.py @@ -11,8 +11,8 @@ import numpy as np # FIXME SR: don't import * here -from tres.interactions import * -from tres.tidal_friction_constant import * +from tres import interactions +import tres.tidal_friction_constant as tfc # from tres.options import REPORT_USER_WARNINGS, \ # GET_GYRATION_RADIUS_FROM_STELLAR_CODE, \ @@ -25,7 +25,7 @@ # maximum_time_step_factor, \ # minimum_time_step -from tres.options import * +from tres import options from tres.setup import setup_secular_code, setup_stellar_code from tres.plotting import PlotDataContainer @@ -92,7 +92,7 @@ def __init__( self.file_type = file_type self.which_common_envelope = which_common_envelope self.include_CHE = include_CHE - if REPORT_USER_WARNINGS and self.include_CHE: + if options.REPORT_USER_WARNINGS and self.include_CHE: print( "Note: For CHE evolution to be included, it also needs to be switched on manually in SeBa." ) @@ -152,7 +152,7 @@ def __init__( or self.stop_at_init_mass_transfer ): self.mass_transfer_at_initialisation = True - self.triple.bin_type = bin_type["rlof"] + self.triple.bin_type = interactions.bin_type["rlof"] return self.check_OLOF() @@ -166,20 +166,17 @@ def __init__( self.mass_transfer_at_initialisation = True # assuming object is triple as is triple constructor if self.is_binary(self.triple.child1): - bin = self.triple.child1 + binary = self.triple.child1 else: - bin = self.triple.child2 + binary = self.triple.child2 - if bin.child1.is_OLOF_donor or bin.child2.is_OLOF_donor: - bin.bin_type = bin_type["olof"] + if binary.child1.is_OLOF_donor or binary.child2.is_OLOF_donor: + binary.bin_type = interactions.bin_type["olof"] return - elif bin.child1.is_donor and bin.child2.is_donor: - bin.bin_type = bin_type["contact"] + if binary.child1.is_donor and binary.child2.is_donor: + binary.bin_type = interactions.bin_type["contact"] return - else: - bin.bin_type = bin_type["rlof"] - return - + binary.bin_type = interactions.bin_type["rlof"] return self.triple.kozai_type = self.get_kozai_type() @@ -202,14 +199,27 @@ def initialize_secular( self.secular_code = setup_secular_code( self.triple, secular_code, stop_at_semisecular_regime ) - self.channel_from_secular = self.secular_code.triples.new_channel_to(triple_set) - self.channel_to_secular = triple_set.new_channel_to(self.secular_code.triples) + secularcode_module = secular_code.__module__.split('.')[-2] + if secularcode_module == "seculartriple": + codeparticles = self.secular_code.triples + else: + codeparticles = self.secular_code.particles + self.channel_from_secular = codeparticles.new_channel_to( + triple_set + ) + self.channel_to_secular = triple_set.new_channel_to( + codeparticles + ) + print("PRINTING CODE PARTICLES") + print(codeparticles.argument_of_pericenter) + codeparticles.argument_of_pericenter = codeparticles.argument_of_pericenter * 0.1 + print("DONE") self.channel_to_secular.copy() self.secular_code.check_for_dynamical_stability() if ( stop_at_dynamical_instability is True - and self.secular_code.triples[0].dynamical_instability is True + and codeparticles[0].dynamical_instability is True ): self.dynamical_instability_at_initialisation = True self.triple.dynamical_instability = True @@ -219,7 +229,7 @@ def initialize_secular( self.secular_code.check_for_semisecular_regime() if ( stop_at_semisecular_regime is True - and self.secular_code.triples[0].semisecular_regime is True + and codeparticles[0].semisecular_regime is True ): self.semisecular_regime_at_initialisation = True self.triple.semisecular_regime = True @@ -305,9 +315,9 @@ def copy_from_stellar(self): "temperature", ] ) - if GET_GYRATION_RADIUS_FROM_STELLAR_CODE: + if options.GET_GYRATION_RADIUS_FROM_STELLAR_CODE: self.channel_from_stellar.copy_attributes(["gyration_radius"]) - if GET_AMC_FROM_STELLAR_CODE: + if options.GET_AMC_FROM_STELLAR_CODE: self.channel_from_stellar.copy_attributes(["apsidal_motion_constant"]) # ------- @@ -318,17 +328,17 @@ def initial_angular_frequency(self, stellar_system=None): self.previous_time = self.triple.time if stellar_system.is_star: - if stellar_system.stellar_type in stellar_types_planetary_objects: + if stellar_system.stellar_type in interactions.stellar_types_planetary_objects: stellar_system.spin_angular_frequency = ( - 0.125 * break_up_angular_frequency(stellar_system) + 0.125 * interactions.break_up_angular_frequency(stellar_system) ) else: - stellar_system.spin_angular_frequency = lang_spin_angular_frequency( + stellar_system.spin_angular_frequency = interactions.lang_spin_angular_frequency( stellar_system ) if self.include_CHE: # sets initial spin to corotation stellar_system.spin_angular_frequency = ( - corotating_spin_angular_frequency_binary( + interactions.corotating_spin_angular_frequency_binary( stellar_system.parent.semimajor_axis, self.get_mass(stellar_system.parent.child1), self.get_mass(stellar_system.parent.child2), @@ -481,11 +491,11 @@ def update_stellar_parameters(self, stellar_system=None): if stellar_system.is_star: - if not GET_GYRATION_RADIUS_FROM_STELLAR_CODE: - stellar_system.gyration_radius = set_gyration_radius( + if not options.GET_GYRATION_RADIUS_FROM_STELLAR_CODE: + stellar_system.gyration_radius = tfc.tidal_friction_constant.set_gyration_radius( stellar_system.stellar_type, stellar_system.mass ) - if not GET_AMC_FROM_STELLAR_CODE: + if not options.GET_AMC_FROM_STELLAR_CODE: stellar_system.apsidal_motion_constant = self.apsidal_motion_constant( stellar_system ) @@ -506,7 +516,7 @@ def update_stellar_parameters(self, stellar_system=None): # This is only possible for BH & NS as other stars would fill their RL earlier # To avoid this articially increase stellar radii of BH/NS in secular code # Does not affect any other processes - if stellar_system.stellar_type in stellar_types_SN_remnants: + if stellar_system.stellar_type in interactions.stellar_types_SN_remnants: stellar_system.radius = stellar_system.radius * 10 else: @@ -525,14 +535,11 @@ def is_binary(self, stellar_system=None): if stellar_system is None: stellar_system = self.triple - if ( + return ( not stellar_system.is_star and stellar_system.child1.is_star and stellar_system.child2.is_star - ): - return True - else: - return False + ) def is_triple(self, stellar_system=None): if stellar_system is None: @@ -584,7 +591,7 @@ def has_contact_system(self, stellar_system=None): if stellar_system.is_star: return False - elif self.is_binary(stellar_system): + if self.is_binary(stellar_system): if stellar_system.child1.is_donor and stellar_system.child2.is_donor: return True else: @@ -607,7 +614,7 @@ def has_merger(self, stellar_system=None): return True if self.has_merger(stellar_system.child2): return True - if stellar_system.bin_type == bin_type["merger"]: + if stellar_system.bin_type == interactions.bin_type["merger"]: return True return False @@ -624,7 +631,7 @@ def has_disintegrated(self, stellar_system=None): return True if self.has_disintegrated(stellar_system.child2): return True - if stellar_system.bin_type == bin_type["disintegrated"]: + if stellar_system.bin_type == interactions.bin_type["disintegrated"]: return True return False @@ -641,7 +648,7 @@ def has_dynamical_instability(self, stellar_system=None): return True if self.has_dynamical_instability(stellar_system.child2): return True - if stellar_system.bin_type == bin_type["dyn_inst"]: + if stellar_system.bin_type == interactions.bin_type["dyn_inst"]: return True return False @@ -652,7 +659,7 @@ def set_bintype_to_dynamical_instability(self, stellar_system=None): stellar_system = self.triple if stellar_system.is_star is False: - stellar_system.bin_type = bin_type["dyn_inst"] + stellar_system.bin_type = interactions.bin_type["dyn_inst"] self.set_bintype_to_dynamical_instability(stellar_system.child1) self.set_bintype_to_dynamical_instability(stellar_system.child2) @@ -709,7 +716,7 @@ def contains_SN_remnant(self, stellar_system=None): stellar_system = self.triple if stellar_system.is_star: - if stellar_system.stellar_type in stellar_types_SN_remnants: + if stellar_system.stellar_type in interactions.stellar_types_SN_remnants: return True else: if self.contains_SN_remnant( @@ -726,7 +733,7 @@ def has_stellar_type_changed_into_SN_remnant(self, stellar_system=None): if stellar_system.is_star: if ( stellar_system.stellar_type != stellar_system.previous_stellar_type - and stellar_system.stellar_type in stellar_types_SN_remnants + and stellar_system.stellar_type in interactions.stellar_types_SN_remnants ): return True else: @@ -794,8 +801,7 @@ def get_size(self, stellar_system=None): if stellar_system.is_star: return stellar_system.radius - else: - return stellar_system.semimajor_axis + return stellar_system.semimajor_axis # ------- @@ -821,12 +827,11 @@ def orbital_angular_momentum(self, bs): e = bs.eccentricity J = M * m * np.sqrt(constants.G * a * (1 - e**2) / (M + m)) - if REPORT_BINARY_EVOLUTION: + if options.REPORT_BINARY_EVOLUTION: print("Jorb:", M, m, a, e, J) return J - else: - sys.exit("orbital_angular_momentum: single star does not have an orbit") + sys.exit("orbital_angular_momentum: single star does not have an orbit") def spin_angular_momentum(self, ss): if ss.is_star: @@ -869,13 +874,13 @@ def apsidal_motion_constant(self, star): def moment_of_inertia(self, star): if star.is_star: - if GET_GYRATION_RADIUS_FROM_STELLAR_CODE: + if options.GET_GYRATION_RADIUS_FROM_STELLAR_CODE: I = star.gyration_radius**2 * (star.mass) * star.radius**2 else: k2 = 0.1 k3 = 0.21 - if star.stellar_type in stellar_types_remnants: + if star.stellar_type in interactions.stellar_types_remnants: I = k3 * (star.mass) * star.radius**2 else: I = ( @@ -891,15 +896,15 @@ def octupole_parameter(self): if self.is_triple(): if self.triple.child1.is_star: star = self.triple.child1 - bin = self.triple.child2 + binary = self.triple.child2 else: star = self.triple.child2 - bin = self.triple.child1 + binary = self.triple.child1 return ( - (self.get_mass(bin.child1) - self.get_mass(bin.child2)) - / self.get_mass(bin) - * bin.semimajor_axis + (self.get_mass(binary.child1) - self.get_mass(binary.child2)) + / self.get_mass(binary) + * binary.semimajor_axis / self.triple.semimajor_axis * self.triple.eccentricity / (1 - self.triple.eccentricity**2) @@ -914,12 +919,12 @@ def kozai_timescale(self): alpha_kozai = 1.0 if self.triple.child1.is_star: star = self.triple.child1 - bin = self.triple.child2 + binary = self.triple.child2 else: star = self.triple.child2 - bin = self.triple.child1 + binary = self.triple.child1 - P_in = self.orbital_period(bin) # period inner binary + P_in = self.orbital_period(binary) # period inner binary P_out = self.orbital_period(self.triple) # period outer binary return ( alpha_kozai @@ -939,11 +944,11 @@ def get_kozai_type(self): return False t_kozai = self.kozai_timescale() - if t_kozai > kozai_type_factor * self.tend: + if t_kozai > options.kozai_type_factor * self.tend: return False t_ev = self.get_min_stellar_evolution_timescale_of_system() - if t_kozai < kozai_type_factor * t_ev: + if t_kozai < options.kozai_type_factor * t_ev: return True else: return False @@ -955,7 +960,7 @@ def get_min_stellar_evolution_timescale_of_system(self, stellar_system=None): stellar_system = self.triple if stellar_system.is_star: - return stellar_evolution_timescale(stellar_system) + return interactions.stellar_evolution_timescale(stellar_system) else: t1 = self.get_min_stellar_evolution_timescale_of_system( stellar_system.child1 @@ -969,9 +974,9 @@ def check_RLOF(self): if self.triple.is_star: return elif self.is_binary(): - Rl1 = roche_radius(self, self.child1) - Rl2 = roche_radius(self, self.child2) - if REPORT_TRIPLE_EVOLUTION: + Rl1 = interactions.roche_radius(self, self.child1) + Rl2 = interactions.roche_radius(self, self.child2) + if options.REPORT_TRIPLE_EVOLUTION: print("Roche lobe radii:", Rl1, Rl2) print( "Stellar radii:", @@ -983,11 +988,11 @@ def check_RLOF(self): self.triple.child2.is_donor = False if self.triple.child1.radius >= Rl1 - ( - 1.0 * small_numerical_error | units.RSun + 1.0 * options.small_numerical_error | units.RSun ): self.triple.child1.is_donor = True if self.triple.child2.radius >= Rl2 - ( - 1.0 * small_numerical_error | units.RSun + 1.0 * options.small_numerical_error | units.RSun ): self.triple.child2.is_donor = True @@ -998,18 +1003,18 @@ def check_RLOF(self): else: bin = self.triple.child1 - Rl1 = roche_radius(bin, bin.child1, self) - Rl2 = roche_radius(bin, bin.child2, self) - if REPORT_TRIPLE_EVOLUTION: + Rl1 = interactions.roche_radius(bin, bin.child1, self) + Rl2 = interactions.roche_radius(bin, bin.child2, self) + if options.REPORT_TRIPLE_EVOLUTION: print("Roche lobe radii:", Rl1, Rl2) print("Stellar radii:", bin.child1.radius, bin.child2.radius) bin.child1.is_donor = False bin.child2.is_donor = False - if bin.child1.radius >= Rl1 - (1.0 * small_numerical_error | units.RSun): + if bin.child1.radius >= Rl1 - (1.0 * options.small_numerical_error | units.RSun): bin.child1.is_donor = True - if bin.child2.radius >= Rl2 - (1.0 * small_numerical_error | units.RSun): + if bin.child2.radius >= Rl2 - (1.0 * options.small_numerical_error | units.RSun): bin.child2.is_donor = True elif self.is_triple(): @@ -1020,25 +1025,25 @@ def check_RLOF(self): star = self.triple.child2 bin = self.triple.child1 - # assumping secular code always returns inner binary first + # assuming secular code always returns inner binary first Rl1, Rl2, Rl3 = self.secular_code.give_roche_radii(self.triple) - if REPORT_TRIPLE_EVOLUTION: + if options.REPORT_TRIPLE_EVOLUTION: print("Roche lobe radii:", Rl1, Rl2, Rl3) print( "Stellar radii:", bin.child1.radius, bin.child2.radius, star.radius ) print( "binary Roche lobe radii:", - roche_radius(bin, bin.child1, self), - roche_radius(bin, bin.child2, self), - roche_radius(self.triple, star, self), + interactions.roche_radius(bin, bin.child1, self), + interactions.roche_radius(bin, bin.child2, self), + interactions.roche_radius(self.triple, star, self), ) print( "eccentric binary Roche lobe radii:", - roche_radius(bin, bin.child1, self) * (1 - bin.eccentricity), - roche_radius(bin, bin.child2, self) * (1 - bin.eccentricity), - roche_radius(self.triple, star, self) + interactions.roche_radius(bin, bin.child1, self) * (1 - bin.eccentricity), + interactions.roche_radius(bin, bin.child2, self) * (1 - bin.eccentricity), + interactions.roche_radius(self.triple, star, self) * (1 - self.triple.eccentricity), ) print("Masses:", bin.child1.mass, bin.child2.mass, star.mass) @@ -1061,11 +1066,11 @@ def check_RLOF(self): bin.child2.is_donor = False star.is_donor = False - if bin.child1.radius >= Rl1 - (1.0 * small_numerical_error | units.RSun): + if bin.child1.radius >= Rl1 - (1.0 * options.small_numerical_error | units.RSun): bin.child1.is_donor = True - if bin.child2.radius >= Rl2 - (1.0 * small_numerical_error | units.RSun): + if bin.child2.radius >= Rl2 - (1.0 * options.small_numerical_error | units.RSun): bin.child2.is_donor = True - if star.radius >= Rl3 - (1.0 * small_numerical_error | units.RSun): + if star.radius >= Rl3 - (1.0 * options.small_numerical_error | units.RSun): star.is_donor = True else: @@ -1075,9 +1080,9 @@ def check_OLOF(self): if self.triple.is_star: return elif self.is_binary(): - Rl2_1 = L2_radius(self, self.child1) - Rl2_2 = L2_radius(self, self.child2) - if REPORT_TRIPLE_EVOLUTION: + Rl2_1 = interactions.L2_radius(self, self.child1) + Rl2_2 = interactions.L2_radius(self, self.child2) + if options.REPORT_TRIPLE_EVOLUTION: print("L2 lobe radii:", Rl2_1, Rl2_2) print( "Stellar radii:", @@ -1089,11 +1094,11 @@ def check_OLOF(self): self.triple.child2.is_OLOF_donor = False if self.triple.child1.radius >= Rl2_1 - ( - 1.0 * small_numerical_error | units.RSun + 1.0 * options.small_numerical_error | units.RSun ): self.triple.child1.is_OLOF_donor = True if self.triple.child2.radius >= Rl2_2 - ( - 1.0 * small_numerical_error | units.RSun + 1.0 * options.small_numerical_error | units.RSun ): self.triple.child2.is_OLOF_donor = True @@ -1106,18 +1111,18 @@ def check_OLOF(self): star = self.triple.child2 bin = self.triple.child1 - Rl2_1 = L2_radius(bin, bin.child1, self) - Rl2_2 = L2_radius(bin, bin.child2, self) + Rl2_1 = interactions.L2_radius(bin, bin.child1, self) + Rl2_2 = interactions.L2_radius(bin, bin.child2, self) bin.child1.is_OLOF_donor = False bin.child2.is_OLOF_donor = False - if bin.child1.radius >= Rl2_1 - (1.0 * small_numerical_error | units.RSun): + if bin.child1.radius >= Rl2_1 - (1.0 * options.small_numerical_error | units.RSun): bin.child1.is_OLOF_donor = True - if bin.child2.radius >= Rl2_2 - (1.0 * small_numerical_error | units.RSun): + if bin.child2.radius >= Rl2_2 - (1.0 * options.small_numerical_error | units.RSun): bin.child2.is_OLOF_donor = True - if REPORT_TRIPLE_EVOLUTION: + if options.REPORT_TRIPLE_EVOLUTION: print("L2 lobe radii:", Rl2_1, Rl2_2) print("Stellar radii:", bin.child1.radius, bin.child2.radius) print("Masses:", bin.child1.mass, bin.child2.mass, star.mass) @@ -1153,12 +1158,12 @@ def check_CHE(self): # future option: potentially use: che_flag in SeBa if self.include_CHE and ( ( bin.child1.spin_angular_frequency - >= criticial_angular_frequency_CHE(bin.child1.mass, metallicity) + >= interactions.criticial_angular_frequency_CHE(bin.child1.mass, metallicity) and bin.child1.stellar_type <= 1 | units.stellar_type ) or ( bin.child2.spin_angular_frequency - >= criticial_angular_frequency_CHE(bin.child2.mass, metallicity) + >= interactions.criticial_angular_frequency_CHE(bin.child2.mass, metallicity) and bin.child2.stellar_type <= 1 | units.stellar_type ) ): @@ -1175,12 +1180,12 @@ def check_CHE(self): # future option: potentially use: che_flag in SeBa if self.include_CHE and ( ( bin.child1.spin_angular_frequency - >= criticial_angular_frequency_CHE(bin.child1.mass, metallicity) + >= interactions.criticial_angular_frequency_CHE(bin.child1.mass, metallicity) and bin.child1.stellar_type <= 1 | units.stellar_type ) or ( bin.child2.spin_angular_frequency - >= criticial_angular_frequency_CHE(bin.child2.mass, metallicity) + >= interactions.criticial_angular_frequency_CHE(bin.child2.mass, metallicity) and bin.child2.stellar_type <= 1 | units.stellar_type ) ): @@ -1328,7 +1333,7 @@ def remove_parents(self, stellar_system=None): p = stellar_system.parent # except AttributeError: #when there is no parent= - if p != None: + if p is not None: stellar_system.parent = 0 parents.append(p) @@ -1442,18 +1447,18 @@ def determine_time_step_wind(self, stellar_system=None): if stellar_system.wind_mass_loss_rate * -1.0 > quantities.zero: dt = ( - maximum_wind_mass_loss_factor + options.maximum_wind_mass_loss_factor * (stellar_system.mass - stellar_system.core_mass) / stellar_system.wind_mass_loss_rate * -1.0 ) - if REPORT_DT: + if options.REPORT_DT: print("Dt_wind_star = ", dt) return dt else: dt1 = self.determine_time_step_wind(stellar_system.child1) dt2 = self.determine_time_step_wind(stellar_system.child2) - if REPORT_DT: + if options.REPORT_DT: print("Dt_wind_binary = ", dt1, dt2) return min(dt1, dt2) @@ -1504,21 +1509,21 @@ def determine_time_step_radius_change(self, stellar_system=None): / stellar_system.time_derivative_of_radius ) - if REPORT_DT: + if options.REPORT_DT: print("Dt_radius_change_star = ", dt) return dt else: dt1 = self.determine_time_step_radius_change(stellar_system.child1) dt2 = self.determine_time_step_radius_change(stellar_system.child2) - if REPORT_DT: + if options.REPORT_DT: print("Dt_radius_change_binary = ", dt1, dt2) return min(dt1, dt2) def determine_time_step_kozai(self): # note: returned value can be inf when the system is a binary or single star if self.is_triple(): - dt = self.kozai_timescale() * time_step_factor_kozai - if REPORT_DT: + dt = self.kozai_timescale() * options.time_step_factor_kozai + if options.REPORT_DT: print("Dt_kozai = ", dt) else: dt = np.inf | units.Myr @@ -1536,15 +1541,15 @@ def determine_time_step_stable_mt(self, stellar_system=None): dt = np.inf | units.Myr if stellar_system.is_donor: dt = abs( - time_step_factor_stable_mt + options.time_step_factor_stable_mt * stellar_system.mass / stellar_system.parent.mass_transfer_rate ) - if REPORT_DT: + if options.REPORT_DT: print( "Dt_mt_star = ", dt, - time_step_factor_stable_mt, + options.time_step_factor_stable_mt, stellar_system.mass, stellar_system.parent.mass_transfer_rate, ) @@ -1552,7 +1557,7 @@ def determine_time_step_stable_mt(self, stellar_system=None): else: dt1 = self.determine_time_step_stable_mt(stellar_system.child1) dt2 = self.determine_time_step_stable_mt(stellar_system.child2) - if REPORT_DT: + if options.REPORT_DT: print("Dt_mt_binary = ", dt1, dt2) return min(dt1, dt2) @@ -1565,7 +1570,7 @@ def e_dot_tides(self, star, m_comp, semi, eccentricity): R_div_a = star.radius / semi spin = star.spin_angular_frequency - k_div_T_tides = tidal_friction_constant( + k_div_T_tides = tfc.tidal_friction_constant( star.stellar_type, star.mass, m_comp, @@ -1578,7 +1583,7 @@ def e_dot_tides(self, star, m_comp, semi, eccentricity): star.gyration_radius, star.apsidal_motion_constant, ) - n = corotating_spin_angular_frequency_binary( + n = interactions.corotating_spin_angular_frequency_binary( semi, star.mass, m_comp ) # mean orbital angular speed From 65817f34530655cab681562d12ea7e8e0cebc721 Mon Sep 17 00:00:00 2001 From: Steven Rieder Date: Fri, 8 Nov 2024 14:57:37 +0100 Subject: [PATCH 23/30] further progress towards better imports for variables [WIP] --- src/tres/triple_class.py | 478 +++++++++++++++++++++------------------ 1 file changed, 260 insertions(+), 218 deletions(-) diff --git a/src/tres/triple_class.py b/src/tres/triple_class.py index 2db58e9..3a2e673 100644 --- a/src/tres/triple_class.py +++ b/src/tres/triple_class.py @@ -94,10 +94,12 @@ def __init__( self.include_CHE = include_CHE if options.REPORT_USER_WARNINGS and self.include_CHE: print( - "Note: For CHE evolution to be included, it also needs to be switched on manually in SeBa." + "Note: For CHE evolution to be included, it also needs to be switched " + "on manually in SeBa." ) print( - "\t This can be done by setting include_CHE=True in SeBa's sstar/starclass/constants.C." + "\t This can be done by setting include_CHE=True in SeBa's " + "sstar/starclass/constants.C." ) print("\t AMUSE developer mode is required to access SeBa files.") self.SN_kick_distr = SN_kick_distr @@ -199,20 +201,18 @@ def initialize_secular( self.secular_code = setup_secular_code( self.triple, secular_code, stop_at_semisecular_regime ) - secularcode_module = secular_code.__module__.split('.')[-2] + secularcode_module = secular_code.__module__.split(".")[-2] if secularcode_module == "seculartriple": codeparticles = self.secular_code.triples else: codeparticles = self.secular_code.particles - self.channel_from_secular = codeparticles.new_channel_to( - triple_set - ) - self.channel_to_secular = triple_set.new_channel_to( - codeparticles - ) + self.channel_from_secular = codeparticles.new_channel_to(triple_set) + self.channel_to_secular = triple_set.new_channel_to(codeparticles) print("PRINTING CODE PARTICLES") print(codeparticles.argument_of_pericenter) - codeparticles.argument_of_pericenter = codeparticles.argument_of_pericenter * 0.1 + codeparticles.argument_of_pericenter = ( + codeparticles.argument_of_pericenter * 0.1 + ) print("DONE") self.channel_to_secular.copy() @@ -328,13 +328,16 @@ def initial_angular_frequency(self, stellar_system=None): self.previous_time = self.triple.time if stellar_system.is_star: - if stellar_system.stellar_type in interactions.stellar_types_planetary_objects: + if ( + stellar_system.stellar_type + in interactions.stellar_types_planetary_objects + ): stellar_system.spin_angular_frequency = ( 0.125 * interactions.break_up_angular_frequency(stellar_system) ) else: - stellar_system.spin_angular_frequency = interactions.lang_spin_angular_frequency( - stellar_system + stellar_system.spin_angular_frequency = ( + interactions.lang_spin_angular_frequency(stellar_system) ) if self.include_CHE: # sets initial spin to corotation stellar_system.spin_angular_frequency = ( @@ -492,8 +495,10 @@ def update_stellar_parameters(self, stellar_system=None): if stellar_system.is_star: if not options.GET_GYRATION_RADIUS_FROM_STELLAR_CODE: - stellar_system.gyration_radius = tfc.tidal_friction_constant.set_gyration_radius( - stellar_system.stellar_type, stellar_system.mass + stellar_system.gyration_radius = ( + tfc.tidal_friction_constant.set_gyration_radius( + stellar_system.stellar_type, stellar_system.mass + ) ) if not options.GET_AMC_FROM_STELLAR_CODE: stellar_system.apsidal_motion_constant = self.apsidal_motion_constant( @@ -733,7 +738,8 @@ def has_stellar_type_changed_into_SN_remnant(self, stellar_system=None): if stellar_system.is_star: if ( stellar_system.stellar_type != stellar_system.previous_stellar_type - and stellar_system.stellar_type in interactions.stellar_types_SN_remnants + and stellar_system.stellar_type + in interactions.stellar_types_SN_remnants ): return True else: @@ -875,20 +881,20 @@ def moment_of_inertia(self, star): if star.is_star: if options.GET_GYRATION_RADIUS_FROM_STELLAR_CODE: - I = star.gyration_radius**2 * (star.mass) * star.radius**2 + m_o_i = star.gyration_radius**2 * (star.mass) * star.radius**2 else: k2 = 0.1 k3 = 0.21 if star.stellar_type in interactions.stellar_types_remnants: - I = k3 * (star.mass) * star.radius**2 + m_o_i = k3 * (star.mass) * star.radius**2 else: - I = ( + m_o_i = ( k2 * (star.mass - star.core_mass) * star.radius**2 + k3 * star.core_mass * star.core_radius**2 ) - return I + return m_o_i else: sys.exit("moment_of_inertia: structure stellar system unknown") @@ -988,42 +994,46 @@ def check_RLOF(self): self.triple.child2.is_donor = False if self.triple.child1.radius >= Rl1 - ( - 1.0 * options.small_numerical_error | units.RSun + 1.0 * interactions.small_numerical_error | units.RSun ): self.triple.child1.is_donor = True if self.triple.child2.radius >= Rl2 - ( - 1.0 * options.small_numerical_error | units.RSun + 1.0 * interactions.small_numerical_error | units.RSun ): self.triple.child2.is_donor = True elif self.is_triple() and self.secular_code.parameters.ignore_tertiary is True: # for disrupted binary if self.triple.child1.is_star: - bin = self.triple.child2 + binary = self.triple.child2 else: - bin = self.triple.child1 + binary = self.triple.child1 - Rl1 = interactions.roche_radius(bin, bin.child1, self) - Rl2 = interactions.roche_radius(bin, bin.child2, self) + Rl1 = interactions.roche_radius(binary, binary.child1, self) + Rl2 = interactions.roche_radius(binary, binary.child2, self) if options.REPORT_TRIPLE_EVOLUTION: print("Roche lobe radii:", Rl1, Rl2) - print("Stellar radii:", bin.child1.radius, bin.child2.radius) + print("Stellar radii:", binary.child1.radius, binary.child2.radius) - bin.child1.is_donor = False - bin.child2.is_donor = False + binary.child1.is_donor = False + binary.child2.is_donor = False - if bin.child1.radius >= Rl1 - (1.0 * options.small_numerical_error | units.RSun): - bin.child1.is_donor = True - if bin.child2.radius >= Rl2 - (1.0 * options.small_numerical_error | units.RSun): - bin.child2.is_donor = True + if binary.child1.radius >= Rl1 - ( + 1.0 * interactions.small_numerical_error | units.RSun + ): + binary.child1.is_donor = True + if binary.child2.radius >= Rl2 - ( + 1.0 * interactions.small_numerical_error | units.RSun + ): + binary.child2.is_donor = True elif self.is_triple(): if self.triple.child1.is_star: star = self.triple.child1 - bin = self.triple.child2 + binary = self.triple.child2 else: star = self.triple.child2 - bin = self.triple.child1 + binary = self.triple.child1 # assuming secular code always returns inner binary first Rl1, Rl2, Rl3 = self.secular_code.give_roche_radii(self.triple) @@ -1031,46 +1041,55 @@ def check_RLOF(self): if options.REPORT_TRIPLE_EVOLUTION: print("Roche lobe radii:", Rl1, Rl2, Rl3) print( - "Stellar radii:", bin.child1.radius, bin.child2.radius, star.radius + "Stellar radii:", + binary.child1.radius, + binary.child2.radius, + star.radius, ) print( "binary Roche lobe radii:", - interactions.roche_radius(bin, bin.child1, self), - interactions.roche_radius(bin, bin.child2, self), + interactions.roche_radius(binary, binary.child1, self), + interactions.roche_radius(binary, binary.child2, self), interactions.roche_radius(self.triple, star, self), ) print( "eccentric binary Roche lobe radii:", - interactions.roche_radius(bin, bin.child1, self) * (1 - bin.eccentricity), - interactions.roche_radius(bin, bin.child2, self) * (1 - bin.eccentricity), + interactions.roche_radius(binary, binary.child1, self) + * (1 - binary.eccentricity), + interactions.roche_radius(binary, binary.child2, self) + * (1 - binary.eccentricity), interactions.roche_radius(self.triple, star, self) * (1 - self.triple.eccentricity), ) - print("Masses:", bin.child1.mass, bin.child2.mass, star.mass) - print("Semi:", bin.semimajor_axis, self.triple.semimajor_axis) - print("Ecc:", bin.eccentricity, self.triple.eccentricity) + print("Masses:", binary.child1.mass, binary.child2.mass, star.mass) + print("Semi:", binary.semimajor_axis, self.triple.semimajor_axis) + print("Ecc:", binary.eccentricity, self.triple.eccentricity) print( "Stellar type:", - bin.child1.stellar_type, - bin.child2.stellar_type, + binary.child1.stellar_type, + binary.child2.stellar_type, star.stellar_type, ) print( "Spin:", - bin.child1.spin_angular_frequency, - bin.child2.spin_angular_frequency, + binary.child1.spin_angular_frequency, + binary.child2.spin_angular_frequency, star.spin_angular_frequency, ) - bin.child1.is_donor = False - bin.child2.is_donor = False + binary.child1.is_donor = False + binary.child2.is_donor = False star.is_donor = False - if bin.child1.radius >= Rl1 - (1.0 * options.small_numerical_error | units.RSun): - bin.child1.is_donor = True - if bin.child2.radius >= Rl2 - (1.0 * options.small_numerical_error | units.RSun): - bin.child2.is_donor = True - if star.radius >= Rl3 - (1.0 * options.small_numerical_error | units.RSun): + if binary.child1.radius >= Rl1 - ( + 1.0 * interactions.small_numerical_error | units.RSun + ): + binary.child1.is_donor = True + if binary.child2.radius >= Rl2 - ( + 1.0 * interactions.small_numerical_error | units.RSun + ): + binary.child2.is_donor = True + if star.radius >= Rl3 - (1.0 * interactions.small_numerical_error | units.RSun): star.is_donor = True else: @@ -1094,11 +1113,11 @@ def check_OLOF(self): self.triple.child2.is_OLOF_donor = False if self.triple.child1.radius >= Rl2_1 - ( - 1.0 * options.small_numerical_error | units.RSun + 1.0 * interactions.small_numerical_error | units.RSun ): self.triple.child1.is_OLOF_donor = True if self.triple.child2.radius >= Rl2_2 - ( - 1.0 * options.small_numerical_error | units.RSun + 1.0 * interactions.small_numerical_error | units.RSun ): self.triple.child2.is_OLOF_donor = True @@ -1106,38 +1125,42 @@ def check_OLOF(self): # for disrupted binary if self.triple.child1.is_star: star = self.triple.child1 - bin = self.triple.child2 + binary = self.triple.child2 else: star = self.triple.child2 - bin = self.triple.child1 + binary = self.triple.child1 - Rl2_1 = interactions.L2_radius(bin, bin.child1, self) - Rl2_2 = interactions.L2_radius(bin, bin.child2, self) + Rl2_1 = interactions.L2_radius(binary, binary.child1, self) + Rl2_2 = interactions.L2_radius(binary, binary.child2, self) - bin.child1.is_OLOF_donor = False - bin.child2.is_OLOF_donor = False + binary.child1.is_OLOF_donor = False + binary.child2.is_OLOF_donor = False - if bin.child1.radius >= Rl2_1 - (1.0 * options.small_numerical_error | units.RSun): - bin.child1.is_OLOF_donor = True - if bin.child2.radius >= Rl2_2 - (1.0 * options.small_numerical_error | units.RSun): - bin.child2.is_OLOF_donor = True + if binary.child1.radius >= Rl2_1 - ( + 1.0 * options.small_numerical_error | units.RSun + ): + binary.child1.is_OLOF_donor = True + if binary.child2.radius >= Rl2_2 - ( + 1.0 * options.small_numerical_error | units.RSun + ): + binary.child2.is_OLOF_donor = True if options.REPORT_TRIPLE_EVOLUTION: print("L2 lobe radii:", Rl2_1, Rl2_2) - print("Stellar radii:", bin.child1.radius, bin.child2.radius) - print("Masses:", bin.child1.mass, bin.child2.mass, star.mass) - print("Semi:", bin.semimajor_axis, self.triple.semimajor_axis) - print("Ecc:", bin.eccentricity, self.triple.eccentricity) + print("Stellar radii:", binary.child1.radius, binary.child2.radius) + print("Masses:", binary.child1.mass, binary.child2.mass, star.mass) + print("Semi:", binary.semimajor_axis, self.triple.semimajor_axis) + print("Ecc:", binary.eccentricity, self.triple.eccentricity) print( "Stellar type:", - bin.child1.stellar_type, - bin.child2.stellar_type, + binary.child1.stellar_type, + binary.child2.stellar_type, star.stellar_type, ) print( "Spin:", - bin.child1.spin_angular_frequency, - bin.child2.spin_angular_frequency, + binary.child1.spin_angular_frequency, + binary.child2.spin_angular_frequency, star.spin_angular_frequency, ) @@ -1145,8 +1168,10 @@ def check_OLOF(self): print("check_OLOF: structure stellar system unknown") sys.exit("check_OLOF: structure stellar system unknown") - def check_CHE(self): # future option: potentially use: che_flag in SeBa - # returns true when one or both of the inner binary components are chemically homogeneously evolving + def check_CHE(self): + # future option: potentially use: che_flag in SeBa + # returns true when one or both of the inner binary components are + # chemically homogeneously evolving # if !include_CHE, then return False # problematic for quadruples - what if one binary is CHE, and other is not @@ -1154,17 +1179,21 @@ def check_CHE(self): # future option: potentially use: che_flag in SeBa if self.triple.is_star: return False elif self.is_binary(): - bin = self.triple + binary = self.triple if self.include_CHE and ( ( - bin.child1.spin_angular_frequency - >= interactions.criticial_angular_frequency_CHE(bin.child1.mass, metallicity) - and bin.child1.stellar_type <= 1 | units.stellar_type + binary.child1.spin_angular_frequency + >= interactions.criticial_angular_frequency_CHE( + binary.child1.mass, metallicity + ) + and binary.child1.stellar_type <= 1 | units.stellar_type ) or ( - bin.child2.spin_angular_frequency - >= interactions.criticial_angular_frequency_CHE(bin.child2.mass, metallicity) - and bin.child2.stellar_type <= 1 | units.stellar_type + binary.child2.spin_angular_frequency + >= interactions.criticial_angular_frequency_CHE( + binary.child2.mass, metallicity + ) + and binary.child2.stellar_type <= 1 | units.stellar_type ) ): return True @@ -1173,20 +1202,24 @@ def check_CHE(self): # future option: potentially use: che_flag in SeBa elif self.is_triple(): if self.triple.child1.is_star: - bin = self.triple.child2 + binary = self.triple.child2 else: - bin = self.triple.child1 + binary = self.triple.child1 if self.include_CHE and ( ( - bin.child1.spin_angular_frequency - >= interactions.criticial_angular_frequency_CHE(bin.child1.mass, metallicity) - and bin.child1.stellar_type <= 1 | units.stellar_type + binary.child1.spin_angular_frequency + >= interactions.criticial_angular_frequency_CHE( + binary.child1.mass, metallicity + ) + and binary.child1.stellar_type <= 1 | units.stellar_type ) or ( - bin.child2.spin_angular_frequency - >= interactions.criticial_angular_frequency_CHE(bin.child2.mass, metallicity) - and bin.child2.stellar_type <= 1 | units.stellar_type + binary.child2.spin_angular_frequency + >= interactions.criticial_angular_frequency_CHE( + binary.child2.mass, metallicity + ) + and binary.child2.stellar_type <= 1 | units.stellar_type ) ): return True @@ -1609,11 +1642,11 @@ def determine_time_step_tides(self, stellar_system=None): if self.triple.is_star: return False, 0 elif self.is_binary(): - Rl1 = roche_radius(self, self.child1) - Rl2 = roche_radius(self, self.child2) + Rl1 = interactions.roche_radius(self, self.child1) + Rl2 = interactions.roche_radius(self, self.child2) if self.triple.child1.radius >= Rl1 or self.triple.child2.radius >= Rl2: return abs( - time_step_factor_stable_mt + options.time_step_factor_stable_mt * min(self.triple.child1.mass, self.triple.child2.mass) / self.triple.mass_transfer_rate ) @@ -1635,7 +1668,7 @@ def determine_time_step_tides(self, stellar_system=None): ) ) return ( - time_step_factor_ecc + options.time_step_factor_ecc * self.triple.eccentricity / max(de_dt_child1, de_dt_child2) ) @@ -1643,49 +1676,49 @@ def determine_time_step_tides(self, stellar_system=None): if self.triple.child1.is_star: star = self.triple.child1 - bin = self.triple.child2 + binary = self.triple.child2 else: star = self.triple.child2 - bin = self.triple.child1 + binary = self.triple.child1 Rl1, Rl2, Rl3 = self.secular_code.give_roche_radii(self.triple) if star.radius >= Rl3: sys.exit("R>Rl3") - elif bin.child1.radius >= Rl1 or bin.child2.radius >= Rl2: + elif binary.child1.radius >= Rl1 or binary.child2.radius >= Rl2: return abs( - time_step_factor_stable_mt - * min(bin.child1.mass, bin.child2.mass) + options.time_step_factor_stable_mt + * min(binary.child1.mass, binary.child2.mass) / self.triple.mass_transfer_rate ) else: de_dt_star = abs( self.e_dot_tides( star, - self.get_mass(bin), + self.get_mass(binary), self.triple.semimajor_axis, self.triple.eccentricity, ) ) de_dt_bin_child1 = abs( self.e_dot_tides( - bin.child1, - bin.child2.mass, - bin.semimajor_axis, - bin.eccentricity, + binary.child1, + binary.child2.mass, + binary.semimajor_axis, + binary.eccentricity, ) ) de_dt_bin_child2 = abs( self.e_dot_tides( - bin.child2, - bin.child1.mass, - bin.semimajor_axis, - bin.eccentricity, + binary.child2, + binary.child1.mass, + binary.semimajor_axis, + binary.eccentricity, ) ) - dt_star = time_step_factor_ecc * self.triple.eccentricity / de_dt_star + dt_star = options.time_step_factor_ecc * self.triple.eccentricity / de_dt_star dt_bin = ( - time_step_factor_ecc - * bin.eccentricity + options.time_step_factor_ecc + * binary.eccentricity / max(de_dt_bin_child1, de_dt_bin_child2) ) return min(dt_star, dt_bin) @@ -1759,7 +1792,7 @@ def determine_time_step_tides(self, stellar_system=None): # exit(2) def determine_time_step(self): - if REPORT_DT: + if options.REPORT_DT: print( "Dt = ", self.stellar_code.particles.time_step, @@ -1780,7 +1813,7 @@ def determine_time_step(self): # small time_step after type change # done automatically by SeBa when due to wind mass losses, but not during RLOF if self.has_stellar_type_changed(): - time_step_stellar_code.append(minimum_time_step) + time_step_stellar_code.append(options.minimum_time_step) # small time_step during heavy wind mass losses time_step_wind = self.determine_time_step_wind() @@ -2116,40 +2149,40 @@ def adjust_system_after_supernova_kick(self): # SN in triple if self.triple.child1.is_star: star = self.triple.child1 - bin = self.triple.child2 + binary = self.triple.child2 else: star = self.triple.child2 - bin = self.triple.child1 + binary = self.triple.child1 # needs BH mass - vel_kick1 = self.get_SN_kick(bin.child1) - vel_kick2 = self.get_SN_kick(bin.child2) + vel_kick1 = self.get_SN_kick(binary.child1) + vel_kick2 = self.get_SN_kick(binary.child2) vel_kick3 = self.get_SN_kick(star) # convention in secular code: dm > 0 - dm1 = bin.child1.previous_mass - bin.child1.mass - dm2 = bin.child2.previous_mass - bin.child2.mass + dm1 = binary.child1.previous_mass - binary.child1.mass + dm2 = binary.child2.previous_mass - binary.child2.mass dm3 = star.previous_mass - star.mass # secular code requires the mass of the stars to be the mass prior to the SN - bin.child1.mass = bin.child1.previous_mass - bin.child2.mass = bin.child2.previous_mass + binary.child1.mass = binary.child1.previous_mass + binary.child2.mass = binary.child2.previous_mass star.mass = star.previous_mass # reset parameters to before SN # to get correct values for the snapshot - bin_child1_proper_stellar_type = bin.child1.stellar_type - bin_child2_proper_stellar_type = bin.child2.stellar_type + bin_child1_proper_stellar_type = binary.child1.stellar_type + bin_child2_proper_stellar_type = binary.child2.stellar_type star_proper_stellar_type = star.stellar_type - bin.child1.stellar_type = bin.child1.previous_stellar_type - bin.child2.stellar_type = bin.child2.previous_stellar_type + binary.child1.stellar_type = binary.child1.previous_stellar_type + binary.child2.stellar_type = binary.child2.previous_stellar_type star.stellar_type = star.previous_stellar_type - bin_child1_proper_radius = bin.child1.radius - bin_child2_proper_radius = bin.child2.radius + bin_child1_proper_radius = binary.child1.radius + bin_child2_proper_radius = binary.child2.radius star_proper_radius = star.radius - bin.child1.radius = bin.child1.previous_radius - bin.child2.radius = bin.child2.previous_radius + binary.child1.radius = binary.child1.previous_radius + binary.child2.radius = binary.child2.previous_radius star.radius = star.previous_radius self.save_snapshot() @@ -2160,7 +2193,7 @@ def adjust_system_after_supernova_kick(self): # determine stellar anomaly # mean anomaly increases uniformly from 0 to 2\pi radians during each orbit - inner_ecc = bin.eccentricity + inner_ecc = binary.eccentricity inner_mean_anomaly = np.random.uniform(0.0, 2.0 * np.pi) inner_eccentric_anomaly = optimize.brentq( @@ -2188,7 +2221,7 @@ def adjust_system_after_supernova_kick(self): np.sqrt(1 + outer_ecc) * np.sin(outer_eccentric_anomaly / 2.0), ) - if REPORT_SN_EVOLUTION: + if options.REPORT_SN_EVOLUTION: print("before SN:", self.triple.number) print( "\n\ntime:", @@ -2197,7 +2230,7 @@ def adjust_system_after_supernova_kick(self): self.triple.time - self.previous_time, ) print("eccentricity:", inner_ecc, outer_ecc) - print("semi-major axis:", bin.semimajor_axis, self.triple.semimajor_axis) + print("semi-major axis:", binary.semimajor_axis, self.triple.semimajor_axis) print( "inner anomaly:", inner_mean_anomaly, @@ -2228,37 +2261,37 @@ def adjust_system_after_supernova_kick(self): # as secular code required the mass of the stars to be the mass prior to the SN # reset mass to after SN - bin.child1.mass = bin.child1.previous_mass - dm1 - bin.child2.mass = bin.child2.previous_mass - dm2 + binary.child1.mass = binary.child1.previous_mass - dm1 + binary.child2.mass = binary.child2.previous_mass - dm2 star.mass = star.previous_mass - dm3 # reset the stellar types to after SN - bin.child1.stellar_type = bin_child1_proper_stellar_type - bin.child2.stellar_type = bin_child2_proper_stellar_type + binary.child1.stellar_type = bin_child1_proper_stellar_type + binary.child2.stellar_type = bin_child2_proper_stellar_type star.stellar_type = star_proper_stellar_type - bin.child1.radius = bin_child1_proper_radius - bin.child2.radius = bin_child2_proper_radius + binary.child1.radius = bin_child1_proper_radius + binary.child2.radius = bin_child2_proper_radius star.radius = star_proper_radius if self.secular_code.parameters.ignore_tertiary: self.triple.semimajor_axis = a_out_init self.triple.eccentricity = e_out_init - if REPORT_SN_EVOLUTION: + if options.REPORT_SN_EVOLUTION: print("after SN") - print("eccentricity:", bin.eccentricity, self.triple.eccentricity) - print("semi-major axis:", bin.semimajor_axis, self.triple.semimajor_axis) + print("eccentricity:", binary.eccentricity, self.triple.eccentricity) + print("semi-major axis:", binary.semimajor_axis, self.triple.semimajor_axis) if ( - bin.eccentricity >= 1.0 - or bin.eccentricity < 0.0 - or bin.semimajor_axis <= 0.0 | units.RSun - or np.isnan(bin.semimajor_axis.value_in(units.RSun)) + binary.eccentricity >= 1.0 + or binary.eccentricity < 0.0 + or binary.semimajor_axis <= 0.0 | units.RSun + or np.isnan(binary.semimajor_axis.value_in(units.RSun)) ): - if REPORT_SN_EVOLUTION: + if options.REPORT_SN_EVOLUTION: print("Inner orbit dissociated by SN at time = ", self.triple.time) - bin.bin_type = bin_type["disintegrated"] + binary.bin_type = bin_type["disintegrated"] return False elif ( self.triple.eccentricity >= 1.0 @@ -2266,7 +2299,7 @@ def adjust_system_after_supernova_kick(self): or self.triple.semimajor_axis <= 0.0 | units.RSun or np.isnan(self.triple.semimajor_axis.value_in(units.RSun)) ): - if REPORT_SN_EVOLUTION: + if options.REPORT_SN_EVOLUTION: print("Outer orbit dissociated by SN at time = ", self.triple.time) self.triple.bin_type = bin_type["disintegrated"] @@ -2287,19 +2320,19 @@ def adjust_system_after_supernova_kick(self): self.adjust_spin_after_supernova() # bh spin frequency has no meaning. make sure it doesn't affect the evolution - bin.child1.previous_moment_of_inertia_of_star = ( - bin.child1.moment_of_inertia_of_star + binary.child1.previous_moment_of_inertia_of_star = ( + binary.child1.moment_of_inertia_of_star ) - bin.child2.previous_moment_of_inertia_of_star = ( - bin.child2.moment_of_inertia_of_star + binary.child2.previous_moment_of_inertia_of_star = ( + binary.child2.moment_of_inertia_of_star ) star.previous_moment_of_inertia_of_star = star.moment_of_inertia_of_star - if bin.child1.stellar_type in stellar_types_SN_remnants: + if binary.child1.stellar_type in stellar_types_SN_remnants: self.secular_code.parameters.include_spin_radius_mass_coupling_terms_star1 = ( False ) - if bin.child2.stellar_type in stellar_types_SN_remnants: + if binary.child2.stellar_type in stellar_types_SN_remnants: self.secular_code.parameters.include_spin_radius_mass_coupling_terms_star2 = ( False ) @@ -2309,7 +2342,7 @@ def adjust_system_after_supernova_kick(self): ) if self.stop_at_SN: - if REPORT_SN_EVOLUTION: + if options.REPORT_SN_EVOLUTION: print("Supernova at time = ", self.triple.time) print( self.triple.child2.child1.mass, @@ -2421,18 +2454,18 @@ def resolve_stellar_interaction(self, stellar_system=None): stellar_system = self.triple if stellar_system.is_star: - if REPORT_TRIPLE_EVOLUTION: + if options.REPORT_TRIPLE_EVOLUTION: print("single stellar evolution") sys.exit("for now no single stellar evolution - exiting program") return elif self.is_binary(stellar_system): - if REPORT_TRIPLE_EVOLUTION: + if options.REPORT_TRIPLE_EVOLUTION: print("\n perform stellar interaction: binary") # stellar_system = perform_stellar_interaction(stellar_system, self) stopping_condition = perform_stellar_interaction(stellar_system, self) return stopping_condition # stellar interaction else: - if REPORT_TRIPLE_EVOLUTION: + if options.REPORT_TRIPLE_EVOLUTION: print("\n perform stellar interaction") stopping_condition = perform_stellar_interaction(stellar_system, self) @@ -2466,23 +2499,23 @@ def determine_mass_transfer_timescale(self, stellar_system=None): stellar_system = self.triple if stellar_system.is_star: - if REPORT_TRIPLE_EVOLUTION: + if options.REPORT_TRIPLE_EVOLUTION: print("single stellar evolution") return elif self.is_binary(stellar_system): - if REPORT_TRIPLE_EVOLUTION: + if options.REPORT_TRIPLE_EVOLUTION: print("\n determine_mass_transfer_timescale: binary - double star") mass_transfer_stability(stellar_system, self) - if REPORT_TRIPLE_EVOLUTION: + if options.REPORT_TRIPLE_EVOLUTION: print("mt rate double star:", stellar_system.mass_transfer_rate) else: self.determine_mass_transfer_timescale(stellar_system.child1) self.determine_mass_transfer_timescale(stellar_system.child2) - if REPORT_TRIPLE_EVOLUTION: + if options.REPORT_TRIPLE_EVOLUTION: print("\n determine_mass_transfer_timescale: binary") mass_transfer_stability(stellar_system, self) - if REPORT_TRIPLE_EVOLUTION: + if options.REPORT_TRIPLE_EVOLUTION: print("mt rate binary:", stellar_system.mass_transfer_rate) def solve_for_partial_time_step_stable_mass_transfer(self): @@ -2583,14 +2616,14 @@ def safety_check_time_step(self, stellar_system=None): return True, 0, 0 def recall_memory_one_step_stellar(self, nr_unsuccessfull, star_unsuccessfull): - if REPORT_DEBUG: + if options.REPORT_DEBUG: print("recall_memory_one_step_stellar") self.update_time_derivative_of_radius() dt = self.triple.time - self.previous_time # crashes for M=1.4Msun: MS hook at stellar type change # dt_new = max(minimum_time_step, min(self.determine_time_step(), 0.9*dt)) - dt_new = max(minimum_time_step, 0.5 * dt) + dt_new = max(options.minimum_time_step, 0.5 * dt) self.stellar_code.particles.recall_memory_one_step() self.triple.time += dt_new - dt @@ -2602,7 +2635,7 @@ def recall_memory_one_step_stellar(self, nr_unsuccessfull, star_unsuccessfull): if nr_unsuccessfull > 1: for i_rec in range(nr_unsuccessfull): triple_number = self.triple.number - if dt_new <= minimum_time_step: + if dt_new <= options.minimum_time_step: triple_number += 0.5 dr = ( star_unsuccessfull[i_rec].radius @@ -2613,27 +2646,27 @@ def recall_memory_one_step_stellar(self, nr_unsuccessfull, star_unsuccessfull): star_unsuccessfull.radius - star_unsuccessfull.previous_radius ) / star_unsuccessfull.radius triple_number = self.triple.number - if dt_new <= minimum_time_step: + if dt_new <= options.minimum_time_step: triple_number += 0.5 - if dt_new <= minimum_time_step: + if dt_new <= options.minimum_time_step: return True, 0, 0 return self.safety_check_time_step() # when the stellar code finds RLOF def rewind_to_begin_of_rlof_stellar(self, dt): - if REPORT_DEBUG: + if options.REPORT_DEBUG: print("rewind to begin of rlof stellar") dt_new = dt - dt_min = max(minimum_time_step, self.determine_time_step_stable_mt()) + dt_min = max(options.minimum_time_step, self.determine_time_step_stable_mt()) while self.has_donor() is True and dt_new > dt_min: dt_old = self.triple.time - self.previous_time - dt_new = max(minimum_time_step, 0.5 * dt_old) + dt_new = max(options.minimum_time_step, 0.5 * dt_old) self.stellar_code.particles.recall_memory_one_step() self.triple.time += dt_new - dt_old - if REPORT_TRIPLE_EVOLUTION or REPORT_DEBUG: + if options.REPORT_TRIPLE_EVOLUTION or options.REPORT_DEBUG: print("\n\ntime:", self.triple.time, self.has_donor()) self.stellar_code.evolve_model(self.triple.time) self.copy_from_stellar() @@ -2642,7 +2675,7 @@ def rewind_to_begin_of_rlof_stellar(self, dt): # when the secular code finds RLOF def rewind_to_begin_of_rlof_secular(self): - if REPORT_DEBUG: + if options.REPORT_DEBUG: print("rewind to begin of rlof secular") # find beginning of RLOF @@ -2660,11 +2693,11 @@ def rewind_to_begin_of_rlof_secular(self): def check_stopping_conditions_stellar_interaction(self): if self.stop_at_merger and self.has_merger(): - if REPORT_TRIPLE_EVOLUTION: + if options.REPORT_TRIPLE_EVOLUTION: print("Merger at time = ", self.triple.time) return False if self.stop_at_disintegrated and self.has_disintegrated(): - if REPORT_TRIPLE_EVOLUTION: + if options.REPORT_TRIPLE_EVOLUTION: print("Disintegration of system at time = ", self.triple.time) return False return True @@ -2712,16 +2745,18 @@ def check_stopping_conditions_stellar(self, stellar_system=None): if self.secular_code.model_time < self.triple.time: self.triple.time = self.secular_code.model_time - if REPORT_TRIPLE_EVOLUTION: + if options.REPORT_TRIPLE_EVOLUTION: print( "Mass transfer in outer binary of triple at time = ", self.triple.time, ) if stellar_system.is_mt_stable: - stellar_system.bin_type = bin_type["stable_mass_transfer"] + stellar_system.bin_type = interactions.bin_type[ + "stable_mass_transfer" + ] else: - stellar_system.bin_type = bin_type["common_envelope"] + stellar_system.bin_type = interactions.bin_type["common_envelope"] return False else: @@ -2745,16 +2780,18 @@ def check_stopping_conditions_stellar(self, stellar_system=None): or ( self.stop_at_eccentric_stable_mass_transfer and stellar_system.is_mt_stable - and stellar_system.eccentricity > minimum_eccentricity * 5.0 + and stellar_system.eccentricity + > interactions.minimum_eccentricity * 5.0 ) or ( self.stop_at_eccentric_unstable_mass_transfer and not stellar_system.is_mt_stable - and stellar_system.eccentricity > minimum_eccentricity * 5.0 + and stellar_system.eccentricity + > interactions.minimum_eccentricity * 5.0 ) ): - if REPORT_TRIPLE_EVOLUTION: + if options.REPORT_TRIPLE_EVOLUTION: print("Mass transfer in inner binary at time = ", self.triple.time) print( self.stop_at_mass_transfer, @@ -2766,9 +2803,11 @@ def check_stopping_conditions_stellar(self, stellar_system=None): ) if stellar_system.is_mt_stable: - stellar_system.bin_type = bin_type["stable_mass_transfer"] + stellar_system.bin_type = interactions.bin_type[ + "stable_mass_transfer" + ] else: - stellar_system.bin_type = bin_type["common_envelope"] + stellar_system.bin_type = interactions.bin_type["common_envelope"] return False else: @@ -2788,30 +2827,30 @@ def check_stopping_conditions(self): if self.secular_code.model_time < self.triple.time: self.triple.time = self.secular_code.model_time self.set_bintype_to_dynamical_instability() - if REPORT_TRIPLE_EVOLUTION: + if options.REPORT_TRIPLE_EVOLUTION: print("Dynamical instability at time = ", self.triple.time) return False if self.stop_at_inner_collision and self.triple.inner_collision is True: self.triple.time = min(self.secular_code.model_time, self.triple.time) - self.triple.child2.bin_type = bin_type["collision"] - if REPORT_TRIPLE_EVOLUTION: + self.triple.child2.bin_type = interactions.bin_type["collision"] + if options.REPORT_TRIPLE_EVOLUTION: print("Inner collision at time = ", self.triple.time) return False if self.stop_at_outer_collision and self.triple.outer_collision is True: self.triple.time = min(self.secular_code.model_time, self.triple.time) - self.triple.bin_type = bin_type["collision"] - if REPORT_TRIPLE_EVOLUTION: + self.triple.bin_type = interactions.bin_type["collision"] + if options.REPORT_TRIPLE_EVOLUTION: print("Outer collision at time = ", self.triple.time) return False if self.stop_at_semisecular_regime and self.triple.semisecular_regime is True: self.triple.time = min(self.secular_code.model_time, self.triple.time) - self.triple.bin_type = bin_type["semisecular"] - if REPORT_TRIPLE_EVOLUTION: + self.triple.bin_type = interactions.bin_type["semisecular"] + if options.REPORT_TRIPLE_EVOLUTION: print("Semisecular regime at time = ", self.triple.time) return False if ( self.triple.time - self.secular_code.model_time - > numerical_error | units.Myr + > interactions.numerical_error | units.Myr ): print( "triple time > sec time: should not be possible", @@ -2833,7 +2872,7 @@ def check_spin_angular_frequency(self, stellar_system=None): if stellar_system.is_star: if stellar_system.spin_angular_frequency < 0.0 | 1.0 / units.Myr: - if REPORT_DEBUG: + if options.REPORT_DEBUG: print("Error in spin at time = ", self.triple.time) return False @@ -2848,7 +2887,7 @@ def check_spin_angular_frequency(self, stellar_system=None): def check_error_flag_secular(self): if self.triple.error_flag_secular < 0: - if REPORT_TRIPLE_EVOLUTION: + if options.REPORT_TRIPLE_EVOLUTION: print("Error in secular code at time = ", self.triple.time) print(self.triple.error_flag_secular) return False @@ -2864,7 +2903,7 @@ def evolve_model(self, tend): self.tend = tend CPU_start_time = time.time() - if REPORT_DEBUG or MAKE_PLOTS: + if options.REPORT_DEBUG or options.MAKE_PLOTS: # for plotting data times_array = quantities.AdaptingVectorQuantity() a_in_array = quantities.AdaptingVectorQuantity() @@ -2950,7 +2989,7 @@ def evolve_model(self, tend): self.secular_code.parameters.include_outer_RLOF_terms ) - if REPORT_TRIPLE_EVOLUTION or REPORT_DEBUG: + if options.REPORT_TRIPLE_EVOLUTION or options.REPORT_DEBUG: print( "kozai timescale:", self.kozai_timescale(), @@ -2961,7 +3000,7 @@ def evolve_model(self, tend): self.determine_mass_transfer_timescale() self.save_snapshot() while self.triple.time < self.tend: - if REPORT_TRIPLE_EVOLUTION or REPORT_DEBUG: + if options.REPORT_TRIPLE_EVOLUTION or options.REPORT_DEBUG: print( "\n\n kozai timescale:", self.kozai_timescale(), @@ -2993,12 +3032,12 @@ def evolve_model(self, tend): self.save_snapshot() dt = self.determine_time_step() - if not no_stellar_evolution: + if not options.no_stellar_evolution: self.update_previous_stellar_parameters() self.stellar_code.particles.refresh_memory() self.triple.time += dt self.previous_dt = dt - if REPORT_DEBUG or REPORT_DT: + if options.REPORT_DEBUG or options.REPORT_DT: print( "\t time:", self.triple.time, self.previous_time, self.previous_dt ) @@ -3007,8 +3046,8 @@ def evolve_model(self, tend): self.instantaneous_evolution = True # do stellar evolution - if not no_stellar_evolution: - if REPORT_DEBUG: + if not options.no_stellar_evolution: + if options.REPORT_DEBUG: print("Stellar evolution") if self.include_CHE: # only needed when including CHE @@ -3031,7 +3070,7 @@ def evolve_model(self, tend): # if SN has taken place if self.has_stellar_type_changed_into_SN_remnant(): - if REPORT_TRIPLE_EVOLUTION: + if options.REPORT_TRIPLE_EVOLUTION: print("Supernova at time = ", self.triple.time, dt) if self.adjust_system_after_supernova_kick() is False: break @@ -3044,10 +3083,10 @@ def evolve_model(self, tend): (self.has_donor() or self.has_OLOF_donor()) and self.triple.bin_type == "detached" and self.triple.child2.bin_type == "detached" - and dt > minimum_time_step + and dt > options.minimum_time_step ): - # self.rewind_to_begin_of_rlof_stellar(dt) - # print('RLOF:', self.triple.child2.child1.is_donor, self.triple.bin_type , self.triple.child2.bin_type ) + # self.rewind_to_begin_of_rlof_stellar(dt) + # print('RLOF:', self.triple.child2.child1.is_donor, self.triple.bin_type , self.triple.child2.bin_type ) self.stellar_code.particles.recall_memory_one_step() self.copy_from_stellar() @@ -3061,11 +3100,11 @@ def evolve_model(self, tend): # resetting is_donor in determine_time_step continue - # needed for nucleair timescale + # needed for nuclear timescale self.update_time_derivative_of_radius() # do stellar interaction - if REPORT_DEBUG: + if options.REPORT_DEBUG: print("Stellar interaction") self.determine_mass_transfer_timescale() @@ -3083,7 +3122,7 @@ def evolve_model(self, tend): # do secular evolution if self.instantaneous_evolution is False: - if REPORT_DEBUG: + if options.REPORT_DEBUG: print("Secular evolution") # needed for refreshing memory in case secular finds RLOF @@ -3111,7 +3150,7 @@ def evolve_model(self, tend): else: self.secular_code.evolve_model(self.triple.time) - if REPORT_DEBUG: + if options.REPORT_DEBUG: print("Secular evolution finished") # to differentiate between semi-detached and contact @@ -3120,7 +3159,7 @@ def evolve_model(self, tend): if ( self.triple.time - self.secular_code.model_time - < -1 * numerical_error | units.Myr + < -1 * interactions.numerical_error | units.Myr and self.secular_code.triples[0].error_flag_secular >= 0 ): print( @@ -3133,17 +3172,19 @@ def evolve_model(self, tend): self.secular_code.triples[0].error_flag_secular, ) break - elif ( + if ( (self.has_donor() or self.has_OLOF_donor()) and self.triple.bin_type == "detached" and self.triple.child2.bin_type == "detached" and self.secular_code.model_time < self.triple.time - max( - minimum_time_step, 0.01 * self.determine_time_step_stable_mt() + options.minimum_time_step, + 0.01 * self.determine_time_step_stable_mt(), ) ): - # factor 0.01 times time_step_stable_mt as used mass_transfer_timescale from previous timestep + # factor 0.01 times time_step_stable_mt as used + # mass_transfer_timescale from previous timestep self.determine_mass_transfer_timescale() if self.check_stopping_conditions_stellar() is False: @@ -3162,12 +3203,13 @@ def evolve_model(self, tend): self.triple.child2.child1.spin_angular_frequency = previous_spin1 self.triple.child2.child2.spin_angular_frequency = previous_spin2 continue - elif ( + if ( self.has_donor() and self.triple.bin_type == "detached" and self.triple.child2.bin_type == "detached" ): - # time difference secular code & tres small enough to continue mass transfer + # time difference secular code & tres small enough to + # continue mass transfer self.secular_code.model_time = self.triple.time self.channel_from_secular.copy() @@ -3184,17 +3226,17 @@ def evolve_model(self, tend): not self.stop_at_inner_collision and self.triple.inner_collision is True ): - perform_inner_collision(self) + interactions.perform_inner_collision(self) else: - if REPORT_DEBUG: + if options.REPORT_DEBUG: print("skip secular") self.secular_code.model_time = self.triple.time self.instantaneous_evolution = False self.calculate_maximum_change_eccentricity() - if REPORT_DEBUG or MAKE_PLOTS: + if options.REPORT_DEBUG or options.MAKE_PLOTS: # for plotting data times_array.append(self.triple.time) e_in_array.append(self.triple.child2.eccentricity) From 6f3798b19da517a587cbcbe3397977048f0a0c0c Mon Sep 17 00:00:00 2001 From: Steven Rieder Date: Mon, 11 Nov 2024 13:28:55 +0100 Subject: [PATCH 24/30] clearer worker name --- src/tres/seculartriple/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tres/seculartriple/Makefile b/src/tres/seculartriple/Makefile index acaff41..74ba038 100644 --- a/src/tres/seculartriple/Makefile +++ b/src/tres/seculartriple/Makefile @@ -14,7 +14,7 @@ LDFLAGS = -lm $(MUSE_LD_FLAGS) OBJS = src/main_code.o src/ODE_system.o src/helper_routines.o src/tidal_friction_parameters.o src/cvode/cvode.o src/cvode/cvode_dense.o src/cvode/cvode_direct.o src/cvode/cvode_io.o src/cvode/cvode_diag.o src/cvode/cvode_spils.o src/cvode/cvode_spgmr.o src/cvode/cvode_spbcgs.o src/cvode/cvode_sptfqmr.o src/cvode/nvector_serial.o src/cvode/sundials_dense.o src/cvode/sundials_direct.o src/cvode/sundials_math.o src/cvode/sundials_nvector.o src/cvode/sundials_spgmr.o src/cvode/sundials_iterative.o src/cvode/sundials_spbcgs.o src/cvode/sundials_sptfqmr.o -all: worker_code +all: seculartriple_worker cleanall: clean rm worker_code @@ -25,7 +25,7 @@ clean: worker_code.cc: interface.py $(CODE_GENERATOR) --type=c interface.py SecularTripleInterface -o $@ -worker_code: worker_code.cc $(OBJS) +seculartriple_worker: worker_code.cc $(OBJS) $(MPICXX) $(CXXFLAGS) $@.cc $(OBJS) -o $@ .cc.o: $< From e8ebf21b2d1fc8a00e45a2de7cb3210821e7456a Mon Sep 17 00:00:00 2001 From: Steven Rieder Date: Mon, 11 Nov 2024 13:29:45 +0100 Subject: [PATCH 25/30] fix imports --- src/tres/triple_class.py | 74 ++++++++++++++++++++-------------------- 1 file changed, 37 insertions(+), 37 deletions(-) diff --git a/src/tres/triple_class.py b/src/tres/triple_class.py index 3a2e673..3f0cbf9 100644 --- a/src/tres/triple_class.py +++ b/src/tres/triple_class.py @@ -496,7 +496,7 @@ def update_stellar_parameters(self, stellar_system=None): if not options.GET_GYRATION_RADIUS_FROM_STELLAR_CODE: stellar_system.gyration_radius = ( - tfc.tidal_friction_constant.set_gyration_radius( + tfc.set_gyration_radius( stellar_system.stellar_type, stellar_system.mass ) ) @@ -1137,11 +1137,11 @@ def check_OLOF(self): binary.child2.is_OLOF_donor = False if binary.child1.radius >= Rl2_1 - ( - 1.0 * options.small_numerical_error | units.RSun + 1.0 * interactions.small_numerical_error | units.RSun ): binary.child1.is_OLOF_donor = True if binary.child2.radius >= Rl2_2 - ( - 1.0 * options.small_numerical_error | units.RSun + 1.0 * interactions.small_numerical_error | units.RSun ): binary.child2.is_OLOF_donor = True @@ -1834,7 +1834,7 @@ def determine_time_step(self): # if self.secular_code.parameters.include_inner_tidal_terms or self.secular_code.parameters.include_outer_tidal_terms: # time_step_tides = self.determine_time_step_tides() - if REPORT_DT or REPORT_DEBUG: + if options.REPORT_DT or options.REPORT_DEBUG: print( "time:", self.triple.time, @@ -1846,7 +1846,7 @@ def determine_time_step(self): ) if not self.has_donor(): - if REPORT_DT: + if options.REPORT_DT: print("no RLOF") time_step = min( time_step_radius_change, @@ -1854,7 +1854,7 @@ def determine_time_step(self): ) if time_step_tides < time_step: Rl1, Rl2, Rl3 = self.secular_code.give_roche_radii(self.triple) - if REPORT_DT: + if options.REPORT_DT: print(time_step, time_step_tides) print(Rl1, Rl2, Rl3) print( @@ -1864,14 +1864,14 @@ def determine_time_step(self): ) time_step = time_step_tides - if REPORT_DT or REPORT_DEBUG: + if options.REPORT_DT or options.REPORT_DEBUG: print( "min increase", time_step, - maximum_time_step_factor * self.previous_dt, + options.maximum_time_step_factor * self.previous_dt, ) - time_step = min(time_step, maximum_time_step_factor * self.previous_dt) + time_step = min(time_step, options.maximum_time_step_factor * self.previous_dt) elif ( self.has_donor() @@ -1879,9 +1879,9 @@ def determine_time_step(self): and self.triple.child2.bin_type == "detached" ): # find beginning of RLOF carefully - time_step = time_step_factor_find_RLOF * self.previous_dt - if REPORT_DT: - print("find rlof", time_step_factor_find_RLOF, self.previous_dt) + time_step = options.time_step_factor_find_RLOF * self.previous_dt + if options.REPORT_DT: + print("find rlof", interactions.time_step_factor_find_RLOF, self.previous_dt) # resetting is_donor self.check_RLOF() @@ -1892,10 +1892,10 @@ def determine_time_step(self): time_step_wind, min(min(time_step_stellar_code), time_step_max) ) time_step = min(time_step, self.determine_time_step_stable_mt()) - if REPORT_DT or REPORT_DEBUG: + if options.REPORT_DT or options.REPORT_DEBUG: print("donor time:", self.determine_time_step_stable_mt()) - if REPORT_DT or REPORT_DEBUG: + if options.REPORT_DT or options.REPORT_DEBUG: print( "min increase", time_step, @@ -1919,7 +1919,7 @@ def determine_time_step(self): # print('prev timestep', time_step, previous_time_step) previous_time_step = self.triple.time - self.previous_time time_step = min( - time_step, maximum_time_step_factor_after_stable_mt * previous_time_step + time_step, options.maximum_time_step_factor_after_stable_mt * previous_time_step ) if self.triple.time == quantities.zero: @@ -1928,9 +1928,9 @@ def determine_time_step(self): # do not take 0.1*P_in -> resonance -> large error time_step = min(min(P_out, time_step), 1.0 | units.yr) - time_step = max(time_step, minimum_time_step) + time_step = max(time_step, options.minimum_time_step) if self.triple.time >= self.tinit: - time_step = min(time_step, maximum_time_step) + time_step = min(time_step, options.maximum_time_step) # else: # during run-up towards mass transfer @@ -1946,14 +1946,14 @@ def determine_time_step(self): # in case secular code finds RLOF if self.fixed_timestep > 0.0 | units.yr: - if REPORT_DT or REPORT_DEBUG: + if options.REPORT_DT or options.REPORT_DEBUG: print("time:", self.fixed_timestep) print("donor time:", self.determine_time_step_stable_mt()) t_donor = ( self.determine_time_step_stable_mt() * time_step_factor_stable_mt ) # extra small for safety - t_donor_lim = max(minimum_time_step, min(time_step, t_donor)) # + t_donor_lim = max(options.minimum_time_step, min(time_step, t_donor)) # # although fixed_timestep < time_step, fixed_timestep can be > time_step_stable_mt if t_donor == np.inf | units.Myr: @@ -2376,12 +2376,12 @@ def planetary_mass_evaporation(self, dt, stellar_system=None): return elif self.is_binary(stellar_system): if ( - stellar_system.child1.stellar_type in stellar_types_planetary_objects + stellar_system.child1.stellar_type in interactions.stellar_types_planetary_objects and stellar_system.child2.stellar_type - not in stellar_types_planetary_objects + not in interactions.stellar_types_planetary_objects ): donor = stellar_system.child1 - dm = mass_lost_due_to_evaporation_in_binary( + dm = interactions.mass_lost_due_to_evaporation_in_binary( stellar_system, dt, donor, stellar_system.child2, self ) donor.previous_mass = donor.mass @@ -2391,12 +2391,12 @@ def planetary_mass_evaporation(self, dt, stellar_system=None): donor_in_stellar_code.change_mass(-1 * dm, 0.0 | units.yr) print("mass lost child1:", dm) elif ( - stellar_system.child2.stellar_type in stellar_types_planetary_objects + stellar_system.child2.stellar_type in interactions.stellar_types_planetary_objects and stellar_system.child1.stellar_type - not in stellar_types_planetary_objects + not in interactions.stellar_types_planetary_objects ): donor = stellar_system.child2 - dm = mass_lost_due_to_evaporation_in_binary( + dm = interactions.mass_lost_due_to_evaporation_in_binary( stellar_system, dt, donor, stellar_system.child1, self ) donor.previous_mass = donor.mass @@ -2410,10 +2410,10 @@ def planetary_mass_evaporation(self, dt, stellar_system=None): # effect on tertiary if ( stellar_system.child1.stellar_type - in stellar_types_planetary_objects + in interactions.stellar_types_planetary_objects ): # evaporation if tertiary is a planet donor = stellar_system.child1 - dm = mass_lost_due_to_evaporation_tertiary( + dm = interactions.mass_lost_due_to_evaporation_tertiary( stellar_system, dt, donor, stellar_system.child2, self ) donor.previous_mass = donor.mass @@ -2427,10 +2427,10 @@ def planetary_mass_evaporation(self, dt, stellar_system=None): elif self.child2.is_star: # child2 is the tertiary # effect on tertiary if ( - self.child2.stellar_type in stellar_types_planetary_objects + self.child2.stellar_type in interactions.stellar_types_planetary_objects ): # evaporation if tertiary is a planet donor = stellar_system.child2 - dm = mass_lost_due_to_evaporation_tertiary( + dm = interactions.mass_lost_due_to_evaporation_tertiary( stellar_system, dt, donor, stellar_system.child1, self ) donor.previous_mass = donor.mass @@ -2462,13 +2462,13 @@ def resolve_stellar_interaction(self, stellar_system=None): if options.REPORT_TRIPLE_EVOLUTION: print("\n perform stellar interaction: binary") # stellar_system = perform_stellar_interaction(stellar_system, self) - stopping_condition = perform_stellar_interaction(stellar_system, self) + stopping_condition = interactions.perform_stellar_interaction(stellar_system, self) return stopping_condition # stellar interaction else: if options.REPORT_TRIPLE_EVOLUTION: print("\n perform stellar interaction") - stopping_condition = perform_stellar_interaction(stellar_system, self) + stopping_condition = interactions.perform_stellar_interaction(stellar_system, self) if not stopping_condition: # stellar interaction return False @@ -2505,7 +2505,7 @@ def determine_mass_transfer_timescale(self, stellar_system=None): elif self.is_binary(stellar_system): if options.REPORT_TRIPLE_EVOLUTION: print("\n determine_mass_transfer_timescale: binary - double star") - mass_transfer_stability(stellar_system, self) + interactions.mass_transfer_stability(stellar_system, self) if options.REPORT_TRIPLE_EVOLUTION: print("mt rate double star:", stellar_system.mass_transfer_rate) else: @@ -2514,7 +2514,7 @@ def determine_mass_transfer_timescale(self, stellar_system=None): if options.REPORT_TRIPLE_EVOLUTION: print("\n determine_mass_transfer_timescale: binary") - mass_transfer_stability(stellar_system, self) + interactions.mass_transfer_stability(stellar_system, self) if options.REPORT_TRIPLE_EVOLUTION: print("mt rate binary:", stellar_system.mass_transfer_rate) @@ -2555,11 +2555,11 @@ def safety_check_time_step(self, stellar_system=None): # print('relative wind mass losses:', dm) if ( - (abs(dm) > error_dm) + (abs(dm) > options.error_dm) and not ( stellar_system.stellar_type != stellar_system.previous_stellar_type ) - and not (stellar_system.stellar_type in stellar_types_SN_remnants) + and not (stellar_system.stellar_type in interactions.stellar_types_SN_remnants) ): successfull_dr = False print( @@ -2579,11 +2579,11 @@ def safety_check_time_step(self, stellar_system=None): # print('relative change in radius:', dr) if ( - (abs(dr) > error_dr) + (abs(dr) > options.error_dr) and not ( stellar_system.stellar_type != stellar_system.previous_stellar_type - and stellar_system.stellar_type in stellar_types_dr + and stellar_system.stellar_type in interactions.stellar_types_dr ) and not stellar_system.parent.bin_type == "stable_mass_transfer" ): From 442f09bf93e5270e895d1ae7e4d69d088e3afae3 Mon Sep 17 00:00:00 2001 From: Steven Rieder Date: Mon, 11 Nov 2024 13:30:09 +0100 Subject: [PATCH 26/30] refactoring --- src/tres/interactions.py | 31 ++++++++++++++++++------------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/src/tres/interactions.py b/src/tres/interactions.py index 1b3c004..3fbdc1f 100644 --- a/src/tres/interactions.py +++ b/src/tres/interactions.py @@ -11,6 +11,7 @@ REPORT_BINARY_EVOLUTION, REPORT_FUNCTION_NAMES, REPORT_MASS_TRANSFER_STABILITY, + minimum_time_step, ) # constants @@ -87,10 +88,10 @@ def roche_radius_dimensionless(M, m): return 0.49 * q23 / (0.6 * q23 + np.log(1 + q13)) -def roche_radius(bin, primary, self): - if not bin.is_star and primary.is_star: - return bin.semimajor_axis * roche_radius_dimensionless( - primary.mass, self.get_mass(bin) - primary.mass +def roche_radius(binary, primary, self): + if not binary.is_star and primary.is_star: + return binary.semimajor_axis * roche_radius_dimensionless( + primary.mass, self.get_mass(binary) - primary.mass ) sys.exit("error in roche radius: Roche radius can only be determined in a binary") @@ -105,14 +106,18 @@ def L2_radius_dimensionless(M, m): return rl2_div_rl1 * rl1 -def L2_radius(bin, primary, self): - # note: this prescription is based on the Eggleton approximation for how to adjust a circular RL to an eccentric one - # may not be consistent with Sepinsky's method for eccentric RL (L1) - if not bin.is_star and primary.is_star: +def L2_radius(binary, primary, self): + # note: this prescription is based on the Eggleton approximation for how to + # adjust a circular RL to an eccentric one may not be consistent with + # Sepinsky's method for eccentric RL (L1) + if not binary.is_star and primary.is_star: return ( - bin.semimajor_axis - * L2_radius_dimensionless(primary.mass, self.get_mass(bin) - primary.mass) - * (1 - bin.eccentricity) + binary.semimajor_axis + * L2_radius_dimensionless( + primary.mass, + self.get_mass(binary) - primary.mass + ) + * (1 - binary.eccentricity) ) sys.exit("Error: L2 radius can only be determined in a binary") @@ -153,7 +158,7 @@ def nuclear_evolution_timescale(star): <= (quantities.zero + numerical_error**2) | units.RSun / units.yr ): # when star is shrinking - # t_nuc = 0.1*main_sequence_time() # in SeBa + # t_nuc = 0.1 * main_sequence_time() # in SeBa t_nuc = 0.1 * star.age else: t_nuc = ( @@ -165,7 +170,7 @@ def nuclear_evolution_timescale(star): def kelvin_helmholds_timescale(star): if star.stellar_type in stellar_types_planetary_objects: - # print('thermal evolution timescale for planetary objects requested') + # print('thermal evolution timescale for planetary objects requested') return dynamic_timescale(star) if REPORT_FUNCTION_NAMES: From f550edc0a752217300b5fc53bfa067cb8048151e Mon Sep 17 00:00:00 2001 From: Steven Rieder Date: Mon, 11 Nov 2024 13:30:34 +0100 Subject: [PATCH 27/30] use units for angles too --- src/tres/tres.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/tres/tres.py b/src/tres/tres.py index 5cc229b..87fba59 100644 --- a/src/tres/tres.py +++ b/src/tres/tres.py @@ -40,7 +40,7 @@ def initialize_triple_class( correct_params, stellar_code, secular_code, - relative_inclination=80.0 * np.pi / 180.0, + relative_inclination=80.0 | units.deg, metallicity=0.02, tend=5.0 | units.Myr, tinit=0.0 | units.Myr, @@ -125,7 +125,7 @@ def tres_main( outer_semimajor_axis=100.0 | units.au, inner_eccentricity=0.1, outer_eccentricity=0.5, - relative_inclination=80.0 * np.pi / 180.0, + relative_inclination=80.0 | units.deg, inner_argument_of_pericenter=0.1, outer_argument_of_pericenter=0.5, inner_longitude_of_ascending_node=0.0, @@ -174,7 +174,7 @@ def tres_main( inner_eccentricity = float(inner_eccentricity) outer_eccentricity = float(outer_eccentricity) - relative_inclination = float(relative_inclination) + relative_inclination = relative_inclination inner_argument_of_pericenter = float(inner_argument_of_pericenter) outer_argument_of_pericenter = float(outer_argument_of_pericenter) inner_longitude_of_ascending_node = float(inner_longitude_of_ascending_node) @@ -302,7 +302,7 @@ def tres_main_developer( correct_params, stellar_code, secular_code, - relative_inclination=80.0 * np.pi / 180.0, + relative_inclination=80.0 | units.deg, metallicity=0.02, tend=5.0 | units.Myr, tinit=0.0 | units.Myr, @@ -350,7 +350,7 @@ def tres_main_developer( bins.argument_of_pericenter[1] = float(bins.argument_of_pericenter[1]) bins.longitude_of_ascending_node[0] = float(bins.longitude_of_ascending_node[0]) bins.longitude_of_ascending_node[1] = float(bins.longitude_of_ascending_node[1]) - relative_inclination = float(relative_inclination) + relative_inclination = relative_inclination triple_class_object = Triple( stars, @@ -505,7 +505,7 @@ def parse_arguments(): "-I", dest="relative_inclination", type=units.rad, - default=(80.0 * np.pi / 180.0) | units.rad, + default=80.0 | units.deg, help="relative inclination", ) parser.add_argument( From 0bc1f5f29bfbe7aca655c325b102396768896ba5 Mon Sep 17 00:00:00 2001 From: Steven Rieder Date: Mon, 11 Nov 2024 13:30:51 +0100 Subject: [PATCH 28/30] refactoring --- src/tres/tps.py | 700 ++++++++++++++++++++---------------------------- 1 file changed, 289 insertions(+), 411 deletions(-) diff --git a/src/tres/tps.py b/src/tres/tps.py index 19ab5f6..dc723c3 100644 --- a/src/tres/tps.py +++ b/src/tres/tps.py @@ -5,7 +5,6 @@ Options: --M_max upper limit for the inner primary mass [100 Msun] --M_min lower limit for the inner primary mass [0.1 Msun] --M_distr mass function option: -lib_inner_primary_mass_distr = { 0: "Kroupa", # default 1: "Scalo", 2: "Miller & Scalo", @@ -13,27 +12,21 @@ 4: "Logarithmically flat", 5: "Eggleton", 6: "Kroupa for massive stars M>0.5 powerlaw with exp=-2.3", -} -## --Q_max upper limit for the inner mass ratio [1.] -## --Q_min lower limit for the inner mass ratio [0.] -## --Q_distr inner mass ratio option: -lib_inner_mass_ratio_distr = { + --Q_max upper limit for the inner mass ratio [1.] + --Q_min lower limit for the inner mass ratio [0.] + --Q_distr inner mass ratio option: 0: "Uniform distribution", # default 1: "Kroupa IMF", # draws from mass distribution instead of mass ratio distribution 2: "Galicher et al. 2016 powerlaw (M^-1.31)", -} # draws from mass distribution instead of mass ratio distribution, appropriate for planets -## --q_max upper limit for the outer mass ratio [1.] -## --q_min lower limit for the mass of the outer star [0.] -## --q_distr outer mass ratio option: -lib_outer_mass_ratio_distr = { + --q_max upper limit for the outer mass ratio [1.] + --q_min lower limit for the mass of the outer star [0.] + --q_distr outer mass ratio option: 0: "Uniform distribution", # default 1: "Kroupa IMF", # draws from mass distribution instead of mass ratio distribution 2: "Galicher et al. 2016 powerlaw (M^-1.31)", -} # draws from mass distribution instead of mass ratio distribution, appropriate for planets -## --A_max upper limit for the inner semi-major axis [5e6 RSun] -## --A_min lower limit for the inner semi-major axis [5] -## --A_distr inner semi-major axcis option: -lib_inner_semi_distr = { + --A_max upper limit for the inner semi-major axis [5e6 RSun] + --A_min lower limit for the inner semi-major axis [5] + --A_distr inner semi-major axcis option: 0: "Log Uniform distribution", # default 1: "Constant semi-major axis", 2: "Tokovinin lognormal mu = 10^5d, sigma = 2.3", @@ -42,11 +35,9 @@ 5: "Sana et al. 2012", 6: "flat distribution", 7: "Galicher et al. 2016 powerlaw (a^-0.61)", -} # appropriate for planets -## --a_max upper limit for the outer semi-major axis [5e6 RSun] -## --a_min lower limit for the outer semi-major axis [5 RSun] -## --a_distr outer semi-major axis option: -lib_outer_semi_distr = { + --a_max upper limit for the outer semi-major axis [5e6 RSun] + --a_min lower limit for the outer semi-major axis [5 RSun] + --a_distr outer semi-major axis option: 0: "Log Uniform distribution", # default 1: "Constant semi-major axis", 2: "Tokovinin lognormal mu = 10^5d, sigma = 2.3", @@ -55,108 +46,87 @@ 5: "Sana et al. 2012", 6: "flat distribution", 7: "Galicher et al. 2016 powerlaw (a^-0.61)", -} # appropriate for planets -## --E_max upper limit for the inner eccentricity [0.9] -## --E_min lower limit for the inner eccentricity [0.] -## --E_distr inner eccentricity option: -lib_inner_ecc_distr = { + --E_max upper limit for the inner eccentricity [0.9] + --E_min lower limit for the inner eccentricity [0.] + --E_distr inner eccentricity option: 0: "Thermal", # default 1: "Constant eccentricity", 2: "Sana et al. 2012 e^-0.45", # -> close binaries 3: "Flat distribution", 4: "Powerlaw e^0.5", 5: "Bowler et al. 2020 Beta distribution", -} # appropriate for planets -## --e_max upper limit for the outer eccentricity [0.9] -## --e_min lower limit for the outer eccentricity [0.] -## --e_distr outer eccentricity option: -lib_outer_ecc_distr = { + --e_max upper limit for the outer eccentricity [0.9] + --e_min lower limit for the outer eccentricity [0.] + --e_distr outer eccentricity option: 0: "Thermal", # default 1: "Constant eccentricity", 2: "Sana et al. 2012 e^-0.45", # -> close binaries 3: "Flat distribution", 4: "Powerlaw e^0.5", 5: "Bowler et al. 2020 Beta distribution", -} # appropriate for planets -## --i_max upper limit for the relative inclination [pi] -## --i_min lower limit for the relative inclination [0] -## --i_distr relative inclination option: -lib_incl_distr = { + --i_max upper limit for the relative inclination [pi] + --i_min lower limit for the relative inclination [0] + --i_distr relative inclination option: 0: "Circular uniform distribution", # default 1: "Constant inclination", -} -## --G_max upper limit for the inner argument of pericenter [pi] -## --G_min lower limit for the inner argument of pericenter [-pi] -## --G_distr inner argument of pericenter option: r -lib_inner_aop_distr = { + --G_max upper limit for the inner argument of pericenter [pi] + --G_min lower limit for the inner argument of pericenter [-pi] + --G_distr inner argument of pericenter option: r 0: "Uniform distribution", # default 1: "Constant argument of pericenter", -} -## --g_max upper limit for the outer argument of pericenter [pi] -## --g_min lower limit for the outer argument of pericenter [-pi] -## --g_distr outer argument of pericenter option: -lib_outer_aop_distr = { + --g_max upper limit for the outer argument of pericenter [pi] + --g_min lower limit for the outer argument of pericenter [-pi] + --g_distr outer argument of pericenter option: 0: "Uniform distribution", # default 1: "Constant argument of pericenter", -} -## outer longitude of ascending nodes = inner - pi -## --O_max upper limit for the inner longitude of ascending node [pi] -## --O_min lower limit for the inner longitude of ascending node [-pi] -## --O_distr inner longitude of ascending node option: -lib_inner_loan_distr = { + outer longitude of ascending nodes = inner - pi + --O_max upper limit for the inner longitude of ascending node [pi] + --O_min lower limit for the inner longitude of ascending node [-pi] + --O_distr inner longitude of ascending node option: 0: "Circular niform distribution", 1: "Constant longitude of ascending nodes", -} # default -## -T or -t binary end time. [13500 Myr] -## -z metallicity of stars [0.02 Solar] -## -n total number of systems to be simulated. [1] -## -N number ID of first system. [0] -## --no_stop_at_mass_transfer stopping condition at mass transfer -## --no_stop_at_init_mass_transfer stopping condition at mass transfer at initialisation -## --no_stop_at_outer_mass_transfer stopping condition at mass transfer in outer binary -## --stop_at_stable_mass_transfer stopping condition at stable mass transfer -## --stop_at_eccentric_stable_mass_transfer stopping condition at eccentric stable mass transfer -## --stop_at_unstable_mass_transfer stopping condition at unstable mass transfer -## --stop_at_eccentric_unstable_mass_transfer stopping condition at eccentric unstable mass transfer -## --stop_at_no_CHE stopping condition if no chemically homogeneous evolution - -## --no_stop_at_merger stopping condition at merger -## --no_stop_at_disintegrated stopping condition at disintegration -## --no_stop_at_inner_collision stopping condition at collision in inner binary -## --no_stop_at_outer_collision stopping condition at collision involving tertiary star -## --no_stop_at_dynamical_instability stopping condition at dynamical instability -## --stop_at_semisecular_regime stopping condition at semisecular regime -## --stop_at_SN stopping condition at supernova -lib_SN_kick_distr = { + -T or -t binary end time. [13500 Myr] + -z metallicity of stars [0.02 Solar] + -n total number of systems to be simulated. [1] + -N number ID of first system. [0] + --no_stop_at_mass_transfer stopping condition at mass transfer + --no_stop_at_init_mass_transfer stopping condition at mass transfer at initialisation + --no_stop_at_outer_mass_transfer stopping condition at mass transfer in outer binary + --stop_at_stable_mass_transfer stopping condition at stable mass transfer + --stop_at_eccentric_stable_mass_transfer stopping condition at eccentric stable mass transfer + --stop_at_unstable_mass_transfer stopping condition at unstable mass transfer + --stop_at_eccentric_unstable_mass_transfer stopping condition at eccentric unstable mass transfer + --stop_at_no_CHE stopping condition if no chemically homogeneous evolution + + --no_stop_at_merger stopping condition at merger + --no_stop_at_disintegrated stopping condition at disintegration + --no_stop_at_inner_collision stopping condition at collision in inner binary + --no_stop_at_outer_collision stopping condition at collision involving tertiary star + --no_stop_at_dynamical_instability stopping condition at dynamical instability + --stop_at_semisecular_regime stopping condition at semisecular regime + --stop_at_SN stopping condition at supernova 0: "No kick", 1: "Hobbs", # Hobbs, Lorimer, Lyne & Kramer 2005, 360, 974 2: "Arzoumanian", # Arzoumanian ea 2002, 568, 289 3: "Hansen", # Hansen & Phinney 1997, 291, 569 4: "Paczynski", # Paczynski 1990, 348, 485 5: "Verbunt", # Verbunt, Igoshev & Cator, 2017, 608, 57 -} # default - -lib_CE = { - 0: "alpha-ce + alpha-dce", - 1: "gamma-ce + alpha-dce", - 2: "seba style; combination of gamma-ce, alpha-ce & alpha-dce", -} - - -# not implemented yet -## -s random seed +not implemented yet: + -s random seed """ import sys +import argparse + import numpy as np + from scipy.interpolate import interp1d from scipy.stats import beta as beta_distribution -from amuse.units.optparse import OptionParser from amuse.units import units, constants +from amuse.units.trigo import cos, arccos from amuse.support.console import set_printing_strategy - from amuse.ic.kroupa import new_kroupa_mass_distribution from amuse.ic.scalo import new_scalo_mass_distribution from amuse.ic.millerscalo import new_miller_scalo_mass_distribution @@ -165,7 +135,7 @@ from amuse.community.seba import Seba import tres -from tres.seculartriple_TPS.interface import SecularTriple +from tres.seculartriple import Seculartriple from tres.options import ( REPORT_TPS, @@ -176,98 +146,9 @@ absolute_min_mass, absolute_max_mass, ) +from tres import distributions as td -secular_code = SecularTriple() - -lib_inner_primary_mass_distr = { - 0: "Kroupa", # default - 1: "Scalo", - 2: "Miller & Scalo", - 3: "Salpeter", - 4: "Logarithmically flat", - 5: "Eggleton", - 6: "Kroupa for massive stars M>0.5 powerlaw with exp=-2.3", -} - -lib_inner_mass_ratio_distr = { - 0: "Uniform distribution", # default - 1: "Kroupa IMF", # draws from mass distribution instead of mass ratio distribution - 2: "Galicher et al. 2016 powerlaw (M^-1.31)", -} # draws from mass distribution instead of mass ratio distribution, appropriate for planets - -lib_outer_mass_ratio_distr = { - 0: "Uniform distribution", # default - 1: "Kroupa IMF", # draws from mass distribution instead of mass ratio distribution - 2: "Galicher et al. 2016 powerlaw (M^-1.31)", -} # draws from mass distribution instead of mass ratio distribution, appropriate for planets - -lib_inner_semi_distr = { - 0: "Log Uniform distribution", # default - 1: "Constant semi-major axis", - 2: "Tokovinin lognormal mu = 10^5d, sigma = 2.3", - 3: "Lognormal mu = 10^3.5d, sigma = 2.3", - 4: "Rizzuto Lognormal mu = 10^0.95 AU, sigma = 1.35", - 5: "Sana et al. 2012", - 6: "flat distribution", - 7: "Galicher et al. 2016 powerlaw (a^-0.61)", -} # appropriate for planets - -lib_outer_semi_distr = { - 0: "Log Uniform distribution", # default - 1: "Constant semi-major axis", - 2: "Tokovinin lognormal mu = 10^5d, sigma = 2.3", - 3: "Lognormal mu = 10^3.5d, sigma = 2.3", - 4: "Rizzuto Lognormal mu = 10^0.95 AU, sigma = 1.35", - 5: "Sana et al. 2012", - 6: "flat distribution", - 7: "Galicher et al. 2016 powerlaw (a^-0.61)", -} # appropriate for planets - -lib_inner_ecc_distr = { - 0: "Thermal", # default - 1: "Constant eccentricity", - 2: "Sana et al. 2012 e^-0.45", # -> close binaries - 3: "Flat distribution", - 4: "Powerlaw e^0.5", - 5: "Bowler et al. 2020 Beta distribution", -} # appropriate for planets - -lib_incl_distr = { - 0: "Circular uniform distribution", # default - 1: "Constant inclination", -} - -lib_inner_aop_distr = { - 0: "Uniform distribution", # default - 1: "Constant argument of pericenter", -} - -lib_outer_aop_distr = { - 0: "Uniform distribution", # default - 1: "Constant argument of pericenter", -} - -lib_inner_loan_distr = { - 0: "Circular niform distribution", - 1: "Constant longitude of ascending nodes", -} # default - -lib_SN_kick_distr = { - 0: "No kick", - 1: "Hobbs", # Hobbs, Lorimer, Lyne & Kramer 2005, 360, 974 - 2: "Arzoumanian", # Arzoumanian ea 2002, 568, 289 - 3: "Hansen", # Hansen & Phinney 1997, 291, 569 - 4: "Paczynski", # Paczynski 1990, 348, 485 - 5: "Verbunt", # Verbunt, Igoshev & Cator, 2017, 608, 57 -} # default - - -lib_CE = { - 0: "alpha-ce + alpha-dce", - 1: "gamma-ce + alpha-dce", - 2: "seba style; combination of gamma-ce, alpha-ce & alpha-dce", -} - +secular_code = Seculartriple() def flat_distr(lower, upper): return np.random.uniform(lower, upper) @@ -517,8 +398,8 @@ def generate_mass( mass_min=inner_secondary_mass_min, mass_max=inner_secondary_mass_max, )[0] - # self.inner_secondary_mass = new_kroupa_mass_distribution(1, mass_min=inner_secondary_mass_min, mass_max=inner_primary_mass_max)[0] - # self.inner_secondary_mass = new_kroupa_mass_distribution(1, mass_min=inner_secondary_mass_min, mass_max=inner_primary_mass)[0] + # self.inner_secondary_mass = new_kroupa_mass_distribution(1, mass_min=inner_secondary_mass_min, mass_max=inner_primary_mass_max)[0] + # self.inner_secondary_mass = new_kroupa_mass_distribution(1, mass_min=inner_secondary_mass_min, mass_max=inner_primary_mass)[0] elif inner_mass_ratio_distr == 2: # Galicher et al 2016 self.inner_secondary_mass = powerlaw_distr( m_min=inner_secondary_mass_min, @@ -611,10 +492,12 @@ def generate_semi_and_ecc( if inner_semi_distr == 1: # Constant if REPORT_USER_WARNINGS_TPS: print( - "TPS::generate_semi: unambiguous choice of constant semi-major axis" + "TPS::generate_semi: unambiguous choice of constant semi-major " + "axis" ) print( - "--A_min option to set the value of the semi-major axis in the inner binary" + "--A_min option to set the value of the semi-major axis in the " + "inner binary" ) self.inner_semi = inner_semi_min elif inner_semi_distr == 2: # Tokovinin Lognormal mu=10^5d, sigma=2.3 @@ -970,8 +853,8 @@ def generate_incl(self, incl_max, incl_min, incl_distr): ) self.incl = incl_min else: # Circular uniform distribution - self.incl = np.arccos( - np.random.uniform(np.cos(incl_min), np.cos(incl_max)) + self.incl = arccos( + np.random.uniform(cos(incl_min), cos(incl_max)) ) def generate_aop( @@ -999,7 +882,10 @@ def generate_aop( ) self.inner_aop = inner_aop_min else: # Uniform distribution - self.inner_aop = np.random.uniform(inner_aop_min, inner_aop_max) + self.inner_aop = np.random.uniform( + inner_aop_min.value_in(units.rad), + inner_aop_max.value_in(units.rad), + ) if outer_aop_max == outer_aop_min: self.outer_aop = outer_aop_min @@ -1014,7 +900,10 @@ def generate_aop( ) self.outer_aop = outer_aop_min else: # Uniform distribution - self.outer_aop = np.random.uniform(outer_aop_min, outer_aop_max) + self.outer_aop = np.random.uniform( + outer_aop_min.value_in(units.rad), + outer_aop_max.value_in(units.rad), + ) def generate_loan(self, inner_loan_max, inner_loan_min, inner_loan_distr): if REPORT_TPS: @@ -1024,8 +913,8 @@ def generate_loan(self, inner_loan_max, inner_loan_min, inner_loan_distr): self.inner_loan = inner_loan_min else: if inner_loan_distr == 0: # Circular uniform distribution - self.inner_loan = np.arccos( - np.random.uniform(np.cos(inner_loan_min), np.cos(inner_loan_max)) + self.inner_loan = arccos( + np.random.uniform(cos(inner_loan_min), cos(inner_loan_max)) ) else: # Constant if REPORT_USER_WARNINGS_TPS: @@ -1550,61 +1439,61 @@ def print_distr( "Primary mass: \t\t", inner_primary_mass_distr, " ", - lib_inner_primary_mass_distr[inner_primary_mass_distr], + td.lib_inner_primary_mass_distr[inner_primary_mass_distr], ) print( "Inner mass ratio: \t", inner_mass_ratio_distr, " ", - lib_inner_mass_ratio_distr[inner_mass_ratio_distr], + td.lib_inner_mass_ratio_distr[inner_mass_ratio_distr], ) print( "Outer mass ratio: \t", outer_mass_ratio_distr, " ", - lib_outer_mass_ratio_distr[outer_mass_ratio_distr], + td.lib_outer_mass_ratio_distr[outer_mass_ratio_distr], ) print( "Inner semi-major axis: \t", inner_semi_distr, " ", - lib_inner_semi_distr[inner_semi_distr], + td.lib_inner_semi_distr[inner_semi_distr], ) print( "Outer semi-major axis: \t", outer_semi_distr, " ", - lib_outer_semi_distr[outer_semi_distr], + td.lib_outer_semi_distr[outer_semi_distr], ) print( "Inner eccentricity: \t", inner_ecc_distr, " ", - lib_inner_ecc_distr[inner_ecc_distr], + td.lib_inner_ecc_distr[inner_ecc_distr], ) print( "Outer eccentricity: \t", outer_ecc_distr, " ", - lib_outer_ecc_distr[outer_ecc_distr], + td.lib_outer_ecc_distr[outer_ecc_distr], ) - print("Inclination: \t\t", incl_distr, " ", lib_incl_distr[incl_distr]) - print("Inner aop: \t\t", inner_aop_distr, " ", lib_inner_aop_distr[inner_aop_distr]) - print("Outer aop: \t\t", outer_aop_distr, " ", lib_outer_aop_distr[outer_aop_distr]) + print("Inclination: \t\t", incl_distr, " ", td.lib_incl_distr[incl_distr]) + print("Inner aop: \t\t", inner_aop_distr, " ", td.lib_inner_aop_distr[inner_aop_distr]) + print("Outer aop: \t\t", outer_aop_distr, " ", td.lib_outer_aop_distr[outer_aop_distr]) print( "Inner loan: \t\t", inner_loan_distr, " ", - lib_inner_loan_distr[inner_loan_distr], + td.lib_inner_loan_distr[inner_loan_distr], ) print( "Common envelope model: \t", which_common_envelope, " ", - lib_CE[which_common_envelope], + td.lib_CE[which_common_envelope], ) - print("SN kick distr: \t\t", SN_kick_distr, " ", lib_SN_kick_distr[SN_kick_distr]) - print("Metallicity: \t\t", "-", " ", metallicity.value_in(units.none)) + print("SN kick distr: \t\t", SN_kick_distr, " ", td.lib_SN_kick_distr[SN_kick_distr]) + print("Metallicity: \t\t", "-", " ", metallicity) print("\n") print("Based on the following assumptions:") @@ -1836,592 +1725,581 @@ def test_initial_parameters( def parse_arguments(): - parser = OptionParser() - parser.add_option( + parser = argparse.ArgumentParser( + formatter_class=argparse.ArgumentDefaultsHelpFormatter, + ) + parser.add_argument( "--M_min", "--M1_min", - unit=units.MSun, + type=units.MSun, dest="inner_primary_mass_min", - type="float", default=1.0 | units.MSun, - help="minimum of inner primary mass [%default]", + help="minimum of inner primary mass", ) - parser.add_option( + parser.add_argument( "--M_max", "--M1_max", - unit=units.MSun, + type=units.MSun, dest="inner_primary_mass_max", - type="float", default=absolute_max_mass, - help="maximum of inner primary mass [%default]", + help="maximum of inner primary mass ", ) - parser.add_option( + parser.add_argument( "--M_distr", "--M1_distr", dest="inner_primary_mass_distr", - type="int", + type=int, default=0, help="inner primary mass distribution [Kroupa]", ) - parser.add_option( + parser.add_argument( "--m_min", "--M2_min", - unit=units.MSun, + type=units.MSun, dest="inner_secondary_mass_min", - type="float", default=absolute_min_mass, - help="minimum of inner secondary mass [%default]", + help="minimum of inner secondary mass ", ) # only used for inner_mass_ratio_distr == 1:# Kroupa 2001 - parser.add_option( + parser.add_argument( "--m_max", "--M2_max", - unit=units.MSun, + type=units.MSun, dest="inner_secondary_mass_max", - type="float", default=absolute_max_mass, - help="maximum of inner secondary mass [%default]", + help="maximum of inner secondary mass ", ) - parser.add_option( + parser.add_argument( "--l_min", "--M3_min", - unit=units.MSun, + type=units.MSun, dest="outer_mass_min", - type="float", default=absolute_min_mass, - help="minimum of outer mass [%default]", + help="minimum of outer mass ", ) - parser.add_option( + parser.add_argument( "--l_max", "--M3_max", - unit=units.MSun, + type=units.MSun, dest="outer_mass_max", - type="float", default=absolute_max_mass, - help="maximum of outer mass [%default]", + help="maximum of outer mass ", ) - parser.add_option( + parser.add_argument( "--Q_max", "--Qin_max", dest="inner_mass_ratio_max", - type="float", + type=float, default=1.0, - help="maximum of inner mass ratio [%default]", + help="maximum of inner mass ratio ", ) - parser.add_option( + parser.add_argument( "--Q_min", "--Qin_min", dest="inner_mass_ratio_min", - type="float", + type=float, default=0.0, - help="minimum of inner mass ratio [%default]", + help="minimum of inner mass ratio ", ) - parser.add_option( + parser.add_argument( "--Q_distr", "--Qin_distr", dest="inner_mass_ratio_distr", - type="int", + type=int, default=0, help="inner mass ratio distribution [Flat]", ) - parser.add_option( + parser.add_argument( "--q_max", "--Qout_max", dest="outer_mass_ratio_max", - type="float", + type=float, default=1.0, - help="maximum of outer mass ratio [%default]", + help="maximum of outer mass ratio ", ) - parser.add_option( + parser.add_argument( "--q_min", "--Qout_min", dest="outer_mass_ratio_min", - type="float", + type=float, default=0.0, - help="minimum of outer mass ratio [%default]", + help="minimum of outer mass ratio ", ) - parser.add_option( + parser.add_argument( "--q_distr", "--Qout_distr", dest="outer_mass_ratio_distr", - type="int", + type=int, default=0, help="outer mass ratio distribution [Flat]", ) - parser.add_option( + parser.add_argument( "--A_min", "--Ain_min", - unit=units.RSun, + type=units.RSun, dest="inner_semi_min", - type="float", default=0.5 | units.RSun, - help="minimum of inner semi major axis [%default]", + help="minimum of inner semi major axis ", ) - parser.add_option( + parser.add_argument( "--A_max", "--Ain_max", - unit=units.RSun, + type=units.RSun, dest="inner_semi_max", - type="float", default=5e6 | units.RSun, - help="maximum of inner semi major axis [%default]", + help="maximum of inner semi major axis ", ) - parser.add_option( + parser.add_argument( "--A_distr", "--Ain_distr", dest="inner_semi_distr", - type="int", + type=int, default=0, help="inner semimajor axis distribution [logFlat]", ) - parser.add_option( + parser.add_argument( "--a_min", "--Aout_min", - unit=units.RSun, + type=units.RSun, dest="outer_semi_min", - type="float", default=0.5 | units.RSun, - help="minimum of outer semi major axis [%default]", + help="minimum of outer semi major axis ", ) - parser.add_option( + parser.add_argument( "--a_max", "--Aout_max", - unit=units.RSun, + type=units.RSun, dest="outer_semi_max", - type="float", default=5e6 | units.RSun, - help="maximum of outer semi major axis [%default]", + help="maximum of outer semi major axis ", ) - parser.add_option( + parser.add_argument( "--a_distr", "--Aout_distr", dest="outer_semi_distr", - type="int", + type=int, default=0, help="outer semimajor axis distribution [logFlat]", ) - parser.add_option( + parser.add_argument( "--Ar_min", "--Arin_min", dest="inner_semi_latus_rectum_min", action="store_true", default=False, - help="minimum inner semi latus rectrum [%default] %unit", + help="minimum inner semi latus rectrum ", ) - parser.add_option( + parser.add_argument( "--ar_min", "--Arout_min", dest="outer_semi_latus_rectum_min", action="store_true", default=False, - help="minimum outer semi latus rectrum [%default] %unit", + help="minimum outer semi latus rectrum ", ) - parser.add_option( + parser.add_argument( "--Ar_max", "--Arin_max", dest="inner_semi_latus_rectum_max", action="store_true", default=False, - help="maximum inner semi latus rectrum [%default] %unit", + help="maximum inner semi latus rectrum ", ) - parser.add_option( + parser.add_argument( "--ar_max", "--Arout_max", dest="outer_semi_latus_rectum_max", action="store_true", default=False, - help="maximum outer semi latus rectrum [%default] %unit", + help="maximum outer semi latus rectrum ", ) - parser.add_option( + parser.add_argument( "--E_min", "--Ein_min", dest="inner_ecc_min", - type="float", + type=float, default=0.0, - help="minimum of inner eccentricity [%default]", + help="minimum of inner eccentricity ", ) - parser.add_option( + parser.add_argument( "--E_max", "--Ein_max", dest="inner_ecc_max", - type="float", + type=float, default=0.9, - help="maximum of inner eccentricity [%default]", + help="maximum of inner eccentricity ", ) - parser.add_option( + parser.add_argument( "--E_distr", "--Ein_distr", dest="inner_ecc_distr", - type="int", + type=int, default=0, help="inner eccentricity distribution [Thermal]", ) - parser.add_option( + parser.add_argument( "--e_min", "--Eout_min", dest="outer_ecc_min", - type="float", + type=float, default=0.0, - help="minimum of outer eccentricity [%default]", + help="minimum of outer eccentricity ", ) - parser.add_option( + parser.add_argument( "--e_max", "--Eout_max", dest="outer_ecc_max", - type="float", + type=float, default=0.9, - help="maximum of outer eccentricity [%default]", + help="maximum of outer eccentricity ", ) - parser.add_option( + parser.add_argument( "--e_distr", "--Eout_distr", dest="outer_ecc_distr", - type="int", + type=int, default=0, help="outer eccentricity distribution [Thermal]", ) - parser.add_option( + parser.add_argument( "--i_min, --I_min", dest="incl_min", - type="float", - default=0.0, - help="minimum of relative inclination [rad] [%default]", + type=units.rad, + default=0.0 | units.rad, + help="minimum of relative inclination [rad] ", ) - parser.add_option( + parser.add_argument( "--i_max, --I_max", dest="incl_max", - type="float", - default=np.pi, - help="maximum of relative inclination [rad] [%default]", + type=units.rad, + default=np.pi | units.rad, + help="maximum of relative inclination [rad] ", ) - parser.add_option( + parser.add_argument( "--i_distr, --I_distr", dest="incl_distr", - type="int", + type=int, default=0, help="relative inclination distribution [Circular uniform]", ) - parser.add_option( + parser.add_argument( "--G_min", "--Gin_min", dest="inner_aop_min", - type="float", - default=-np.pi, - help="minimum of inner argument of pericenter [rad] [%default]", + type=units.rad, + default=-np.pi | units.rad, + help="minimum of inner argument of pericenter", ) - parser.add_option( + parser.add_argument( "--G_max", "--Gin_max", dest="inner_aop_max", - type="float", - default=np.pi, - help="maximum of inner argument of pericenter [rad] [%default]", + type=units.rad, + default=np.pi | units.rad, + help="maximum of inner argument of pericenter [rad] ", ) - parser.add_option( + parser.add_argument( "--G_distr", "--Gin_distr", dest="inner_aop_distr", - type="int", + type=int, default=0, help="inner argument of pericenter distribution [Uniform]", ) - parser.add_option( + parser.add_argument( "--g_min", "--Gout_min", dest="outer_aop_min", - type="float", - default=-np.pi, - help="minimum of outer argument of pericenter [rad] [%default]", + type=units.rad, + default=-np.pi | units.rad, + help="minimum of outer argument of pericenter [rad] ", ) - parser.add_option( + parser.add_argument( "--g_max", "--Gout_max", dest="outer_aop_max", - type="float", - default=np.pi, - help="maximum of outer argument of pericenter [rad] [%default]", + type=units.rad, + default=np.pi | units.rad, + help="maximum of outer argument of pericenter [rad] ", ) - parser.add_option( + parser.add_argument( "--g_distr", "--Gout_distr", dest="outer_aop_distr", - type="int", + type=int, default=0, help="outer argument of pericenter distribution [Uniform]", ) - parser.add_option( + parser.add_argument( "--O_min", "--Oin_min", dest="inner_loan_min", - type="float", - default=-np.pi, - help="minimum of inner longitude of ascending node [rad] [%default]", + type=units.rad, + default=-np.pi | units.rad, + help="minimum of inner longitude of ascending node [rad] ", ) - parser.add_option( + parser.add_argument( "--O_max", "--Oin_max", dest="inner_loan_max", - type="float", - default=np.pi, - help="maximum of inner longitude of ascending node [rad] [%default]", + type=units.rad, + default=np.pi | units.rad, + help="maximum of inner longitude of ascending node [rad] ", ) - parser.add_option( + parser.add_argument( "--O_distr", "--Oin_distr", dest="inner_loan_distr", - type="int", + type=int, default=1, help="inner longitude of ascending node distribution [Constant]", ) - parser.add_option( + parser.add_argument( "-z", "-Z", - unit=units.none, dest="metallicity", - type="float", - default=0.02 | units.none, - help="metallicity [%default] %unit", + type=float, + default=0.02, + help="metallicity", ) - parser.add_option( + parser.add_argument( "-t", "-T", - unit=units.Myr, + type=units.Myr, dest="tend", - type="float", default=13500 | units.Myr, - help="end time [%default] %unit", + help="end time", ) - parser.add_option( + parser.add_argument( "-n", dest="number", - type="int", + type=int, default=10, - help="total number of systems to be simulated [%default]", + help="total number of systems to be simulated ", ) - parser.add_option( + parser.add_argument( "-N", dest="initial_number", - type="int", + type=int, default=0, - help="number ID of first system [%default]", + help="number ID of first system ", ) - parser.add_option( + parser.add_argument( "-s", - unit=units.none, dest="seed", - type="float", - default=0.0 | units.none, - help="seed [%default] %unit", + type=int, + default=0, + help="seed", ) # int actual_seed = srandinter(input_seed); - parser.add_option( + parser.add_argument( "--no_stop_at_mass_transfer", dest="stop_at_mass_transfer", action="store_false", default=True, - help="stop at mass transfer [%default] %unit", + help="stop at mass transfer", ) - parser.add_option( + parser.add_argument( "--no_stop_at_init_mass_transfer", dest="stop_at_init_mass_transfer", action="store_false", default=True, - help="stop if initially mass transfer[%default] %unit", + help="stop if initially mass transfer", ) - parser.add_option( + parser.add_argument( "--no_stop_at_outer_mass_transfer", dest="stop_at_outer_mass_transfer", action="store_false", default=True, - help="stop at outer mass transfer [%default] %unit", + help="stop at outer mass transfer", ) # if stop_at_mass_transfer is False, the following 4 stopping conditions can be used to further specify. # if stop_at_mass_transfer is True, the following 4 are ignored. - parser.add_option( + parser.add_argument( "--stop_at_stable_mass_transfer", dest="stop_at_stable_mass_transfer", action="store_true", default=False, - help="stop at stable mass transfer [%default] %unit", + help="stop at stable mass transfer", ) - parser.add_option( + parser.add_argument( "--stop_at_eccentric_stable_mass_transfer", dest="stop_at_eccentric_stable_mass_transfer", action="store_true", default=False, - help="stop at eccentric stable mass transfer [%default] %unit", + help="stop at eccentric stable mass transfer", ) # unstable mass transfer leads to common-envelope evolution - parser.add_option( + parser.add_argument( "--stop_at_unstable_mass_transfer", dest="stop_at_unstable_mass_transfer", action="store_true", default=False, - help="stop at unstable mass transfer [%default] %unit", + help="stop at unstable mass transfer", ) - parser.add_option( + parser.add_argument( "--stop_at_eccentric_unstable_mass_transfer", dest="stop_at_eccentric_unstable_mass_transfer", action="store_true", default=False, - help="stop at eccentric unstable mass transfer [%default] %unit", + help="stop at eccentric unstable mass transfer", ) - parser.add_option( + parser.add_argument( "--CE", dest="which_common_envelope", - type="int", + type=int, default=2, - help="which common envelope modeling [%default]", + help="which common envelope modeling ", ) - parser.add_option( + parser.add_argument( "--stop_at_no_CHE", dest="stop_at_no_CHE", action="store_true", default=False, - help="stop if no chemically homogeneous evolution [%default] %unit", + help="stop if no chemically homogeneous evolution", ) - parser.add_option( + parser.add_argument( "--include_CHE", dest="include_CHE", action="store_true", default=False, - help="include chemically homogeneous evolution in the stellar evolution [%default] %unit", + help="include chemically homogeneous evolution in the stellar evolution", ) - parser.add_option( + parser.add_argument( "--include_circularisation_during_preMS", dest="include_circ", action="store_true", default=False, - help="include circularisation during pre-MS [%default] %unit", + help="include circularisation during pre-MS", ) - parser.add_option( + parser.add_argument( "--no_stop_at_merger", dest="stop_at_merger", action="store_false", default=True, - help="stop at merger [%default] %unit", + help="stop at merger", ) - parser.add_option( + parser.add_argument( "--no_stop_at_disintegrated", dest="stop_at_disintegrated", action="store_false", default=True, - help="stop at disintegrated [%default] %unit", + help="stop at disintegrated", ) - parser.add_option( + parser.add_argument( "--no_stop_at_inner_collision", dest="stop_at_inner_collision", action="store_false", default=True, - help="stop at collision in inner binary[%default] %unit", + help="stop at collision in inner binary", ) - parser.add_option( + parser.add_argument( "--no_stop_at_outer_collision", dest="stop_at_outer_collision", action="store_false", default=True, - help="stop at collision in outer binary[%default] %unit", + help="stop at collision in outer binary", ) - parser.add_option( + parser.add_argument( "--no_stop_at_dynamical_instability", dest="stop_at_dynamical_instability", action="store_false", default=True, - help="stop at dynamical instability [%default] %unit", + help="stop at dynamical instability", ) - parser.add_option( + parser.add_argument( "--stop_at_semisecular_regime", dest="stop_at_semisecular_regime", action="store_true", default=False, - help="stop at semisecular regime [%default] %unit", + help="stop at semisecular regime", ) - parser.add_option( + parser.add_argument( "--stop_at_SN", dest="stop_at_SN", action="store_true", default=False, - help="stop at supernova [%default] %unit", + help="stop at supernova", ) - parser.add_option( + parser.add_argument( "--SN_kick_distr", dest="SN_kick_distr", - type="int", + type=int, default=5, - help="which supernova kick distribution [%default]", + help="which supernova kick distribution", ) - parser.add_option( + parser.add_argument( "--no_impulse_kick_for_black_holes", dest="impulse_kick_for_black_holes", action="store_false", default=True, - help="do not rescale the BH SN kick by mass -> impulse kick [%default]", + help="do not rescale the BH SN kick by mass -> impulse kick", ) - parser.add_option( + parser.add_argument( "--no_fallback_kick_for_black_holes", dest="fallback_kick_for_black_holes", action="store_false", default=True, - help="do not rescale the BH SN kick with fallback [%default]", + help="do not rescale the BH SN kick with fallback", ) - parser.add_option( + parser.add_argument( "--stop_at_CPU_time", dest="stop_at_CPU_time", action="store_true", default=False, - help="stop at CPU time [%default] %unit", + help="stop at CPU time", ) - parser.add_option( + parser.add_argument( "--max_CPU_time", dest="max_CPU_time", - type="float", - default=3600.0, - help="max CPU time [%default] %unit", + type=units.s, + default=3600.0 | units.s, + help="max CPU time", ) - parser.add_option( + parser.add_argument( "-f", dest="file_name", - type="string", + type=str, default="TRES.hdf", # "TRES.txt" - help="file name[%default]", + help="file name", ) - parser.add_option( + parser.add_argument( "-F", dest="file_type", - type="string", + type=str, default="hdf5", # "txt" - help="file type[%default]", + help="file type", ) - parser.add_option( + parser.add_argument( "--dir_plots", dest="dir_plots", - type="string", + type=str, default="", # "txt" - help="directory for plots for debugging mode [%default]", + help="directory for plots for debugging mode ", ) - options, args = parser.parse_args() - return options.__dict__ + args = parser.parse_args() + return args.__dict__ if __name__ == "__main__": From ebb4e9ba2227a473d23c1f522f8604fd8321291c Mon Sep 17 00:00:00 2001 From: Steven Rieder Date: Mon, 11 Nov 2024 13:31:07 +0100 Subject: [PATCH 29/30] split off distributions from tps.py --- src/tres/distributions.py | 106 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 106 insertions(+) create mode 100644 src/tres/distributions.py diff --git a/src/tres/distributions.py b/src/tres/distributions.py new file mode 100644 index 0000000..c332161 --- /dev/null +++ b/src/tres/distributions.py @@ -0,0 +1,106 @@ +lib_inner_primary_mass_distr = { + 0: "Kroupa", # default + 1: "Scalo", + 2: "Miller & Scalo", + 3: "Salpeter", + 4: "Logarithmically flat", + 5: "Eggleton", + 6: "Kroupa for massive stars M>0.5 powerlaw with exp=-2.3", +} + +# draws from mass distribution instead of mass ratio distribution, appropriate +# for planets +lib_inner_mass_ratio_distr = { + 0: "Uniform distribution", # default + 1: "Kroupa IMF", # draws from mass distribution instead of mass ratio distribution + 2: "Galicher et al. 2016 powerlaw (M^-1.31)", +} + +# draws from mass distribution instead of mass ratio distribution, appropriate +# for planets +lib_outer_mass_ratio_distr = { + 0: "Uniform distribution", # default + 1: "Kroupa IMF", # draws from mass distribution instead of mass ratio distribution + 2: "Galicher et al. 2016 powerlaw (M^-1.31)", +} + +# appropriate for planets +lib_inner_semi_distr = { + 0: "Log Uniform distribution", # default + 1: "Constant semi-major axis", + 2: "Tokovinin lognormal mu = 10^5d, sigma = 2.3", + 3: "Lognormal mu = 10^3.5d, sigma = 2.3", + 4: "Rizzuto Lognormal mu = 10^0.95 AU, sigma = 1.35", + 5: "Sana et al. 2012", + 6: "flat distribution", + 7: "Galicher et al. 2016 powerlaw (a^-0.61)", +} + +# appropriate for planets +lib_outer_semi_distr = { + 0: "Log Uniform distribution", # default + 1: "Constant semi-major axis", + 2: "Tokovinin lognormal mu = 10^5d, sigma = 2.3", + 3: "Lognormal mu = 10^3.5d, sigma = 2.3", + 4: "Rizzuto Lognormal mu = 10^0.95 AU, sigma = 1.35", + 5: "Sana et al. 2012", + 6: "flat distribution", + 7: "Galicher et al. 2016 powerlaw (a^-0.61)", +} + +# appropriate for planets +lib_inner_ecc_distr = { + 0: "Thermal", # default + 1: "Constant eccentricity", + 2: "Sana et al. 2012 e^-0.45", # -> close binaries + 3: "Flat distribution", + 4: "Powerlaw e^0.5", + 5: "Bowler et al. 2020 Beta distribution", +} + +# appropriate for planets +lib_outer_ecc_distr = { + 0: "Thermal", # default + 1: "Constant eccentricity", + 2: "Sana et al. 2012 e^-0.45", # -> close binaries + 3: "Flat distribution", + 4: "Powerlaw e^0.5", + 5: "Bowler et al. 2020 Beta distribution", +} + +lib_incl_distr = { + 0: "Circular uniform distribution", # default + 1: "Constant inclination", +} + +lib_inner_aop_distr = { + 0: "Uniform distribution", # default + 1: "Constant argument of pericenter", +} + +lib_outer_aop_distr = { + 0: "Uniform distribution", # default + 1: "Constant argument of pericenter", +} + +# default +lib_inner_loan_distr = { + 0: "Circular niform distribution", + 1: "Constant longitude of ascending nodes", +} + +# default +lib_SN_kick_distr = { + 0: "No kick", + 1: "Hobbs", # Hobbs, Lorimer, Lyne & Kramer 2005, 360, 974 + 2: "Arzoumanian", # Arzoumanian ea 2002, 568, 289 + 3: "Hansen", # Hansen & Phinney 1997, 291, 569 + 4: "Paczynski", # Paczynski 1990, 348, 485 + 5: "Verbunt", # Verbunt, Igoshev & Cator, 2017, 608, 57 +} + +lib_CE = { + 0: "alpha-ce + alpha-dce", + 1: "gamma-ce + alpha-dce", + 2: "seba style; combination of gamma-ce, alpha-ce & alpha-dce", +} From 5c7523a2b0062461dca9014d0abf1492834a057d Mon Sep 17 00:00:00 2001 From: Steven Rieder Date: Mon, 11 Nov 2024 13:33:36 +0100 Subject: [PATCH 30/30] fix --- src/tres/seculartriple/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tres/seculartriple/Makefile b/src/tres/seculartriple/Makefile index 74ba038..679d0dd 100644 --- a/src/tres/seculartriple/Makefile +++ b/src/tres/seculartriple/Makefile @@ -26,7 +26,7 @@ worker_code.cc: interface.py $(CODE_GENERATOR) --type=c interface.py SecularTripleInterface -o $@ seculartriple_worker: worker_code.cc $(OBJS) - $(MPICXX) $(CXXFLAGS) $@.cc $(OBJS) -o $@ + $(MPICXX) $(CXXFLAGS) worker_code.cc $(OBJS) -o $@ .cc.o: $< $(CXX) $(CXXFLAGS) -c -o $@ $<