Skip to content

Commit 5228916

Browse files
sirus20x6claude
andcommitted
feat(types): real carbon planets via per-system carbon-rich (C/O>1) flag
Make the dead tCarbon type reachable with actual physics instead of relabeling composition noise. In a carbon-rich (C/O>1) disk, carbon/carbides condense before silicates so terrestrial bodies are carbon-dominated (Kuchner & Seager 2005; Bond et al. 2010). - carbon_rich_from_seed() (utils.cpp): a PURE splitmix64 hash of the per-system seed -> true with probability CARBON_RICH_SYSTEM_FRACTION (0.05, a conservative high-end estimate of the C/O>1 host fraction; the old ~25% C/O>0.8 figure was an overestimate). Consumes NO RandomContext draw. - sun::carbonRich set once per system at the metallicity site (accrete.cpp), from the seed hash via RandomContext::getSeed() -- so it does not shift the RNG stream: non-carbon-rich systems are byte-identical. - assign_composition (enviro.cpp): carbon-rich systems draw cmf=about(0.75,0.15) (same single draw) instead of ~0.05, crossing the existing cmf>=0.75 tCarbon threshold; cmf feeds the Zeng radius so carbon worlds get realistic radii. Determinism preserved (pure hash + unchanged draw count; -T1==-T8 byte-identical across a run spanning carbon-rich systems). Golden seeds 12345/42/7 do not hash carbon-rich, so goldens are byte-unchanged. Verified reachable: ~5% of systems are carbon-rich and produce "Carbon" / "Tidally Locked Carbon" worlds. 23/23 ctest. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1 parent 517e7b6 commit 5228916

7 files changed

Lines changed: 56 additions & 6 deletions

File tree

accrete.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -899,6 +899,10 @@ auto accrete::dist_planetary_masses(sun &the_sun, long double inner_dust,
899899
GIANT_METALLICITY_MEAN +
900900
GIANT_METALLICITY_SIGMA * sqrt(-2.0L * log(u1)) * cos(2.0L * PI * u2);
901901
the_sun.setMetallicity(feh); // expose the per-star [Fe/H] in output
902+
// Carbon-rich (C/O>1) systems: a deterministic per-system flag hashed from
903+
// the seed (NO RNG draw -> stream unperturbed) that makes rocky bodies
904+
// carbon-dominated (-> tCarbon). See assign_composition() / const.h.
905+
the_sun.setCarbonRich(carbon_rich_from_seed(random_ctx->getSeed()));
902906
long double p_giant = GIANT_FORMATION_NORM * stell_mass_ratio *
903907
std::pow(10.0L, GIANT_FORMATION_FEH_SLOPE * feh);
904908
if (stell_mass_ratio > GIANT_FORMATION_MASS_TURNOVER_MSUN) { // steep drop for A-stars

const.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,18 @@ constexpr double IRON_REFRACTORY_FRACTION = 0.33;
119119
constexpr double ICE_MAX_FRACTION = 0.5;
120120
constexpr double SOLAR_CMF = 0.05;
121121
constexpr double COMPOSITION_SCATTER = 0.15;
122+
/* Carbon planets: a fraction of systems form in carbon-rich (C/O>1) disks where
123+
* carbon/carbides condense before silicates, so rock is carbon-dominated rather
124+
* than silicate (Kuchner & Seager 2005; Bond et al. 2010). CARBON_RICH_SYSTEM_
125+
* FRACTION is the per-system probability -- a deliberately conservative value at
126+
* the high end of the C/O>1 host fraction (Fortney 2012); the once-claimed ~25%
127+
* C/O>0.8 figure was a large overestimate (Nissen 2013; Brewer & Fischer 2016
128+
* find genuine C/O>1 hosts are rare). In a carbon-rich system rocky bodies get
129+
* carbon-of-rock fraction ~ CARBON_RICH_CMF_MEAN (vs solar ~0.05), crossing the
130+
* existing cmf>=0.75 tCarbon threshold. The flag is a pure hash of the system
131+
* seed (no RNG draw), so non-carbon-rich systems are byte-unchanged. */
132+
constexpr double CARBON_RICH_SYSTEM_FRACTION = 0.05;
133+
constexpr double CARBON_RICH_CMF_MEAN = 0.75;
122134
constexpr double T_SILICATE_CONDENSE = 1350.0; /* K; Lodders 2003 forsterite */
123135

124136
/* --- Display-only planet-type MODIFIERS (orthogonal state, not base types) ----

enviro.cpp

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2780,12 +2780,20 @@ void assign_composition(planet *the_planet, sun &the_sun, bool is_moon) {
27802780
}
27812781

27822782
if (the_planet->getCmf() == 0) {
2783-
long double cmf = about(SOLAR_CMF, COMPOSITION_SCATTER); // carbon-of-rock, small/solar
2783+
// In a carbon-rich (C/O>1) system carbon/carbides condense before silicates,
2784+
// so rock is carbon-dominated -> high cmf -> the body classifies as tCarbon.
2785+
// Same single about() draw either way, so the RNG stream is unperturbed; only
2786+
// the value and clamp differ for carbon-rich systems.
2787+
const bool carbon_rich = the_sun.getCarbonRich();
2788+
long double cmf = carbon_rich
2789+
? about(CARBON_RICH_CMF_MEAN, COMPOSITION_SCATTER)
2790+
: about(SOLAR_CMF, COMPOSITION_SCATTER);
27842791
if (cmf < 0.0) {
27852792
cmf = 0.0;
27862793
}
2787-
if (cmf > 0.2) {
2788-
cmf = 0.2;
2794+
const long double cmf_cap = carbon_rich ? 1.0 : 0.2;
2795+
if (cmf > cmf_cap) {
2796+
cmf = cmf_cap;
27892797
}
27902798
the_planet->setCmf(cmf);
27912799
}

structs.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -882,6 +882,9 @@ void sun::setAge(long double a) { age = a; }
882882
void sun::setMetallicity(long double m) { metallicity = m; }
883883
auto sun::getMetallicity() -> long double { return metallicity; }
884884

885+
void sun::setCarbonRich(bool b) { carbonRich = b; }
886+
auto sun::getCarbonRich() -> bool { return carbonRich; }
887+
885888
void sun::setEffTemp(long double e) {
886889
effTemp = e;
887890
if (specType.empty()) {

structs.h

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,9 @@ using planet_type = enum planet_type {
3030
// positional type_counts[]/weighted-count table in stargen.cpp.
3131
tBrownDwarf, // seb
3232
tIron,
33-
tCarbon, // carbon-dominated rock (Kuchner & Seager 2005). Currently only
34-
// reachable in carbon-rich (C/O>1) systems, which StarGen does not
35-
// yet model -- see the carbon-rich-system note in assign_type.
33+
tCarbon, // carbon-dominated rock (Kuchner & Seager 2005). Reached in carbon-
34+
// rich (C/O>1) systems: sun::carbonRich (a per-system seed hash, set
35+
// in accrete.cpp) boosts cmf>=0.75 in assign_composition.
3636
tOil // DEPRECATED: a non-physical "oil ocean" (originally Star-Trek-
3737
// flavored); never assigned. Kept vestigial to preserve ordinals.
3838
};
@@ -64,6 +64,7 @@ class sun {
6464
std::string specType{""};
6565
long double age{0};
6666
long double metallicity{0}; // [Fe/H] in dex (0 = solar); drives giant formation
67+
bool carbonRich{false}; // C/O>1 disk -> carbon-dominated rock (tCarbon planets)
6768
std::string name{""};
6869
bool isCircumbinary{false};
6970
long double secondaryMass{0};
@@ -91,6 +92,8 @@ class sun {
9192
auto getAge() -> long double;
9293
void setMetallicity(long double);
9394
auto getMetallicity() -> long double;
95+
void setCarbonRich(bool);
96+
auto getCarbonRich() -> bool;
9497
void setName(std::string);
9598
auto getName() -> std::string;
9699
auto getREcosphere(long double) -> long double;

utils.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include <cctype> // for toupper, isspace
77
#include <cmath> // for log, exp, pow, NAN, sqrt, fmod, abs
88
#include <cstdlib> // for rand, abs, RAND_MAX
9+
#include <cstdint> // for std::uint64_t (carbon_rich_from_seed)
910
#include <string> // for std::string, basic_string, operator<<
1011
#include "const.h" // for pow2, pow1_4, pow3, pow4
1112
#include "enviro.h" // for eff_temp_to_spec_type, getStarType
@@ -121,6 +122,21 @@ auto about(long double value, long double variation) -> long double {
121122
return (value + (value * random_number(-variation, variation)));
122123
}
123124

125+
/// @brief Deterministic per-system carbon-rich (C/O>1) flag from the system seed.
126+
/// Pure splitmix64 hash -> uniform [0,1) compared to CARBON_RICH_SYSTEM_FRACTION.
127+
/// Consumes NO RandomContext draw, so it does not shift the per-system RNG stream
128+
/// (only carbon-rich systems' composition changes); integer-only hash keeps it
129+
/// byte-identical across compilers/threads.
130+
auto carbon_rich_from_seed(long sys_seed) -> bool {
131+
std::uint64_t z = static_cast<std::uint64_t>(sys_seed) + 0x9E3779B97F4A7C15ULL;
132+
z = (z ^ (z >> 30)) * 0xBF58476D1CE4E5B9ULL;
133+
z = (z ^ (z >> 27)) * 0x94D049BB133111EBULL;
134+
z = z ^ (z >> 31);
135+
// Top 53 bits -> double in [0,1).
136+
const double u = static_cast<double>(z >> 11) * (1.0 / 9007199254740992.0);
137+
return u < CARBON_RICH_SYSTEM_FRACTION;
138+
}
139+
124140
/// @brief
125141
/// @param ecc_coef
126142
/// @return

utils.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,10 @@ auto escapeCelestiaId(const std::string&) -> std::string;
4242
auto random_number(long double, long double) -> long double;
4343
auto random_number_int(int min, int max) -> int;
4444
auto about(long double, long double) -> long double;
45+
// Deterministic per-system "carbon-rich" (C/O>1) flag from the system seed via a
46+
// splitmix64 hash. PURE -- consumes NO RandomContext draw, so it does not shift
47+
// the per-system RNG stream. True with probability CARBON_RICH_SYSTEM_FRACTION.
48+
auto carbon_rich_from_seed(long sys_seed) -> bool;
4549
auto random_eccentricity(long double) -> long double;
4650
auto gaussian(long double) -> long double;
4751
auto poisson(long double) -> long;

0 commit comments

Comments
 (0)