File size: 5,307 Bytes
2afa69c | 1 2 3 4 5 6 7 8 9 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 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 | import numpy as np
from dataclasses import dataclass
from .grid import WorldGrid
from .fluids import HydroKernel
from .erosion_process import ErosionProcess
from .lateral_erosion import LateralErosionKernel
from .mass_movement import MassMovementKernel
from .climate import ClimateKernel
from .wave import WaveKernel
from .glacier import GlacierKernel
from .wind import WindKernel
class EarthSystem:
"""
Project Genesis: Unified Earth System Engine
ํตํฉ ์ง๊ตฌ ์์คํ
์์ง
- ๊ธฐํ(Climate) -> ์๋ฌธ(Hydro) -> ์งํ(Erosion/Tectonics) ์ํธ์์ฉ์
๋จ์ผ ๋ฃจํ(step) ๋ด์์ ์ฒ๋ฆฌํฉ๋๋ค.
"""
def __init__(self, grid: WorldGrid):
self.grid = grid
self.time = 0.0
# Core Kernels
self.hydro = HydroKernel(self.grid)
self.erosion = ErosionProcess(self.grid)
self.lateral = LateralErosionKernel(self.grid, k=0.01)
self.mass_movement = MassMovementKernel(self.grid, friction_angle=35.0)
self.climate = ClimateKernel(self.grid)
# Phase 2 Kernels (Optional, enabled via settings)
self.wave = WaveKernel(self.grid)
self.glacier = GlacierKernel(self.grid)
self.wind = WindKernel(self.grid)
# State History (Optional for analysis)
self.history = []
def step(self, dt: float = 1.0, settings: dict = None):
"""
์์คํ
1๋จ๊ณ ์งํ (Time Step)
Process Chain:
1. Tectonics (Endogenous): Uplift, subsidence based on scenario settings
2. Climate (Exogenous): Generate precipitation
3. Hydro (Physics): Route flow, calculate discharge/depth
4. Morphodynamics (Response): Erode, transport, deposit
"""
if settings is None:
settings = {}
# 1. Tectonics (์ง๊ตฌ์กฐ ์ด๋)
# Simple vertical uplift logic if provided
uplift_rate = settings.get('uplift_rate', 0.0)
tile_uplift = settings.get('uplift_mask', None)
if uplift_rate > 0:
if tile_uplift is not None:
self.grid.apply_uplift(tile_uplift * uplift_rate, dt)
else:
self.grid.apply_uplift(uplift_rate, dt)
# 2. Climate (๊ธฐํ)
# Generate precipitation map
# Default: Uniform rain + randomness
base_precip = settings.get('precipitation', 0.01)
precip_map = np.ones((self.grid.height, self.grid.width)) * base_precip
# Apply rain source if specified (e.g., river mouth)
rain_source = settings.get('rain_source', None) # (y, x, radius, amount)
if rain_source:
y, x, r, amount = rain_source
# Simplified box source for speed
y_min, y_max = max(0, int(y-r)), min(self.grid.height, int(y+r+1))
x_min, x_max = max(0, int(x-r)), min(self.grid.width, int(x+r+1))
precip_map[y_min:y_max, x_min:x_max] += amount
# 3. Hydro (์๋ฌธ)
# Route flow based on current topography + precip
discharge = self.hydro.route_flow_d8(precipitation=precip_map)
# Update grid state
self.grid.discharge = discharge
self.grid.water_depth = self.hydro.calculate_water_depth(discharge)
# 4. Erosion / Deposition (์งํ ๋ณํ)
# Using the ErosionKernel (ErosionProcess wrapper)
# Need to update K, m, n parameters dynamically?
# For now, use instance defaults or allow overrides
# Execute Transport & Deposition
sediment_influx_map = None
sediment_source = settings.get('sediment_source', None) # (y, x, radius, amount)
if sediment_source:
y, x, r, amount = sediment_source
sediment_influx_map = np.zeros((self.grid.height, self.grid.width))
y_min, y_max = max(0, int(y-r)), min(self.grid.height, int(y+r+1))
x_min, x_max = max(0, int(x-r)), min(self.grid.width, int(x+r+1))
sediment_influx_map[y_min:y_max, x_min:x_max] += amount
self.erosion.simulate_transport(discharge, dt=dt, sediment_influx_map=sediment_influx_map)
# 5. Lateral Erosion (์ธก๋ฐฉ ์นจ์) - ๊ณก๋ฅ ํ์ฑ
lateral_enabled = settings.get('lateral_erosion', True)
if lateral_enabled:
self.lateral.step(discharge, dt=dt)
# 6. Hillslope Diffusion (์ฌ๋ฉด ์์ ํ)
diff_rate = settings.get('diffusion_rate', 0.01)
if diff_rate > 0:
self.erosion.hillslope_diffusion(dt=dt * diff_rate)
# 7. Mass Movement (๋งค์ค๋ฌด๋ธ๋จผํธ) - ์ฐ์ฌํ
mass_movement_enabled = settings.get('mass_movement', True)
if mass_movement_enabled:
self.mass_movement.step(dt=dt)
# Update Time
self.time += dt
def get_state(self):
"""ํ์ฌ ์์คํ
์ํ ๋ฐํ"""
self.grid.update_elevation()
return {
'elevation': self.grid.elevation.copy(),
'water_depth': self.grid.water_depth.copy(),
'discharge': self.grid.discharge.copy(),
'sediment': self.grid.sediment.copy(),
'time': self.time
}
|