diff --git a/.github/workflows/cmc-review.yml b/.github/workflows/cmc-review.yml index 18fd92d76..844302f5e 100644 --- a/.github/workflows/cmc-review.yml +++ b/.github/workflows/cmc-review.yml @@ -5,6 +5,7 @@ on: types: [opened] paths: - 'src/cosmic/evolve.py' + - 'src/cosmic/consts.py' - 'src/cosmic/data/cosmic-settings.json' - 'src/cosmic/src/ran3.f' diff --git a/changelog.md b/changelog.md index d93272527..03332eb30 100644 --- a/changelog.md +++ b/changelog.md @@ -9,8 +9,9 @@ - Code cleanup - Function signature for kick() and evolv2() in the fortran changed to remove ``bkick`` entirely - Also removed ``kick_info_out``. Both of these can be reconstructed from ``kick_info`` + - [Just for developers] Created ``consts.py`` which ``evolve.py`` now draws from, loops over GROUPED_SETTINGS instead of giant chunk of assignments -- Bug fixes: c +- Bug fixes: - corrected mass sign in bjorklund wind routine in SSE_mlwind.f - fixed bug in ``bhspinmag`` assignment in ``assign_remnant.f`` diff --git a/docs/pages/develop/new-settings.rst b/docs/pages/develop/new-settings.rst index b56f9a3b0..374663760 100644 --- a/docs/pages/develop/new-settings.rst +++ b/docs/pages/develop/new-settings.rst @@ -13,9 +13,7 @@ This page guides you through adding an entirely new setting to COSMIC. If you ju - ``src/cosmic/src/const_bse.h``: Initialise a new variable and add it to the relevant common block - ``src/cosmic/data/cosmic-settings.json``: Add the setting to the JSON file, with a description and default value - - ``src/cosmic/evolve.py`` - - Add variable to ``INITIAL_CONDITIONS_BSE_COLUMNS`` - - Add variable in ``_evolve_single_system()`` list + - ``src/cosmic/consts.py`` - Add settings to correct group in ``GROUPED_SETTINGS`` dict - ``src/cosmic/tests/data``: Update initC files and params.ini with new setting - ``src/cosmic/tests/data/initial_conditions_for_testing.hdf5`` - ``src/cosmic/tests/data/kick_initial_conditions.h5`` @@ -25,7 +23,7 @@ This page guides you through adding an entirely new setting to COSMIC. If you ju Adding a new setting to ``COSMIC`` is a little more involved than just adding an options. Settings are stored in common blocks in the Fortran code so that they can be accessed anywhere in the code. Let's do it step by step. -Throughout this example, let's say we want to add a new setting called ``lbv_flag`` that sets the prescription for luminous blue variable mass loss. +Throughout this example, let's say we want to add a new setting called ``LBV_flag`` that sets the prescription for luminous blue variable mass loss. Add new setting to a common block ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -55,7 +53,7 @@ In ``src/cosmic/data/cosmic-settings.json``, we add a new entry for our setting: .. code-block:: json - "name": "lbv_flag", + "name": "LBV_flag", "description": "Flag for luminous blue variable wind mass loss prescription.", "type": "dropdown", "options-preface": "", @@ -83,22 +81,15 @@ In ``src/cosmic/data/cosmic-settings.json``, we add a new entry for our setting: Pass the setting from evolve() to the Fortran code ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Now we need to pass the setting from the Python code in ``evolve.py`` to the Fortran code. This is done in the ``_evolve_single_system()`` function in ``src/cosmic/evolve.py``. But first, we need to add the new setting to the list of columns in the initial binary table. This is done by adding it to the ``INITIAL_CONDITIONS_BSE_COLUMNS`` list at the top of ``src/cosmic/evolve.py``: +Now we need to pass the setting from the Python code in ``evolve.py`` to the Fortran code. This is actually handled in ``src/cosmic/consts.py``, where we have a dictionary called ``GROUPED_SETTINGS`` that groups settings by the common block they belong to. We need to add our new setting to the correct group in this dictionary: .. code-block:: python - # dots are representing the existing columns - INITIAL_CONDITIONS_BSE_COLUMNS = [..., 'lbv_flag'] - -Now we change the ``_evolve_single_system()`` function to pass the new setting to the Fortran code. In the list of flags that is passed to the Fortran code, we add our new setting: - -.. code-block:: python - - _evolvebin.windvars.lbv_flag = f["lbv_flag"] - -.. warning:: - - Make sure you use the right common block here (``windvars`` in this case) otherwise the setting won't get properly passed but will also not throw an error which can be very confusing to debug! (I have made this mistake before and it was not fun to figure out what was going wrong) + GROUPED_SETTINGS = { + ..., + "windvars": [..., "LBV_flag"], + ... + } Use the new setting in the Fortran code ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -135,6 +126,6 @@ For the params.ini file, add a new entry for the new setting with a reasonable d with open("src/cosmic/tests/data/Params.ini", "a") as f: f.write(f"\n\n{setting_name} = {setting_value}\n\n") - add_setting_to_test_files("lbv_flag", 1) + add_setting_to_test_files("LBV_flag", 1) And that's it! You've added a new setting to COSMIC. Now you should absolutely run the tests to make sure everything is working properly! Better yet, add more tests that specifically test the new setting to make sure it's working as expected. \ No newline at end of file diff --git a/src/cosmic/consts.py b/src/cosmic/consts.py new file mode 100644 index 000000000..f3d94c627 --- /dev/null +++ b/src/cosmic/consts.py @@ -0,0 +1,66 @@ +__all__ = ['ALL_COLUMNS', 'INTEGER_COLUMNS', 'BPP_COLUMNS', 'BCM_COLUMNS', 'KICK_COLUMNS', 'GROUPED_SETTINGS'] + +# Make this match the ordering of all_cols in bpp_array.f +ALL_COLUMNS = ['tphys', 'mass_1', 'mass_2', 'kstar_1', 'kstar_2', 'sep', 'porb', + 'ecc', 'RRLO_1', 'RRLO_2', 'evol_type', 'aj_1', 'aj_2', 'tms_1', + 'tms_2', 'massc_he_layer_1', 'massc_he_layer_2', 'massc_co_layer_1', 'massc_co_layer_2', + 'rad_1', 'rad_2', 'mass0_1', + 'mass0_2', 'lum_1', 'lum_2', 'teff_1', 'teff_2', 'radc_1', + 'radc_2', 'menv_1', 'menv_2', 'renv_1', 'renv_2', 'omega_spin_1', + 'omega_spin_2', 'B_1', 'B_2', 'bacc_1', 'bacc_2', 'tacc_1', + 'tacc_2', 'epoch_1', 'epoch_2', 'bhspin_1', 'bhspin_2', + 'deltam_1', 'deltam_2', 'SN_1', 'SN_2', 'bin_state', 'merger_type', 'metallicity'] + +INTEGER_COLUMNS = ["bin_state", "bin_num", "kstar_1", "kstar_2", "SN_1", "SN_2", "evol_type"] + +BPP_COLUMNS = ['tphys', 'mass_1', 'mass_2', 'kstar_1', 'kstar_2', + 'sep', 'porb', 'ecc', 'RRLO_1', 'RRLO_2', 'evol_type', + 'aj_1', 'aj_2', 'tms_1', 'tms_2', + 'massc_he_layer_1', 'massc_he_layer_2', 'massc_co_layer_1', 'massc_co_layer_2', 'rad_1', 'rad_2', + 'mass0_1', 'mass0_2', 'lum_1', 'lum_2', 'teff_1', 'teff_2', + 'radc_1', 'radc_2', 'menv_1', 'menv_2', 'renv_1', 'renv_2', + 'omega_spin_1', 'omega_spin_2', 'B_1', 'B_2', 'bacc_1', 'bacc_2', + 'tacc_1', 'tacc_2', 'epoch_1', 'epoch_2', + 'bhspin_1', 'bhspin_2'] + +BCM_COLUMNS = ['tphys', 'kstar_1', 'mass0_1', 'mass_1', 'lum_1', 'rad_1', + 'teff_1', 'massc_he_layer_1', 'massc_co_layer_1', 'radc_1', 'menv_1', 'renv_1', 'epoch_1', + 'omega_spin_1', 'deltam_1', 'RRLO_1', 'kstar_2', 'mass0_2', 'mass_2', + 'lum_2', 'rad_2', 'teff_2', 'massc_he_layer_2', 'massc_co_layer_2', 'radc_2', 'menv_2', + 'renv_2', 'epoch_2', 'omega_spin_2', 'deltam_2', 'RRLO_2', + 'porb', 'sep', 'ecc', 'B_1', 'B_2', + 'SN_1', 'SN_2', 'bin_state', 'merger_type'] + +KICK_COLUMNS = ['star', 'disrupted', 'natal_kick', 'phi', 'theta', 'mean_anomaly', + 'delta_vsysx_1', 'delta_vsysy_1', 'delta_vsysz_1', 'vsys_1_total', + 'delta_vsysx_2', 'delta_vsysy_2', 'delta_vsysz_2', 'vsys_2_total', + 'theta_euler', 'phi_euler', 'psi_euler', 'randomseed', 'tphys', 'bin_num'] + +GROUPED_SETTINGS = { + "windvars": [ + "neta", "bwind", "hewind", "beta", "xi", "acc2", + "epsnov", "eddfac", "gamma", "LBV_flag", + ], + "cevars": ["alpha1", "lambdaf", "qcrit_array"], + "ceflags": ["ceflag", "cekickflag", "cemergeflag", "cehestarflag", "ussn"], + "flags": [ + "tflag", "ifflag", "wdflag", "rtmsflag", "bhflag", "remnantflag", + "maltsev_mode", "grflag", "bhms_coll_flag", "wd_mass_lim", "aic", + "bdecayfac", "windflag", "qcflag", "eddlimflag", "bhspinflag", + "rejuvflag", "htpmb", "ST_cr", "ST_tide", + ], + "snvars": [ + "pisn", "ppi_co_shift", "ppi_extra_ml", "maltsev_fallback", + "maltsev_pf_prob", "fryer_mass_limit", "mxns", "fryer_fmix", + "fryer_mcrit_nsbh", "ecsn", "ecsn_mlow", "sigma", "sigmadiv", + "bhsigmafrac", "polar_kick_angle", "natal_kick_array", "bhspinmag", + "rembar_massloss", "kickflag", "mm_mu_ns", "mm_mu_bh", + ], + "points": ["pts1", "pts2", "pts3"], + "mtvars": ["don_lim", "acc_lim", "smt_periastron_check"], + "magvars": ["bconst", "ck"], + "tidalvars": ["fprimc_array"], + "mixvars": ["rejuv_fac"], + "metvars": ["zsun"], + "rand1": ["randomseed"] +} \ No newline at end of file diff --git a/src/cosmic/evolve.py b/src/cosmic/evolve.py index 6c3e40faa..301a87f35 100644 --- a/src/cosmic/evolve.py +++ b/src/cosmic/evolve.py @@ -21,6 +21,7 @@ from cosmic import _evolvebin from . import utils +from .consts import ALL_COLUMNS, INTEGER_COLUMNS, BPP_COLUMNS, BCM_COLUMNS, KICK_COLUMNS, GROUPED_SETTINGS from .sample import initialbinarytable from .checkstate import set_checkstates @@ -48,44 +49,6 @@ 'Tom Wagg '] __all__ = ['Evolve', 'read_tracks_for_METISSE', 'populate_tracks'] - -# Make this match the ordering of all_cols in bpp_array.f -ALL_COLUMNS = ['tphys', 'mass_1', 'mass_2', 'kstar_1', 'kstar_2', 'sep', 'porb', - 'ecc', 'RRLO_1', 'RRLO_2', 'evol_type', 'aj_1', 'aj_2', 'tms_1', - 'tms_2', 'massc_he_layer_1', 'massc_he_layer_2', 'massc_co_layer_1', 'massc_co_layer_2', - 'rad_1', 'rad_2', 'mass0_1', - 'mass0_2', 'lum_1', 'lum_2', 'teff_1', 'teff_2', 'radc_1', - 'radc_2', 'menv_1', 'menv_2', 'renv_1', 'renv_2', 'omega_spin_1', - 'omega_spin_2', 'B_1', 'B_2', 'bacc_1', 'bacc_2', 'tacc_1', - 'tacc_2', 'epoch_1', 'epoch_2', 'bhspin_1', 'bhspin_2', - 'deltam_1', 'deltam_2', 'SN_1', 'SN_2', 'bin_state', 'merger_type', 'metallicity'] - -INTEGER_COLUMNS = ["bin_state", "bin_num", "kstar_1", "kstar_2", "SN_1", "SN_2", "evol_type"] - - -BPP_COLUMNS = ['tphys', 'mass_1', 'mass_2', 'kstar_1', 'kstar_2', - 'sep', 'porb', 'ecc', 'RRLO_1', 'RRLO_2', 'evol_type', - 'aj_1', 'aj_2', 'tms_1', 'tms_2', - 'massc_he_layer_1', 'massc_he_layer_2', 'massc_co_layer_1', 'massc_co_layer_2', 'rad_1', 'rad_2', - 'mass0_1', 'mass0_2', 'lum_1', 'lum_2', 'teff_1', 'teff_2', - 'radc_1', 'radc_2', 'menv_1', 'menv_2', 'renv_1', 'renv_2', - 'omega_spin_1', 'omega_spin_2', 'B_1', 'B_2', 'bacc_1', 'bacc_2', - 'tacc_1', 'tacc_2', 'epoch_1', 'epoch_2', - 'bhspin_1', 'bhspin_2'] - -BCM_COLUMNS = ['tphys', 'kstar_1', 'mass0_1', 'mass_1', 'lum_1', 'rad_1', - 'teff_1', 'massc_he_layer_1', 'massc_co_layer_1', 'radc_1', 'menv_1', 'renv_1', 'epoch_1', - 'omega_spin_1', 'deltam_1', 'RRLO_1', 'kstar_2', 'mass0_2', 'mass_2', - 'lum_2', 'rad_2', 'teff_2', 'massc_he_layer_2', 'massc_co_layer_2', 'radc_2', 'menv_2', - 'renv_2', 'epoch_2', 'omega_spin_2', 'deltam_2', 'RRLO_2', - 'porb', 'sep', 'ecc', 'B_1', 'B_2', - 'SN_1', 'SN_2', 'bin_state', 'merger_type'] - -KICK_COLUMNS = ['star', 'disrupted', 'natal_kick', 'phi', 'theta', 'mean_anomaly', - 'delta_vsysx_1', 'delta_vsysy_1', 'delta_vsysz_1', 'vsys_1_total', - 'delta_vsysx_2', 'delta_vsysy_2', 'delta_vsysz_2', 'vsys_2_total', - 'theta_euler', 'phi_euler', 'psi_euler', 'randomseed', 'tphys', 'bin_num'] - # We use the list of column in the initialbinarytable function to initialize # the list of columns that we will send to the fortran evolv2 function. # we also send this in a specific order so this help ensures that the list that @@ -95,35 +58,17 @@ else: INITIAL_CONDITIONS_PASS_COLUMNS = initialbinarytable.INITIAL_CONDITIONS_COLUMNS.copy() -INITIAL_CONDITIONS_BSE_COLUMNS = ['neta', 'bwind', 'hewind', 'alpha1', 'lambdaf', - 'ceflag', 'tflag', 'ifflag', 'wdflag', - 'pisn', 'ppi_co_shift', 'ppi_extra_ml', - 'rtmsflag', - 'bhflag', 'remnantflag', 'fryer_mass_limit', - 'maltsev_mode', 'maltsev_fallback', 'maltsev_pf_prob', - 'grflag', 'bhms_coll_flag', 'wd_mass_lim', - 'cekickflag', 'cemergeflag', 'cehestarflag', - 'mxns', 'pts1', 'pts2', 'pts3', - "fryer_fmix", "fryer_mcrit_nsbh", - 'ecsn', 'ecsn_mlow', 'aic', 'ussn', 'sigma', 'sigmadiv', - 'bhsigmafrac', 'polar_kick_angle', 'mm_mu_ns', 'mm_mu_bh', - 'natal_kick_array', 'qcrit_array', - 'beta', 'xi', 'acc2', 'epsnov', - 'eddfac', 'gamma', 'don_lim', 'acc_lim', 'smt_periastron_check', - 'bdecayfac', 'bconst', 'ck', - 'windflag', 'qcflag', 'eddlimflag', 'LBV_flag', - 'fprimc_array', 'dtp', 'randomseed', - 'bhspinflag', 'bhspinmag', 'rejuv_fac', 'rejuvflag', 'htpmb', - 'ST_cr', 'ST_tide', 'rembar_massloss', 'zsun', 'kickflag'] - -INITIAL_CONDITIONS_MISC_COLUMN = ['bin_num'] - -INITIAL_CONDITIONS_SSE_COLUMN = ['stellar_engine','path_to_tracks','path_to_he_tracks','z_accuracy_limit'] +# construct BSE columns from flattened GROUPED_SETTINGS +INITIAL_CONDITIONS_BSE_COLUMNS = [col for group in GROUPED_SETTINGS.values() for col in group] + +INITIAL_CONDITIONS_MISC_COLUMNS = ['bin_num', 'dtp'] + +INITIAL_CONDITIONS_SSE_COLUMNS = ['stellar_engine', 'path_to_tracks', 'path_to_he_tracks', 'z_accuracy_limit'] # Add the BSE COLUMSN and MISC COLUMN to the PASS_COLUMNS list INITIAL_CONDITIONS_PASS_COLUMNS.extend(INITIAL_CONDITIONS_BSE_COLUMNS) -INITIAL_CONDITIONS_PASS_COLUMNS.extend(INITIAL_CONDITIONS_MISC_COLUMN) -INITIAL_CONDITIONS_PASS_COLUMNS.extend(INITIAL_CONDITIONS_SSE_COLUMN) +INITIAL_CONDITIONS_PASS_COLUMNS.extend(INITIAL_CONDITIONS_MISC_COLUMNS) +INITIAL_CONDITIONS_PASS_COLUMNS.extend(INITIAL_CONDITIONS_SSE_COLUMNS) if sys.version_info.major == 2 and sys.version_info.minor == 7: INITIAL_BINARY_TABLE_SAVE_COLUMNS = INITIAL_CONDITIONS_PASS_COLUMNS[:] @@ -133,11 +78,7 @@ for col in ['natal_kick_array', 'qcrit_array', 'fprimc_array', 'alpha1', 'acc_lim']: INITIAL_BINARY_TABLE_SAVE_COLUMNS.remove(col) -NATAL_KICK_COLUMNS = ['natal_kick', - 'phi', - 'theta', - 'mean_anomaly', - 'randomseed'] +NATAL_KICK_COLUMNS = ['natal_kick', 'phi', 'theta', 'mean_anomaly', 'randomseed'] FLATTENED_NATAL_KICK_COLUMNS = [] for sn_idx in range(2): @@ -324,7 +265,7 @@ def evolve(self, initialbinarytable, pool=None, bpp_columns=None, bcm_columns=No initialbinarytable = initialbinarytable.assign(bin_num=np.arange(idx, idx + len(initialbinarytable))) # ensure SSEDict keys are unique in the initial binary table and warn otherwise - for col in INITIAL_CONDITIONS_SSE_COLUMN: + for col in INITIAL_CONDITIONS_SSE_COLUMNS: if col in initialbinarytable.columns and initialbinarytable[col].nunique() > 1: raise ValueError(f"The value for {col} in the initial binary table is not unique. " f"Please make sure that the value for {col} is the same for all rows in the initial binary table.") @@ -514,7 +455,7 @@ def evolve(self, initialbinarytable, pool=None, bpp_columns=None, bcm_columns=No # if stellar engine is METISSE then check all of the SSE columns are present and if not raise an error if initialbinarytable['stellar_engine'].iloc[0] == 'metisse': - if not set(INITIAL_CONDITIONS_SSE_COLUMN).issubset(initialbinarytable.columns): + if not set(INITIAL_CONDITIONS_SSE_COLUMNS).issubset(initialbinarytable.columns): raise ValueError("If you want to use the METISSE stellar engine, you must provide the following in the SSEDict, initial binary table, or params file: path_to_tracks, path_to_he_tracks, z_accuracy_limit.") else: # if not using METISSE, set default values for the SSE columns if they are not present in the initial binary table @@ -688,78 +629,17 @@ def _evolve_single_system(f, zpars=None): # determine if we already have a compact object, if yes than one SN has already occured if (f["kstar_1"] in range(10, 15)) or (f["kstar_2"] in range(10, 15)): f["kick_info"][0, 0] = 1 - # kstar, mass, orbital period (days), eccentricity, metaliccity, evolution time (millions of years) - _evolvebin.windvars.neta = f["neta"] - _evolvebin.windvars.bwind = f["bwind"] - _evolvebin.windvars.hewind = f["hewind"] - _evolvebin.cevars.alpha1 = f["alpha1"] - _evolvebin.cevars.lambdaf = f["lambdaf"] - _evolvebin.ceflags.ceflag = f["ceflag"] - _evolvebin.flags.tflag = f["tflag"] - _evolvebin.flags.ifflag = f["ifflag"] - _evolvebin.flags.wdflag = f["wdflag"] - _evolvebin.flags.rtmsflag = f["rtmsflag"] - _evolvebin.snvars.pisn = f["pisn"] - _evolvebin.snvars.ppi_co_shift = f["ppi_co_shift"] - _evolvebin.snvars.ppi_extra_ml = f["ppi_extra_ml"] - _evolvebin.flags.bhflag = f["bhflag"] - _evolvebin.flags.remnantflag = f["remnantflag"] - _evolvebin.flags.maltsev_mode = f["maltsev_mode"] - _evolvebin.snvars.maltsev_fallback = f["maltsev_fallback"] - _evolvebin.snvars.maltsev_pf_prob = f["maltsev_pf_prob"] - _evolvebin.snvars.fryer_mass_limit = f["fryer_mass_limit"] - _evolvebin.ceflags.cekickflag = f["cekickflag"] - _evolvebin.ceflags.cemergeflag = f["cemergeflag"] - _evolvebin.ceflags.cehestarflag = f["cehestarflag"] - _evolvebin.flags.grflag = f["grflag"] - _evolvebin.flags.bhms_coll_flag = f["bhms_coll_flag"] - _evolvebin.flags.wd_mass_lim = f["wd_mass_lim"] - _evolvebin.snvars.mxns = f["mxns"] - _evolvebin.points.pts1 = f["pts1"] - _evolvebin.points.pts2 = f["pts2"] - _evolvebin.points.pts3 = f["pts3"] - _evolvebin.snvars.fryer_fmix = f["fryer_fmix"] - _evolvebin.snvars.fryer_mcrit_nsbh = f["fryer_mcrit_nsbh"] - _evolvebin.snvars.ecsn = f["ecsn"] - _evolvebin.snvars.ecsn_mlow = f["ecsn_mlow"] - _evolvebin.flags.aic = f["aic"] - _evolvebin.ceflags.ussn = f["ussn"] - _evolvebin.snvars.sigma = f["sigma"] - _evolvebin.snvars.sigmadiv = f["sigmadiv"] - _evolvebin.snvars.bhsigmafrac = f["bhsigmafrac"] - _evolvebin.snvars.polar_kick_angle = f["polar_kick_angle"] - _evolvebin.snvars.natal_kick_array = f["natal_kick_array"] - _evolvebin.cevars.qcrit_array = f["qcrit_array"] - _evolvebin.mtvars.don_lim = f["don_lim"] - _evolvebin.mtvars.acc_lim = f["acc_lim"] - _evolvebin.mtvars.smt_periastron_check = f["smt_periastron_check"] - _evolvebin.windvars.beta = f["beta"] - _evolvebin.windvars.xi = f["xi"] - _evolvebin.windvars.acc2 = f["acc2"] - _evolvebin.windvars.epsnov = f["epsnov"] - _evolvebin.windvars.eddfac = f["eddfac"] - _evolvebin.windvars.gamma = f["gamma"] - _evolvebin.windvars.lbv_flag = f["LBV_flag"] - _evolvebin.flags.bdecayfac = f["bdecayfac"] - _evolvebin.magvars.bconst = f["bconst"] - _evolvebin.magvars.ck = f["ck"] - _evolvebin.flags.windflag = f["windflag"] - _evolvebin.flags.qcflag = f["qcflag"] - _evolvebin.flags.eddlimflag = f["eddlimflag"] - _evolvebin.tidalvars.fprimc_array = f["fprimc_array"] - _evolvebin.rand1.idum1 = f["randomseed"] - _evolvebin.flags.bhspinflag = f["bhspinflag"] - _evolvebin.snvars.bhspinmag = f["bhspinmag"] - _evolvebin.mixvars.rejuv_fac = f["rejuv_fac"] - _evolvebin.flags.rejuvflag = f["rejuvflag"] - _evolvebin.flags.htpmb = f["htpmb"] - _evolvebin.flags.st_cr = f["ST_cr"] - _evolvebin.flags.st_tide = f["ST_tide"] - _evolvebin.snvars.rembar_massloss = f["rembar_massloss"] - _evolvebin.metvars.zsun = f["zsun"] - _evolvebin.snvars.kickflag = f["kickflag"] - _evolvebin.snvars.mm_mu_ns = f["mm_mu_ns"] - _evolvebin.snvars.mm_mu_bh = f["mm_mu_bh"] + + # you can GROUPED_SETTINGS find this in consts.py + for group, settings in GROUPED_SETTINGS.items(): + for setting in settings: + # special case: we call randomseed idum1 in the fortran (because why make it simple?) + if setting == "randomseed": + _evolvebin.rand1.idum1 = f["randomseed"] + + # otherwise just set the value in the fortran module + else: + setattr(getattr(_evolvebin, group), setting.lower(), f[setting]) _evolvebin.cmcpass.using_cmc = 0 if f["stellar_engine"] == "sse": diff --git a/src/cosmic/meson.build b/src/cosmic/meson.build index 899314bd0..1342ca59c 100644 --- a/src/cosmic/meson.build +++ b/src/cosmic/meson.build @@ -3,6 +3,7 @@ python_sources = [ '_commit_hash.py', '_version.py', 'checkstate.py', + 'consts.py', 'evolve.py', 'filter.py', 'get_commit_hash.py', diff --git a/src/cosmic/tests/test_sample.py b/src/cosmic/tests/test_sample.py index 05155d22e..36afedebc 100644 --- a/src/cosmic/tests/test_sample.py +++ b/src/cosmic/tests/test_sample.py @@ -15,6 +15,7 @@ from cosmic.sample.initialcmctable import InitialCMCTable from scipy.optimize import curve_fit from cosmic.utils import a_from_p, get_porb_norm +import tempfile SAMPLECLASS = Sample() MULTIDIMSAMPLECLASS = MultiDim() @@ -671,15 +672,16 @@ def test_set_reff(self): np.testing.assert_allclose(REFF_TEST_ARRAY, reff) def test_cmc_sampler(self): - np.random.seed(2) - # Test generating CMC initial conditions and test saving the output to files - Singles, Binaries = InitialCMCTable.sampler('cmc', binfrac_model=0.2, primary_model='kroupa01', ecc_model='sana12', porb_model='sana12', cluster_profile='plummer', met=0.014, size=20, params=os.path.join(TEST_DATA_DIR,'Params.ini'), gamma=4, r_max=100, qmin=0.1) - InitialCMCTable.write(Singles, Binaries, filename="input.hdf5") - InitialCMCTable.write(Singles, Binaries, filename="input.fits") - Singles, Binaries = InitialCMCTable.read(filename="input.fits") - # read the test files and compare to the static unit tests files - pd.testing.assert_frame_equal(Singles, SINGLES_CMC_FITS) - pd.testing.assert_frame_equal(Binaries, BINARIES_CMC_FITS) - Singles, Binaries = InitialCMCTable.read(filename="input.hdf5") - pd.testing.assert_frame_equal(Singles, SINGLES_CMC_HDF5) - pd.testing.assert_frame_equal(Binaries, BINARIES_CMC_HDF5) + with tempfile.TemporaryDirectory() as tmpdirname: + np.random.seed(2) + # Test generating CMC initial conditions and test saving the output to files + Singles, Binaries = InitialCMCTable.sampler('cmc', binfrac_model=0.2, primary_model='kroupa01', ecc_model='sana12', porb_model='sana12', cluster_profile='plummer', met=0.014, size=20, params=os.path.join(TEST_DATA_DIR,'Params.ini'), gamma=4, r_max=100, qmin=0.1) + InitialCMCTable.write(Singles, Binaries, filename=f"{tmpdirname}/input.hdf5") + InitialCMCTable.write(Singles, Binaries, filename=f"{tmpdirname}/input.fits") + Singles, Binaries = InitialCMCTable.read(filename=f"{tmpdirname}/input.fits") + # read the test files and compare to the static unit tests files + pd.testing.assert_frame_equal(Singles, SINGLES_CMC_FITS) + pd.testing.assert_frame_equal(Binaries, BINARIES_CMC_FITS) + Singles, Binaries = InitialCMCTable.read(filename=f"{tmpdirname}/input.hdf5") + pd.testing.assert_frame_equal(Singles, SINGLES_CMC_HDF5) + pd.testing.assert_frame_equal(Binaries, BINARIES_CMC_HDF5)