| 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 |
| |
| |
| 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) |
| |
| |
| self.wave = WaveKernel(self.grid) |
| self.glacier = GlacierKernel(self.grid) |
| self.wind = WindKernel(self.grid) |
| |
| |
| 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 = {} |
| |
| |
| |
| 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) |
| |
| |
| |
| |
| base_precip = settings.get('precipitation', 0.01) |
| precip_map = np.ones((self.grid.height, self.grid.width)) * base_precip |
| |
| |
| rain_source = settings.get('rain_source', None) |
| if rain_source: |
| y, x, r, amount = rain_source |
| |
| 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 |
| |
| |
| |
| discharge = self.hydro.route_flow_d8(precipitation=precip_map) |
| |
| |
| self.grid.discharge = discharge |
| self.grid.water_depth = self.hydro.calculate_water_depth(discharge) |
| |
| |
| |
| |
| |
| |
| |
| sediment_influx_map = None |
| sediment_source = settings.get('sediment_source', None) |
| 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) |
| |
| |
| lateral_enabled = settings.get('lateral_erosion', True) |
| if lateral_enabled: |
| self.lateral.step(discharge, dt=dt) |
| |
| |
| diff_rate = settings.get('diffusion_rate', 0.01) |
| if diff_rate > 0: |
| self.erosion.hillslope_diffusion(dt=dt * diff_rate) |
| |
| |
| mass_movement_enabled = settings.get('mass_movement', True) |
| if mass_movement_enabled: |
| self.mass_movement.step(dt=dt) |
| |
| |
| 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 |
| } |
|
|