tower / cascadia / files / src / canon / constants.ts
Branch cascadia · default branch · all branches
constants.ts
| 1 | /** |
| 2 | * Tower canon. See design.md §1. |
| 3 | * |
| 4 | * Per decisions.md D-007, only the values in FREE PARAMETERS are chosen. Everything |
| 5 | * below them is derived, so changing the radius changes the whole world coherently. |
| 6 | * test/canon.test.ts pins every derived figure to the number printed in design.md. |
| 7 | */ |
| 8 | |
| 9 | // ---------------------------------------------------------------- free parameters |
| 10 | export const RADIUS_M = 50_000 |
| 11 | export const LENGTH_M = 540_000 |
| 12 | /** |
| 13 | * Canon default: **none**. The hull is sealed (design.md §1.4, D-017). |
| 14 | * The 0–16 control in src/canon/slats.ts is retained as an exploration tool for |
| 15 | * the author, not because canon is undecided. |
| 16 | */ |
| 17 | export const SLAT_COUNT_DEFAULT = 0 |
| 18 | export const SLAT_COUNT_MIN = 0 |
| 19 | export const SLAT_COUNT_MAX = 16 |
| 20 | /** Wisconsin's land area. Slats are sized to leave exactly this much land (D-002). */ |
| 21 | export const TARGET_LAND_AREA_M2 = 140_268e6 |
| 22 | |
| 23 | // ------------------------------------------------------------------------ physics |
| 24 | export const G0 = 9.80665 |
| 25 | export const SOLAR_CONSTANT_W_M2 = 1361 |
| 26 | /** Speed of light, for radiation pressure. */ |
| 27 | export const C_M_S = 2.998e8 |
| 28 | |
| 29 | // ----------------------------------------------------------------------- geometry |
| 30 | export const CIRCUMFERENCE_M = 2 * Math.PI * RADIUS_M |
| 31 | export const INNER_AREA_M2 = CIRCUMFERENCE_M * LENGTH_M |
| 32 | |
| 33 | // ------------------------------------------------------------- spin (design.md §1.2) |
| 34 | /** Angular velocity giving exactly 1 g at the floor. */ |
| 35 | export const OMEGA_RAD_S = Math.sqrt(G0 / RADIUS_M) |
| 36 | export const SPIN_PERIOD_S = (2 * Math.PI) / OMEGA_RAD_S |
| 37 | export const RIM_SPEED_M_S = OMEGA_RAD_S * RADIUS_M |
| 38 | /** Gravity at radius `s` from the axis. Zero on the axis, 1 g at the floor. */ |
| 39 | export const gravityAtRadius = (s: number): number => OMEGA_RAD_S ** 2 * s |
| 40 | /** Gravity at height `h` above the floor. */ |
| 41 | export const gravityAtHeight = (h: number): number => gravityAtRadius(RADIUS_M - h) |
| 42 | |
| 43 | // ------------------------------------------------------------ slats (design.md §1.4) |
| 44 | /** |
| 45 | * Total slat width is fixed by the land-area target (D-002) and does NOT depend on |
| 46 | * how many slats that width is divided into. So changing the slat count changes |
| 47 | * how wide each one is, and leaves Tower's land area exactly Wisconsin's. |
| 48 | */ |
| 49 | export const SLAT_TOTAL_WIDTH_M = (INNER_AREA_M2 - TARGET_LAND_AREA_M2) / LENGTH_M |
| 50 | /** Land area with at least one slat. With none, the land is the whole surface. */ |
| 51 | export const LAND_AREA_M2 = CIRCUMFERENCE_M * LENGTH_M - SLAT_TOTAL_WIDTH_M * LENGTH_M |
| 52 | |
| 53 | // ------------------------------------------------------- sun system (design.md §1.3) |
| 54 | export const BEAM_CIRCUMFERENCE_M = 10_000 |
| 55 | export const BEAM_RADIUS_M = BEAM_CIRCUMFERENCE_M / (2 * Math.PI) |
| 56 | export const BEAM_AREA_M2 = Math.PI * BEAM_RADIUS_M ** 2 |
| 57 | /** Odeillo-class, and 11% of the étendue limit. See D-003. */ |
| 58 | export const BEAM_CONCENTRATION = 5_000 |
| 59 | export const BEAM_INTENSITY_W_M2 = SOLAR_CONSTANT_W_M2 * BEAM_CONCENTRATION |
| 60 | export const BEAM_POWER_W = BEAM_AREA_M2 * BEAM_INTENSITY_W_M2 |
| 61 | /** Thermodynamic ceiling on passive concentration at 1 AU (D-003). */ |
| 62 | export const ETENDUE_LIMIT = 46_223 |
| 63 | |
| 64 | /** The sun's disc from Tower's orbit — 0.53°, and the reason the eclipse is total. */ |
| 65 | export const SUN_ANGULAR_DIAMETER_RAD = 0.53 * Math.PI / 180 |
| 66 | export const COLLECTOR_EFFICIENCY = 0.85 |
| 67 | export const COLLECTOR_AREA_M2 = BEAM_POWER_W / SOLAR_CONSTANT_W_M2 / COLLECTOR_EFFICIENCY |
| 68 | export const COLLECTOR_DIAMETER_M = 2 * Math.sqrt(COLLECTOR_AREA_M2 / Math.PI) |
| 69 | /** |
| 70 | * How far ahead of the sun cap the collector flies. Not fixed by canon, but it has |
| 71 | * to live here rather than in one view: both 3D views draw the collector now, and |
| 72 | * the interior needs it to decide which part of the sun cap window it covers. |
| 73 | */ |
| 74 | export const COLLECTOR_STANDOFF_M = 320_000 |
| 75 | /** |
| 76 | * The collector is **41.8° across from the sun cap — 79 times the sun's diameter**, |
| 77 | * so it occults the sun completely and Tower sits in its umbra permanently. Nobody |
| 78 | * aboard can see the sun, for the same reason nobody can see Earth (§1.4). From |
| 79 | * inside, the back of it is the only object in the sky that is neither Tower nor a |
| 80 | * star, and it never moves. D-050. |
| 81 | */ |
| 82 | export const COLLECTOR_ANGULAR_DIAMETER_RAD = |
| 83 | 2 * Math.atan(COLLECTOR_DIAMETER_M / 2 / COLLECTOR_STANDOFF_M) |
| 84 | /** |
| 85 | * The sunlit rim. |
| 86 | * |
| 87 | * The collector's face is a mirror pointed away from Tower, so from inside it is a |
| 88 | * black disc — but it is a **backlit** black disc, and its edge is not. The array |
| 89 | * has to hold 46,938 km² flat, and the structure that does it stands proud of the |
| 90 | * mirror plane at the rim, where the sun strikes it side-on. Add the scatter any |
| 91 | * real mirror throws at grazing incidence and the edge reads as a thin sun-coloured |
| 92 | * ring: a crescent of lit structure with nothing behind it. 4 km on a 244 km disc. |
| 93 | * |
| 94 | * Note what it is *not*: sunlight leaking past the edge. Tower sits wholly inside |
| 95 | * the umbra (below), so the sun's disc is hidden from every point in the world. The |
| 96 | * ring is lit structure, not a sliver of star. D-054. |
| 97 | */ |
| 98 | export const COLLECTOR_RIM_M = 4000 |
| 99 | |
| 100 | /** |
| 101 | * Umbra radius at the sun cap. Tower's 51 km sits well inside it, which is what |
| 102 | * makes the eclipse total rather than partial. |
| 103 | */ |
| 104 | export const COLLECTOR_UMBRA_RADIUS_M = |
| 105 | COLLECTOR_DIAMETER_M / 2 - COLLECTOR_STANDOFF_M * (SUN_ANGULAR_DIAMETER_RAD / 2) |
| 106 | |
| 107 | // ---------------------------------------------------- diffuser swarm (design.md §1.3.1) |
| 108 | export const MIRRORLET_EDGE_M = 0.012 |
| 109 | export const MIRRORLET_AREA_M2 = MIRRORLET_EDGE_M ** 2 |
| 110 | export const MIRRORLET_MASS_KG = 2.0e-6 |
| 111 | /** Projected mirror area needed to divert the whole beam, tilted ~45°. */ |
| 112 | export const SWARM_AREA_M2 = BEAM_AREA_M2 * Math.SQRT2 |
| 113 | export const SWARM_COUNT = SWARM_AREA_M2 / MIRRORLET_AREA_M2 |
| 114 | export const SWARM_MASS_KG = SWARM_COUNT * MIRRORLET_MASS_KG |
| 115 | export const SWARM_OPTICAL_DEPTH = (SWARM_COUNT / (BEAM_AREA_M2 * LENGTH_M)) * MIRRORLET_AREA_M2 * LENGTH_M |
| 116 | /** Green-light diffraction limit of one mirrorlet — sets Tower's aiming resolution. */ |
| 117 | export const MIRRORLET_DIFFRACTION_RAD = 550e-9 / MIRRORLET_EDGE_M |
| 118 | export const AIM_SPOT_AT_FLOOR_M = MIRRORLET_DIFFRACTION_RAD * RADIUS_M |
| 119 | |
| 120 | // --------------------------------------------------- illumination (design.md §1.3) |
| 121 | /** Mean insolation settings, W/m² over the whole inner surface. */ |
| 122 | export const BRIGHTNESS_TWILIGHT_W_M2 = 30 |
| 123 | export const BRIGHTNESS_TEMPERATE_W_M2 = 200 |
| 124 | export const BRIGHTNESS_FULL_W_M2 = BEAM_POWER_W / INNER_AREA_M2 |
| 125 | // ------------------------------------------- the far cap mirror (design.md §1.3.2) |
| 126 | /** |
| 127 | * What survives the swarm arrives collimated, in the beam's own cross-section — |
| 128 | * 7.96 km², a thousandth of the far cap's 7,854. So the load is not 13 TW spread |
| 129 | * over a disc; it is **1.7 MW/m² in a 3.2 km spot**, some 1,200 suns, which an |
| 130 | * absorber would sit at 2,330 K to re-radiate. D-048 puts a mirror there instead. |
| 131 | */ |
| 132 | export const BEAM_FAR_CAP_FLUX_W_M2 = |
| 133 | (BEAM_POWER_W * Math.exp(-SWARM_OPTICAL_DEPTH)) / BEAM_AREA_M2 |
| 134 | /** Sized to the beam's 1,592 m with a margin, since the spot is not held perfectly. */ |
| 135 | export const FAR_CAP_MIRROR_RADIUS_M = 2000 |
| 136 | /** |
| 137 | * A mirror is the cheap thermal answer, not the expensive one: at 99.9% it absorbs |
| 138 | * about 1.2 Earth solar constants, which is a warm plate rather than a glowing one. |
| 139 | */ |
| 140 | export const FAR_CAP_MIRROR_REFLECTIVITY = 0.999 |
| 141 | export const FAR_CAP_MIRROR_ABSORBED_W_M2 = |
| 142 | BEAM_FAR_CAP_FLUX_W_M2 * (1 - FAR_CAP_MIRROR_REFLECTIVITY) |
| 143 | /** |
| 144 | * Returning the residual for a second pass makes the optical column 1,080 km |
| 145 | * rather than 540, so utilisation is 1 - e^(-2τ) instead of 1 - e^(-τ): **94%** |
| 146 | * against 76%. What survives even that exits the beam aperture toward the |
| 147 | * collector, which returns it again — so in the limit the whole 54.3 TW lands on |
| 148 | * the inner surface, and BRIGHTNESS_FULL_W_M2 is right as it stands (D-048). |
| 149 | */ |
| 150 | export const BEAM_UTILISATION_ONE_PASS = 1 - Math.exp(-SWARM_OPTICAL_DEPTH) |
| 151 | export const BEAM_UTILISATION_TWO_PASS = 1 - Math.exp(-2 * SWARM_OPTICAL_DEPTH) |
| 152 | |
| 153 | /** |
| 154 | * The beam's own glow, seen from the floor (design.md §1.3). |
| 155 | * |
| 156 | * Radiance is the figure §1.3 states — 26x a clear blue sky — and is taken from |
| 157 | * the doc rather than re-derived here; the derivation needs the Rayleigh phase |
| 158 | * function and the air density at the axis, and a second version of it that |
| 159 | * disagreed by 30% would be worse than none. The angular width IS derived, and |
| 160 | * comes out at the 3.65° §1.3 prints. |
| 161 | */ |
| 162 | export const BEAM_RADIANCE_W_M2_SR = 779 |
| 163 | export const BEAM_ANGULAR_WIDTH_RAD = 2 * Math.atan(BEAM_RADIUS_M / RADIUS_M) |
| 164 | |
| 165 | /** |
| 166 | * Night is made by banking the beam, not by aiming the swarm away — §1.3 says the |
| 167 | * glow belongs to the beam and the air, so a lit beam lights the world whatever |
| 168 | * the diffusers do. A thousandth of full leaves a rod you can still find overhead |
| 169 | * and a world you can just make out under it. D-046. |
| 170 | */ |
| 171 | export const NIGHT_BEAM_FRACTION = 0.001 |
| 172 | export const BRIGHTNESS_NIGHT_W_M2 = BRIGHTNESS_FULL_W_M2 * NIGHT_BEAM_FRACTION |
| 173 | |
| 174 | // ------------------------------------------------ the day cycle (design.md §1.3.4) |
| 175 | /** |
| 176 | * Tower's day. Nothing physical sets it — there is no rotation to inherit one from, |
| 177 | * since the spin is 7.5 minutes and has nothing to do with light. It is chosen for |
| 178 | * the people living under it, so it is Earth's. |
| 179 | */ |
| 180 | export const DAY_LENGTH_S = 86_400 |
| 181 | /** |
| 182 | * How long the light takes to cross the world at dawn, and again at dusk. |
| 183 | * |
| 184 | * The swarm cannot brighten everywhere at once and would not want to: the beam |
| 185 | * enters at the sun cap and the diffusers hand it down the axis, so the natural |
| 186 | * thing — and the only thing that gives a world with no east a direction for its |
| 187 | * mornings — is to bring it up as a front running deepward. 40 minutes over 540 km |
| 188 | * is **225 m/s**, which is a shadow line moving at about the rim speed of Tower |
| 189 | * itself, and slow enough to stand and watch arrive. D-053. |
| 190 | */ |
| 191 | export const DAWN_SWEEP_S = 2400 |
| 192 | export const DAWN_FRONT_SPEED_M_S = LENGTH_M / DAWN_SWEEP_S |
| 193 | /** The lag between the sun cap's morning and the far cap's — Tower's only longitude. */ |
| 194 | export const DAY_SWEEP_FRACTION = DAWN_SWEEP_S / DAY_LENGTH_S |
| 195 | |
| 196 | // --------------------------------------------------------- structure (design.md §1.1) |
| 197 | /** |
| 198 | * Wall depth, floor to outer skin. Canon had no figure for this; 1 km is 2% of the |
| 199 | * radius — enough to read as built from outside and to give the cap windows a |
| 200 | * reveal you can see the depth of, without making Tower a pipe. D-044. |
| 201 | */ |
| 202 | export const HULL_DEPTH_M = 1000 |
| 203 | |
| 204 | // --------------------------------------------------- atmosphere (design.md §1.5) |
| 205 | export const SPECIFIC_GAS_CONSTANT = 287 |
| 206 | export const TEMPERATURE_K = 288 |
| 207 | export const FLOOR_PRESSURE_PA = 101_325 |
| 208 | export const FLOOR_DENSITY_KG_M3 = FLOOR_PRESSURE_PA / (SPECIFIC_GAS_CONSTANT * TEMPERATURE_K) |
| 209 | /** Rayleigh volume scattering coefficient at floor density, 550 nm. */ |
| 210 | export const RAYLEIGH_FLOOR_PER_M = 1.16e-5 |