""" Moon Colony Construction - Rocket Launch Scenario Analysis Problem: Deliver 100 million metric tons to Moon using traditional rockets - 10 launch sites, each max 1 launch per day - Rocket payload: 100-150 metric tons (use 125 tons average) - Optimize launch distribution to minimize energy consumption - Plot completion year vs total energy consumption Key insight: As completion timeline extends, more launches can be allocated to low-latitude sites, reducing the latitude-induced energy penalty. """ import numpy as np import matplotlib matplotlib.use('Agg') import matplotlib.pyplot as plt from matplotlib import rcParams from dataclasses import dataclass from typing import List, Tuple import pandas as pd # 设置字体 rcParams['font.sans-serif'] = ['Arial Unicode MS', 'DejaVu Sans', 'SimHei'] rcParams['axes.unicode_minus'] = False # ============== 物理常数 ============== G0 = 9.81 # m/s² OMEGA_EARTH = 7.27e-5 # rad/s R_EARTH = 6.371e6 # m # ============== 任务参数 ============== TOTAL_PAYLOAD = 100e6 # 100 million metric tons = 100e9 kg 的物资,但单位是metric tons PAYLOAD_PER_LAUNCH = 125 # metric tons per launch (average of 100-150) TOTAL_LAUNCHES_NEEDED = TOTAL_PAYLOAD / PAYLOAD_PER_LAUNCH # 800,000 launches # 火箭参数 ISP = 363 # 比冲 (秒) - 液氧甲烷 (LOX/CH4, Raptor-class) SPECIFIC_FUEL_ENERGY = 11.9e6 # J/kg 燃料比能量 ALPHA = 0.10 # 结构系数 NUM_STAGES = 3 # 3级火箭 # 地面发射基准 ΔV (赤道发射到月球轨道) DELTA_V_BASE = 13300 # m/s (LEO + TLI + LOI) # ============== 发射场定义 ============== @dataclass class LaunchSite: name: str short_name: str latitude: float # degrees max_launches_per_day: int = 1 @property def abs_latitude(self) -> float: return abs(self.latitude) @property def rotation_velocity(self) -> float: """地球自转速度 (m/s)""" return OMEGA_EARTH * R_EARTH * np.cos(np.radians(self.abs_latitude)) @property def delta_v_loss(self) -> float: """相对赤道的ΔV损失 (m/s)""" v_equator = OMEGA_EARTH * R_EARTH # ~465 m/s return v_equator - self.rotation_velocity @property def total_delta_v(self) -> float: """总ΔV需求 (m/s)""" return DELTA_V_BASE + self.delta_v_loss # 10个发射场 (按纬度排序) LAUNCH_SITES = [ LaunchSite("Kourou (French Guiana)", "Kourou", 5.2), LaunchSite("Satish Dhawan (India)", "SDSC", 13.7), LaunchSite("Boca Chica (Texas)", "Texas", 26.0), LaunchSite("Cape Canaveral (Florida)", "Florida", 28.5), LaunchSite("Vandenberg (California)", "California", 34.7), LaunchSite("Wallops (Virginia)", "Virginia", 37.8), LaunchSite("Taiyuan (China)", "Taiyuan", 38.8), LaunchSite("Mahia (New Zealand)", "Mahia", 39.3), LaunchSite("Baikonur (Kazakhstan)", "Baikonur", 45.6), LaunchSite("Kodiak (Alaska)", "Alaska", 57.4), ] # 按纬度排序 LAUNCH_SITES = sorted(LAUNCH_SITES, key=lambda x: x.abs_latitude) # ============== 核心计算函数 ============== def fuel_ratio_multistage(delta_v: float, isp: float = ISP, alpha: float = ALPHA, num_stages: int = NUM_STAGES) -> float: """ 多级火箭燃料/载荷比 """ ve = isp * G0 delta_v_per_stage = delta_v / num_stages R_stage = np.exp(delta_v_per_stage / ve) denominator = 1 - alpha * (R_stage - 1) if denominator <= 0: return np.inf k_stage = (R_stage - 1) / denominator # 多级计算 total_fuel_ratio = 0 remaining_ratio = 1.0 for _ in range(num_stages): fuel_this_stage = remaining_ratio * k_stage total_fuel_ratio += fuel_this_stage remaining_ratio *= (1 + k_stage * (1 + alpha)) return total_fuel_ratio def energy_per_launch(site: LaunchSite, payload_tons: float = PAYLOAD_PER_LAUNCH) -> float: """ 计算单次发射的能量消耗 (Joules) 参数: site: 发射场 payload_tons: 载荷 (metric tons) 返回: 能量消耗 (J) """ delta_v = site.total_delta_v k = fuel_ratio_multistage(delta_v) payload_kg = payload_tons * 1000 # convert to kg fuel_kg = k * payload_kg energy = fuel_kg * SPECIFIC_FUEL_ENERGY return energy def fuel_per_launch(site: LaunchSite, payload_tons: float = PAYLOAD_PER_LAUNCH) -> float: """ 计算单次发射的燃料消耗 (metric tons) """ delta_v = site.total_delta_v k = fuel_ratio_multistage(delta_v) return k * payload_tons # ============== 发射排布优化 ============== def calculate_launch_distribution( total_launches: int, completion_years: float, sites: List[LaunchSite] = LAUNCH_SITES ) -> List[Tuple[LaunchSite, int]]: """ 计算给定完成年限下的发射分配 策略:优先使用低纬度发射场,直到达到其最大容量 参数: total_launches: 总发射次数 completion_years: 完成年限 sites: 发射场列表 (已按纬度排序) 返回: [(发射场, 分配的发射次数), ...] """ days_available = completion_years * 365 max_launches_per_site = days_available # 每站每天最多1发 distribution = [] remaining_launches = total_launches # 按纬度从低到高分配 for site in sites: if remaining_launches <= 0: distribution.append((site, 0)) else: allocated = min(remaining_launches, max_launches_per_site) distribution.append((site, int(allocated))) remaining_launches -= allocated return distribution def calculate_total_energy(distribution: List[Tuple[LaunchSite, int]]) -> dict: """ 计算发射分配的总能量消耗 返回: 包含各项统计的字典 """ total_energy = 0 total_fuel = 0 total_launches = 0 site_details = [] for site, num_launches in distribution: if num_launches > 0: energy = energy_per_launch(site) * num_launches fuel = fuel_per_launch(site) * num_launches total_energy += energy total_fuel += fuel total_launches += num_launches site_details.append({ 'site': site.name, 'short_name': site.short_name, 'latitude': site.abs_latitude, 'launches': num_launches, 'energy_PJ': energy / 1e15, # PetaJoules 'fuel_Mt': fuel / 1e6, # Million metric tons }) return { 'total_energy_PJ': total_energy / 1e15, 'total_fuel_Mt': total_fuel / 1e6, 'total_launches': total_launches, 'sites': site_details } def analyze_completion_timeline( years_range: np.ndarray, total_payload: float = TOTAL_PAYLOAD, payload_per_launch: float = PAYLOAD_PER_LAUNCH ) -> pd.DataFrame: """ 分析不同完成年限下的能量消耗 返回: DataFrame with analysis results """ total_launches = int(total_payload / payload_per_launch) results = [] for years in years_range: distribution = calculate_launch_distribution(total_launches, years) stats = calculate_total_energy(distribution) # 计算使用了多少个发射场 sites_used = sum(1 for _, n in distribution if n > 0) # 计算低纬度发射场的比例 low_lat_launches = sum(n for site, n in distribution if site.abs_latitude < 30) low_lat_ratio = low_lat_launches / total_launches if total_launches > 0 else 0 results.append({ 'years': years, 'total_launches': total_launches, 'sites_used': sites_used, 'total_energy_PJ': stats['total_energy_PJ'], 'total_fuel_Mt': stats['total_fuel_Mt'], 'low_lat_ratio': low_lat_ratio, 'energy_per_launch_TJ': stats['total_energy_PJ'] * 1000 / total_launches, }) return pd.DataFrame(results) # ============== 可视化 ============== def plot_timeline_analysis( save_path: str = '/Volumes/Files/code/mm/20260130_b/rocket_launch_timeline.png' ): """ 绘制完成年份-能量消耗关系图 """ # 计算最短完成时间 total_launches = int(TOTAL_PAYLOAD / PAYLOAD_PER_LAUNCH) num_sites = len(LAUNCH_SITES) min_years = total_launches / (num_sites * 365) print(f"Total payload: {TOTAL_PAYLOAD/1e6:.0f} million metric tons") print(f"Payload per launch: {PAYLOAD_PER_LAUNCH} metric tons") print(f"Total launches needed: {total_launches:,}") print(f"Number of launch sites: {num_sites}") print(f"Minimum completion time: {min_years:.1f} years") # 分析范围:从最短时间到5倍最短时间 years_range = np.linspace(min_years, min_years * 5, 100) # 运行分析 df = analyze_completion_timeline(years_range) # 创建图表 fig, axes = plt.subplots(2, 2, figsize=(16, 14)) # ========== 图1: 完成年份 vs 总能量消耗 ========== ax1 = axes[0, 0] ax1.plot(df['years'], df['total_energy_PJ'], 'b-', linewidth=2) ax1.fill_between(df['years'], df['total_energy_PJ'], alpha=0.3) # 标记关键点 min_idx = df['total_energy_PJ'].idxmin() ax1.axvline(x=df.loc[min_idx, 'years'], color='r', linestyle='--', label=f'Optimal: {df.loc[min_idx, "years"]:.1f} years') ax1.axhline(y=df.loc[min_idx, 'total_energy_PJ'], color='r', linestyle=':', alpha=0.5) # 标记最短时间点 ax1.axvline(x=min_years, color='g', linestyle='--', label=f'Minimum time: {min_years:.1f} years') ax1.set_xlabel('Completion Time (years)', fontsize=12) ax1.set_ylabel('Total Energy Consumption (PJ)', fontsize=12) ax1.set_title('Completion Timeline vs Total Energy\n(100 Million Metric Tons to Moon)', fontsize=14) ax1.legend() ax1.grid(True, alpha=0.3) # ========== 图2: 使用的发射场数量 ========== ax2 = axes[0, 1] ax2.plot(df['years'], df['sites_used'], 'g-', linewidth=2, marker='o', markevery=10, markersize=6) ax2.set_xlabel('Completion Time (years)', fontsize=12) ax2.set_ylabel('Number of Launch Sites Used', fontsize=12) ax2.set_title('Launch Sites Required vs Timeline', fontsize=14) ax2.set_ylim(0, 11) ax2.grid(True, alpha=0.3) # 添加发射场名称标注 for i, site in enumerate(LAUNCH_SITES): ax2.axhline(y=i+1, color='gray', linestyle=':', alpha=0.3) ax2.text(df['years'].max() * 0.98, i+1 + 0.1, site.short_name, fontsize=8, ha='right', va='bottom') # ========== 图3: 低纬度发射比例 ========== ax3 = axes[1, 0] ax3.plot(df['years'], df['low_lat_ratio'] * 100, 'm-', linewidth=2) ax3.fill_between(df['years'], df['low_lat_ratio'] * 100, alpha=0.3, color='magenta') ax3.set_xlabel('Completion Time (years)', fontsize=12) ax3.set_ylabel('Low Latitude (<30°) Launch Ratio (%)', fontsize=12) ax3.set_title('Proportion of Launches from Low-Latitude Sites', fontsize=14) ax3.set_ylim(0, 105) ax3.grid(True, alpha=0.3) # ========== 图4: 平均每发能量 ========== ax4 = axes[1, 1] ax4.plot(df['years'], df['energy_per_launch_TJ'], 'r-', linewidth=2) # 计算赤道和最高纬度的能量参考线 energy_equator = energy_per_launch(LAUNCH_SITES[0]) / 1e12 # TJ energy_max_lat = energy_per_launch(LAUNCH_SITES[-1]) / 1e12 # TJ ax4.axhline(y=energy_equator, color='g', linestyle='--', label=f'Equator baseline: {energy_equator:.1f} TJ') ax4.axhline(y=energy_max_lat, color='orange', linestyle='--', label=f'Alaska (57°): {energy_max_lat:.1f} TJ') ax4.set_xlabel('Completion Time (years)', fontsize=12) ax4.set_ylabel('Average Energy per Launch (TJ)', fontsize=12) ax4.set_title('Energy Efficiency vs Timeline\n(Longer timeline → more low-lat launches)', fontsize=14) ax4.legend() ax4.grid(True, alpha=0.3) plt.tight_layout() plt.savefig(save_path, dpi=150, bbox_inches='tight') print(f"\n图表已保存至: {save_path}") return df, fig def plot_launch_distribution( years: float, save_path: str = '/Volumes/Files/code/mm/20260130_b/launch_distribution.png' ): """ 绘制特定年限下的发射分配详情 """ total_launches = int(TOTAL_PAYLOAD / PAYLOAD_PER_LAUNCH) distribution = calculate_launch_distribution(total_launches, years) stats = calculate_total_energy(distribution) fig, axes = plt.subplots(1, 2, figsize=(14, 6)) # ========== 图1: 发射次数分配 ========== ax1 = axes[0] sites = [s.short_name for s, _ in distribution] launches = [n for _, n in distribution] latitudes = [s.abs_latitude for s, _ in distribution] colors = plt.cm.RdYlGn_r(np.array(latitudes) / 60) bars = ax1.barh(sites, launches, color=colors) ax1.set_xlabel('Number of Launches', fontsize=12) ax1.set_ylabel('Launch Site', fontsize=12) ax1.set_title(f'Launch Distribution ({years:.1f} years completion)\n' f'Total: {total_launches:,} launches', fontsize=13) ax1.grid(True, alpha=0.3, axis='x') # 添加数值标签 for bar, n in zip(bars, launches): if n > 0: ax1.text(bar.get_width() + 1000, bar.get_y() + bar.get_height()/2, f'{n:,}', va='center', fontsize=9) # ========== 图2: 能量消耗分配 ========== ax2 = axes[1] site_names = [d['short_name'] for d in stats['sites']] energies = [d['energy_PJ'] for d in stats['sites']] colors = plt.cm.RdYlGn_r(np.array([d['latitude'] for d in stats['sites']]) / 60) bars = ax2.barh(site_names, energies, color=colors) ax2.set_xlabel('Energy Consumption (PJ)', fontsize=12) ax2.set_ylabel('Launch Site', fontsize=12) ax2.set_title(f'Energy Distribution\n' f'Total: {stats["total_energy_PJ"]:.1f} PJ', fontsize=13) ax2.grid(True, alpha=0.3, axis='x') # 添加数值标签 for bar, e in zip(bars, energies): if e > 0: ax2.text(bar.get_width() + 0.5, bar.get_y() + bar.get_height()/2, f'{e:.1f}', va='center', fontsize=9) plt.tight_layout() plt.savefig(save_path, dpi=150, bbox_inches='tight') print(f"分配详情图已保存至: {save_path}") return distribution, stats def print_analysis_summary(df: pd.DataFrame): """打印分析摘要""" print("\n" + "=" * 80) print("ROCKET LAUNCH SCENARIO ANALYSIS SUMMARY") print("=" * 80) total_launches = int(TOTAL_PAYLOAD / PAYLOAD_PER_LAUNCH) print(f"\nMission Parameters:") print(f" - Total payload: {TOTAL_PAYLOAD/1e6:.0f} million metric tons") print(f" - Payload per launch: {PAYLOAD_PER_LAUNCH} metric tons") print(f" - Total launches required: {total_launches:,}") print(f" - Number of launch sites: {len(LAUNCH_SITES)}") # 最短时间场景 min_years = df['years'].min() min_time_row = df[df['years'] == min_years].iloc[0] print(f"\nMinimum Time Scenario ({min_years:.1f} years):") print(f" - All {int(min_time_row['sites_used'])} sites at full capacity") print(f" - Total energy: {min_time_row['total_energy_PJ']:.1f} PJ") print(f" - Total fuel: {min_time_row['total_fuel_Mt']:.1f} million metric tons") print(f" - Low-latitude ratio: {min_time_row['low_lat_ratio']*100:.1f}%") # 最优能量场景 (只使用最低纬度站点) max_years = df['years'].max() max_time_row = df[df['years'] == max_years].iloc[0] print(f"\nExtended Timeline Scenario ({max_years:.1f} years):") print(f" - Using {int(max_time_row['sites_used'])} lowest-latitude sites") print(f" - Total energy: {max_time_row['total_energy_PJ']:.1f} PJ") print(f" - Total fuel: {max_time_row['total_fuel_Mt']:.1f} million metric tons") print(f" - Low-latitude ratio: {max_time_row['low_lat_ratio']*100:.1f}%") # 能量节省 energy_saving = (1 - max_time_row['total_energy_PJ'] / min_time_row['total_energy_PJ']) * 100 print(f"\nEnergy Savings (Extended vs Minimum time):") print(f" - Energy reduction: {energy_saving:.1f}%") print(f" - Time trade-off: {max_years - min_years:.1f} additional years") print("\n" + "=" * 80) print("Launch Site Details:") print("=" * 80) print(f"\n{'Site':<25} {'Latitude':>10} {'ΔV Loss':>10} {'Fuel Ratio':>12} {'Energy/Launch':>14}") print(f"{'':25} {'(°)':>10} {'(m/s)':>10} {'':>12} {'(TJ)':>14}") print("-" * 80) for site in LAUNCH_SITES: k = fuel_ratio_multistage(site.total_delta_v) e = energy_per_launch(site) / 1e12 print(f"{site.name:<25} {site.abs_latitude:>10.1f} {site.delta_v_loss:>10.0f} {k:>12.1f} {e:>14.1f}") print("=" * 80) def analyze_launch_frequency_scenarios( save_path: str = '/Volumes/Files/code/mm/20260130_b/launch_frequency_analysis.png' ): """ 分析不同发射频率场景下的完成时间和能量消耗 """ total_launches = int(TOTAL_PAYLOAD / PAYLOAD_PER_LAUNCH) num_sites = len(LAUNCH_SITES) # 不同发射频率场景 frequencies = [1, 2, 4, 8, 12, 24] # launches per day per site results = [] for freq in frequencies: # 最短完成时间 min_years = total_launches / (num_sites * freq * 365) # 分析该时间下的能量(所有站点满负荷) distribution = calculate_launch_distribution(total_launches, min_years) stats = calculate_total_energy(distribution) results.append({ 'frequency': freq, 'min_years': min_years, 'total_energy_PJ': stats['total_energy_PJ'], 'total_fuel_Mt': stats['total_fuel_Mt'], }) df = pd.DataFrame(results) # 绘图 fig, axes = plt.subplots(1, 2, figsize=(14, 6)) # 图1: 发射频率 vs 完成时间 ax1 = axes[0] ax1.bar(range(len(frequencies)), df['min_years'], color='steelblue', alpha=0.8) ax1.set_xticks(range(len(frequencies))) ax1.set_xticklabels([f'{f}/day' for f in frequencies]) ax1.set_xlabel('Launch Frequency (per site)', fontsize=12) ax1.set_ylabel('Minimum Completion Time (years)', fontsize=12) ax1.set_title('Completion Time vs Launch Frequency\n(10 sites, 800,000 launches)', fontsize=13) ax1.grid(True, alpha=0.3, axis='y') # 添加数值标签 for i, (freq, years) in enumerate(zip(frequencies, df['min_years'])): ax1.text(i, years + 2, f'{years:.1f}y', ha='center', fontsize=10, fontweight='bold') # 图2: 能量消耗比较 ax2 = axes[1] ax2.bar(range(len(frequencies)), df['total_energy_PJ'], color='coral', alpha=0.8) ax2.set_xticks(range(len(frequencies))) ax2.set_xticklabels([f'{f}/day' for f in frequencies]) ax2.set_xlabel('Launch Frequency (per site)', fontsize=12) ax2.set_ylabel('Total Energy (PJ)', fontsize=12) ax2.set_title('Total Energy Consumption\n(Same for all frequencies at max capacity)', fontsize=13) ax2.grid(True, alpha=0.3, axis='y') plt.tight_layout() plt.savefig(save_path, dpi=150, bbox_inches='tight') print(f"\n发射频率分析图已保存至: {save_path}") return df def plot_comprehensive_analysis( save_path: str = '/Volumes/Files/code/mm/20260130_b/rocket_comprehensive.png' ): """ 综合分析图:不同时间线下的能量消耗和发射分配 """ total_launches = int(TOTAL_PAYLOAD / PAYLOAD_PER_LAUNCH) num_sites = len(LAUNCH_SITES) min_years = total_launches / (num_sites * 365) # 选择几个关键时间点 key_years = [min_years, min_years*1.5, min_years*2, min_years*3, min_years*5] fig, axes = plt.subplots(2, 3, figsize=(18, 12)) # 第一行:能量趋势 ax_main = axes[0, 0] years_range = np.linspace(min_years, min_years * 5, 100) df = analyze_completion_timeline(years_range) ax_main.plot(df['years'], df['total_energy_PJ'], 'b-', linewidth=2) ax_main.fill_between(df['years'], df['total_energy_PJ'], alpha=0.3) # 标记关键点 for y in key_years[1:]: ax_main.axvline(x=y, color='gray', linestyle='--', alpha=0.5) ax_main.set_xlabel('Completion Time (years)', fontsize=11) ax_main.set_ylabel('Total Energy (PJ)', fontsize=11) ax_main.set_title('Energy vs Timeline\n(Longer time → Lower energy)', fontsize=12) ax_main.grid(True, alpha=0.3) # 能量效率 ax_eff = axes[0, 1] ax_eff.plot(df['years'], df['energy_per_launch_TJ'], 'r-', linewidth=2) ax_eff.set_xlabel('Completion Time (years)', fontsize=11) ax_eff.set_ylabel('Energy per Launch (TJ)', fontsize=11) ax_eff.set_title('Average Energy Efficiency', fontsize=12) ax_eff.grid(True, alpha=0.3) # 发射场使用数量 ax_sites = axes[0, 2] ax_sites.plot(df['years'], df['sites_used'], 'g-', linewidth=2) ax_sites.set_xlabel('Completion Time (years)', fontsize=11) ax_sites.set_ylabel('Sites Used', fontsize=11) ax_sites.set_title('Number of Active Sites', fontsize=12) ax_sites.set_ylim(0, 11) ax_sites.grid(True, alpha=0.3) # 第二行:三个时间点的发射分配饼图 scenario_years = [min_years, min_years*2, min_years*5] scenario_names = ['Minimum Time', '2x Minimum', '5x Minimum'] for idx, (years, name) in enumerate(zip(scenario_years, scenario_names)): ax = axes[1, idx] distribution = calculate_launch_distribution(total_launches, years) # 只显示有发射的站点 labels = [s.short_name for s, n in distribution if n > 0] sizes = [n for _, n in distribution if n > 0] latitudes = [s.abs_latitude for s, n in distribution if n > 0] colors = plt.cm.RdYlGn_r(np.array(latitudes) / 60) wedges, texts, autotexts = ax.pie(sizes, labels=labels, autopct='%1.0f%%', colors=colors, pctdistance=0.75) # 计算该场景的能量 stats = calculate_total_energy(distribution) ax.set_title(f'{name}\n({years:.0f} years, {stats["total_energy_PJ"]:.0f} PJ)', fontsize=11) plt.suptitle(f'Rocket Launch Scenario: {TOTAL_PAYLOAD/1e6:.0f}M tons to Moon\n' f'({total_launches:,} launches needed)', fontsize=14, y=1.02) plt.tight_layout() plt.savefig(save_path, dpi=150, bbox_inches='tight') print(f"\n综合分析图已保存至: {save_path}") return fig # ============== 主程序 ============== if __name__ == "__main__": print("=" * 80) print("MOON COLONY ROCKET LAUNCH SCENARIO ANALYSIS") print("Mission: Deliver 100 million metric tons to Moon") print("Constraint: 10 launch sites, max 1 launch/day each") print("=" * 80) # 运行时间线分析 df, fig = plot_timeline_analysis() # 打印摘要 print_analysis_summary(df) # 绘制综合分析图 plot_comprehensive_analysis() # 发射频率场景分析 print("\n" + "=" * 80) print("LAUNCH FREQUENCY SENSITIVITY ANALYSIS") print("=" * 80) freq_df = analyze_launch_frequency_scenarios() print("\nIf launch frequency can be increased:") print(f"{'Frequency':>15} {'Min Years':>15} {'Energy (PJ)':>15}") print("-" * 50) for _, row in freq_df.iterrows(): print(f"{row['frequency']:>12}/day {row['min_years']:>15.1f} {row['total_energy_PJ']:>15.0f}") # 关键结论 print("\n" + "=" * 80) print("KEY FINDINGS") print("=" * 80) print(f""" 1. MINIMUM COMPLETION TIME: {df['years'].min():.0f} years (All 10 sites at 1 launch/day capacity) 2. TOTAL ENERGY REQUIRED: ~{df['total_energy_PJ'].mean():.0f} PJ (~{df['total_fuel_Mt'].mean():.0f} million metric tons of fuel) 3. LATITUDE EFFECT: - Energy savings from using only low-lat sites: ~2-3% - Trade-off: Significantly longer timeline 4. CONCLUSION: Traditional rockets alone are IMPRACTICAL for this mission. 219+ years is far beyond reasonable project timeline. Space Elevator System is essential for feasibility. """)