API reference
The public entry point is morrigan.run_system, documented first below. The modules after it are the model's internals, documented for contributors and for readers tracing an equation from the model overview into code.
Public API
morrigan
morrigan
Semi-analytical model for the dynamical evolution of planetary systems via giant impacts, following Kimura et al. (2025). Author(s): Anna Grace Ulses
Driver
driver
driver.py
Runs a dynamical evolution model for [ndisk] systems with [N] planets each and saves data in .csv files Author(s): Anna Grace Ulses
cli()
Read the settings-file path from the command line, then run
Kept separate from main() so that importing Morrigan and calling main() from another program never inspects that program's own command line.
Source code in src/morrigan/driver.py
671 672 673 674 675 676 677 678 679 680 681 682 683 | |
main(config_path)
Run every system described by a settings file
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
config_path
|
str
|
Path to the .toml settings file |
required |
Notes
A batch of more than one system runs on a process pool. Python starts
those workers by re-importing the module that launched them, so a
caller that reaches this function from an unguarded top level would
have each worker launch the batch again. Put the call behind
if __name__ == '__main__':; a batch that cannot start a pool runs
its systems one after another instead, which gives the same numbers
because each system seeds itself from its own index.
Source code in src/morrigan/driver.py
589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 | |
read_config(config_path=DEFAULT_CONFIG)
Read a settings file
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
config_path
|
str
|
Path to the .toml settings file |
DEFAULT_CONFIG
|
Returns:
| Name | Type | Description |
|---|---|---|
config |
dict
|
Parsed settings |
Raises:
| Type | Description |
|---|---|
FileNotFoundError
|
If no settings file is at the given path. The default is a bare file name, so it only resolves when the command runs from a checkout root; the message names the path that was tried. |
Source code in src/morrigan/driver.py
31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 | |
run_system(seed, masses, eccentricity, inner_edge, spacing, density, impact_angle, evolution_time, inner_cutoff, stellar_mass)
Evolve one system and return its survivors and impact history in memory.
This is the entry point an in-process caller uses instead of the file-writing command line. Inputs are SI apart from the stellar mass, in solar masses, and the evolution time, in Gyr; masses are in kg and lengths in metres. The returned quantities are SI with times in years.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
seed
|
int
|
Seed for this system's random draws. |
required |
masses
|
sequence of float
|
Initial embryo masses [kg]. |
required |
eccentricity
|
float
|
Initial eccentricity shared by the embryos. |
required |
inner_edge
|
float
|
Orbit of the innermost embryo [m]. |
required |
spacing
|
float
|
Spacing between adjacent embryos [mutual Hill radii]. |
required |
density
|
float
|
Bulk density shared by the embryos [kg m-3]. |
required |
impact_angle
|
float
|
Impact angle [deg]; its sine is the impact parameter. |
required |
evolution_time
|
float
|
Length of the dynamical evolution [Gyr]. |
required |
inner_cutoff
|
float
|
Orbit inside which a body is taken to have fallen into the star [m]. |
required |
stellar_mass
|
float
|
Host stellar mass [Msun]. |
required |
Returns:
| Type | Description |
|---|---|
dict
|
|
Source code in src/morrigan/driver.py
446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 | |
system_seed(base_seed, run_idx)
Return the seed for one system of a batch.
Mixes the settings-file seed with the run index rather than adding them. Adding makes neighbouring ensembles overlap: run k of seed s draws the same stream as run k-1 of seed s+1, so two ensembles one apart share all but one of their systems, and any scatter measured across seeds comes out far too small. Mixing decorrelates them while keeping each system exactly reproducible from its settings file, which is the property that matters for rerunning a result.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
base_seed
|
int
|
Seed from the settings file, shared by the whole batch. |
required |
run_idx
|
int
|
Index of this system within the batch. |
required |
Returns:
| Type | Description |
|---|---|
int
|
Seed for this system, in numpy's valid seed range. |
Source code in src/morrigan/driver.py
103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 | |
Crossing-pair scheduler
crossing_pair
crossing_pair.py
Function to identify a crossing pair from an interacting triplet of planets on eccentric orbits and calculate when the pair will cross and trigger an event Author(s): Anna Grace Ulses
crossing_pair(ap, Mp, Rp, Ms, ecc, ecc_vec, g, beta, interact, N, t, t_ref)
Identify interacting pair of planets and calculate when their orbits will cross
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
ap
|
list
|
Semi major axes of all planets in system [m] |
required |
Mp
|
list
|
Masses of all planets in system [kg] |
required |
Rp
|
list
|
Radii of all planets in system [m] |
required |
ecc
|
list
|
Eccentriticies of all planets |
required |
ecc_vec
|
array
|
Eccentricity vector components per planet |
required |
g
|
array
|
Secular eigenfrequency |
required |
beta
|
array
|
Phase angle |
required |
interact
|
boolean list
|
Flags for which planets are live and interacting |
required |
N
|
int
|
Number of planets |
required |
t
|
float
|
Time in simulation [s] |
required |
t_ref
|
float
|
|
required |
Returns:
| Name | Type | Description |
|---|---|---|
icross |
int
|
Index of the inner planet in the crossing pair |
t_event |
float
|
Time of next crossing event |
Source code in src/morrigan/crossing_pair.py
13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 | |
Interaction timescales
interaction_timescales
interaction_timescales.py
Functions to calculate crossing timescale, viscous interaction, and collision timescale Author(s): Anna Grace Ulses
interaction_wrapper(ap, Mp, Ms, ecc, N_affect)
Function to determine if triplet is stable, and if not, calculate timescale of instability
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
ap
|
list
|
Semi-major axes of triplet [m] |
required |
Mp
|
list
|
Masses of triplet [kg] |
required |
Ms
|
float
|
Stellar mass [kg] |
required |
ecc
|
list
|
Eccentricities of triplet |
required |
N_affect
|
int
|
Number of planets interacting |
required |
Returns:
| Type | Description |
|---|---|
float
|
1e20 if the system is stable, otherwise the instability timescale
from |
Source code in src/morrigan/interaction_timescales.py
75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 | |
tau_col(ap, Mp, Rp, Ms, ecc)
Function to calculate duration of a collision event
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
ap
|
list
|
Semi-major axes of interacting pair [m] |
required |
Mp
|
list
|
Masses of interacting pair [kg] |
required |
Rp
|
list
|
Radii of interacting pair [m] |
required |
Ms
|
float
|
Stellar mass [kg] |
required |
ecc
|
list
|
Eccentricities of interacting pair |
required |
Returns:
| Name | Type | Description |
|---|---|---|
timescale |
float
|
Duration of collisional event [s] |
Source code in src/morrigan/interaction_timescales.py
165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 | |
tau_cross_petit(a, Mp, Ms, ecc, N_affect)
Function to calculate timescale to instability as a result of 3-body mean motion resonances
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
a
|
list
|
Semi-major axes of planetary triplet [m] |
required |
Mp
|
list
|
Masses of planetary triplet [kg] |
required |
Ms
|
float
|
Stellar mass [kg] |
required |
ecc
|
list
|
Eccentricities of planetary triplet |
required |
N_affect
|
int
|
Number of planets interacting |
required |
Returns:
| Name | Type | Description |
|---|---|---|
tau_cross |
float
|
Instability timescale for planetary triplet [s] |
Source code in src/morrigan/interaction_timescales.py
13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 | |
tau_vis(ap, Mp, Rp, Ms, ecc)
Viscous relaxation timescale for an interacting planetary pair
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
ap
|
list
|
Semi-major axes of interacting pair [m] |
required |
Mp
|
list
|
Masses of interacting pair [kg] |
required |
Rp
|
list
|
Radii of interacting pair [m] |
required |
Ms
|
float
|
Stellar mass [kg] |
required |
ecc
|
list
|
Eccentricities of interacting pair |
required |
Returns:
| Name | Type | Description |
|---|---|---|
timescale |
float
|
Viscous relaxation timescale (when system settles down after scattering) |
Source code in src/morrigan/interaction_timescales.py
119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 | |
Secular solution
secular_solution
secular_solution.py
Solves secular perturbation theory to evolve eccentricity of planets in system Author(s): Anna Grace Ulses
secular_solution(ap, Mp, ecc, Rp, Ms, N)
Solution to secular perturbation theory of orbital mechanics. Only recalculates after an event
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
ap
|
list
|
Semi-major axes of all planets in system [m] |
required |
Mp
|
list
|
Masses of all planets in system [kg] |
required |
ecc
|
list
|
Eccentricities of all planets in system |
required |
Rp
|
list
|
Radii of all planets in system [m] |
required |
Ms
|
float
|
Stellar mass [kg] |
required |
N
|
int
|
Number of planets |
required |
Returns:
| Name | Type | Description |
|---|---|---|
ecc_vec |
array
|
Scaled eigenvectors - columns represent eccentricity contribution from each mode per planet |
g |
array
|
Secular eigenfrequencies |
beta |
array
|
Phase angle for each planet in system |
Source code in src/morrigan/secular_solution.py
13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 | |
Crossing outcomes
orbit_cross_K25
orbit_cross_K25.py
Function that modifies arrays of orbital separation, mass, radius, eccentricity, interaction status, and live status of planets based on whether a collision or scattering (or ejection) event happens Author(s): Anna Grace Ulses
orbit_cross_K25(ap, Mp, Rp, Ms, impact_parameter, ecc, interact, live_status, N, planet_id, icross)
Function to determine what happens once an orbit crossing event has been established
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
ap
|
list
|
Semi major axes of interacting pair [m] |
required |
Mp
|
list
|
Masses of interacting pair [kg] |
required |
Rp
|
list
|
Radii of interacting pair [m] |
required |
Ms
|
float
|
Stellar mass [kg] |
required |
impact_parameter
|
Defined as sin(impact angle). Describes angle of contact between target and impactor |
required | |
ecc
|
list
|
Eccentricities of interacing pair |
required |
interact
|
bool
|
Interaction status of interacting pair (set to True) |
required |
live_status
|
bool
|
Live status of interacting pair (starts as True and will be modified depending on scattering vs. merge events) |
required |
N
|
int
|
Number of planets |
required |
planet_id
|
list
|
Persistent ID number for interacting planets to track evolutions |
required |
icross
|
Index of inner planet in interacting pair |
required |
Returns:
| Name | Type | Description |
|---|---|---|
Modified arrays for ap, Mp, Rp, ecc, interact, live_status, N following scattering or merging
|
|
|
merge_record |
dict
|
Stores information about targets and impactors for each merging event |
Source code in src/morrigan/orbit_cross_K25.py
14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 | |
Merger bookkeeping
merge_embryo
merge_embryo.py
Handles merging events. collision_velocity: calculates collision velocity between target and impactor merge_embryo: Computes resulting mass, orbital separation, and eccentricity Author(s): Anna Grace Ulses
collision_velocity(ap, Mp, Rp, Ms, ecc)
Velocity of collision between target and impactor during merge events
Parameters: ap : list Semi-major axes of interacting pair [m] Mp : list Masses of interacting pair [kg] Rp : list Radii of interacting pair [m] Ms : float Stellar mass [kg] ecc : list Eccentricities of interacting pair
Returns:
| Name | Type | Description |
|---|---|---|
v_c |
float
|
Collision velocity between target and impactor during merging [m/s] |
Source code in src/morrigan/merge_embryo.py
14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | |
merge_embryo(ap, Mp, Rp, Ms, ecc, v_c, live_status, b)
Function to compute mass, orbital separation, and eccentricity after a giant impact
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
ap
|
list
|
Semi major axes of colliding pair [m] |
required |
Mp
|
list
|
Masses of colliding pair [kg] |
required |
Rp
|
list
|
Radii of colliding pair [m] |
required |
ecc
|
list
|
Secular eccentricity of colliding pair just before collision |
required |
v_c
|
float
|
Collision velocity [m/s] |
required |
live_status
|
list
|
Live_status of colliding pair |
required |
b
|
float
|
Impact parameter, defined as sin(beta) where beta is impact angle in [deg] |
required |
Returns:
| Name | Type | Description |
|---|---|---|
ap |
float
|
Updated semi-major axis of surviving planet [m] |
Mp |
float
|
Updated mass of surviving planet [kg] |
ecc |
float
|
Updated eccentricity of surviving planet |
live_status |
list
|
Sets consumed planet's status to 'False' |
Source code in src/morrigan/merge_embryo.py
44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 | |
Helper functions
helper_functions
helper_functions.py
Ancillary functions used periodically throughout 'Morrigan' code Author(s): Anna Grace Ulses
Cleanup sort
sort_planet
sort_planet.py
Function to clean up planetary systems and sort by semi-major axis after every event Author(s): Anna Grace Ulses
sort_planet(ap, Mp, ecc, Rp, live_status, interact, densities, planet_id)
Removes dead planets and sorts system by increasing semi-major axis
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
ap
|
list
|
Semi-major axes of all planets [m] |
required |
Mp
|
list
|
Masses of all planets [m] |
required |
ecc
|
list
|
Eccentricities of all planets |
required |
Rp
|
list
|
Radii of all planets [m] |
required |
live_status
|
Whether a planet is surviving (True), or was ejected or consumed (False) |
required | |
interact
|
Indices of interacting planets at this timestep |
required | |
densities
|
Densities of all planets [kg/m^3] |
required | |
planet_id
|
Persistent planet ID to track evolutions |
required |
Returns:
| Type | Description |
|---|---|
Sorted arrays for ap, Mp, ecc, Rp, live_status, interact, densities, and planet_id
|
|
Source code in src/morrigan/sort_planet.py
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 | |
Constants
constants
constants.py
Physical constants and unit conversions. Author(s): Anna Grace Ulses