| """ |
| Climate Kernel (๊ธฐํ ์ปค๋) |
| |
| ๊ธฐํ ์กฐ๊ฑด์ ๋ฐ๋ฅธ ๊ฐ์/๊ธฐ์จ ๋ถํฌ ์์ฑ |
| - ์๋ ๊ธฐ๋ฐ ๊ฐ์ ํจํด |
| - ๊ณ ๋ ๊ธฐ๋ฐ ์งํ์ฑ ๊ฐ์ |
| - ๊ธฐ์จ์ ๋ฐ๋ฅธ ํํ์จ ์กฐ์ |
| """ |
|
|
| import numpy as np |
| from .grid import WorldGrid |
|
|
|
|
| class ClimateKernel: |
| """ |
| ๊ธฐํ ์ปค๋ |
| |
| ๊ฐ์์ ๊ธฐ์จ ๋ถํฌ๋ฅผ ์์ฑํ์ฌ ๋ค๋ฅธ ํ๋ก์ธ์ค์ ์ํฅ. |
| """ |
| |
| def __init__(self, grid: WorldGrid, |
| base_precipitation: float = 1000.0, |
| base_temperature: float = 15.0, |
| lapse_rate: float = 6.5): |
| self.grid = grid |
| self.base_precipitation = base_precipitation |
| self.base_temperature = base_temperature |
| self.lapse_rate = lapse_rate |
| |
| def generate_precipitation(self, |
| orographic_factor: float = 0.5, |
| latitude_effect: bool = True) -> np.ndarray: |
| """ |
| ๊ฐ์ ๋ถํฌ ์์ฑ |
| |
| Args: |
| orographic_factor: ์งํ์ฑ ๊ฐ์ ๊ฐ๋ (0~1) |
| latitude_effect: ์๋ ํจ๊ณผ ์ ์ฉ ์ฌ๋ถ |
| |
| Returns: |
| precipitation: ๊ฐ์๋ ๋ฐฐ์ด (mm/year โ m/timestep์ผ๋ก ๋ณํ ํ์) |
| """ |
| h, w = self.grid.height, self.grid.width |
| elev = self.grid.elevation |
| |
| |
| precip = np.ones((h, w)) * self.base_precipitation |
| |
| |
| if latitude_effect: |
| |
| |
| lat_factor = np.zeros(h) |
| for r in range(h): |
| |
| normalized_lat = r / h |
| |
| lat_factor[r] = 1.0 - 0.3 * abs(normalized_lat - 0.5) * 2 |
| |
| precip *= lat_factor[:, np.newaxis] |
| |
| |
| if orographic_factor > 0: |
| |
| |
| |
| |
| |
| _, dx = self.grid.get_gradient() |
| |
| |
| orographic = 1.0 + orographic_factor * (-dx) * 0.1 |
| orographic = np.clip(orographic, 0.2, 2.0) |
| |
| precip *= orographic |
| |
| |
| |
| optimal_elev = 2000.0 |
| elev_effect = 1.0 - 0.2 * np.abs(elev - optimal_elev) / optimal_elev |
| elev_effect = np.clip(elev_effect, 0.3, 1.2) |
| |
| precip *= elev_effect |
| |
| return precip |
| |
| def get_temperature(self) -> np.ndarray: |
| """ |
| ๊ธฐ์จ ๋ถํฌ ์์ฑ |
| |
| Returns: |
| temperature: ๊ธฐ์จ ๋ฐฐ์ด (ยฐC) |
| """ |
| h, w = self.grid.height, self.grid.width |
| elev = self.grid.elevation |
| |
| |
| temp = np.ones((h, w)) * self.base_temperature |
| |
| |
| for r in range(h): |
| normalized_lat = r / h |
| |
| lat_temp_diff = 30.0 * abs(normalized_lat - 0.5) * 2 |
| temp[r, :] -= lat_temp_diff |
| |
| |
| |
| temp -= (elev / 1000.0) * self.lapse_rate |
| |
| return temp |
| |
| def get_weathering_rate(self, temperature: np.ndarray = None) -> np.ndarray: |
| """ |
| ๊ธฐ์จ์ ๋ฐ๋ฅธ ํํ์จ ๊ณ์ฐ |
| |
| ํํ์ ํํ: ์จ๋ ๋ค์ต โ ๋น ๋ฆ |
| ๋ฌผ๋ฆฌ์ ํํ: ๋๊ฒฐ-์ตํด (-10~10ยฐC) โ ๋น ๋ฆ |
| |
| Args: |
| temperature: ๊ธฐ์จ ๋ฐฐ์ด (์์ผ๋ฉด ์์ฑ) |
| |
| Returns: |
| weathering_rate: ์๋ ํํ์จ (0~1) |
| """ |
| if temperature is None: |
| temperature = self.get_temperature() |
| |
| h, w = self.grid.height, self.grid.width |
| |
| |
| chemical = np.clip((temperature + 10) / 40.0, 0, 1) |
| |
| |
| freeze_thaw = np.exp(-((temperature - 0) ** 2) / (2 * 10 ** 2)) |
| |
| |
| weathering = chemical * 0.5 + freeze_thaw * 0.5 |
| |
| return weathering |
|
|