diff --git a/src/postprocessing/map.py b/src/postprocessing/map.py index 79731a7..43e8d27 100644 --- a/src/postprocessing/map.py +++ b/src/postprocessing/map.py @@ -672,7 +672,52 @@ class ContentMapper: grid_y = grid_yy[:, 0] total_cells = len(grid_x) * len(grid_y) - # ── 1) 全局变异函数拟合(多模型容错回退)── + # ── 1) 全局变异函数拟合(自适应分层抽样防 OOM)── + # 变异函数拟合内存 ≈ N²×8 bytes。预留 1.5GB 安全上限 → N_max≈14000 + _vario_pts = points + _vario_vals = values + # 从系统内存动态估算可容纳的最大点数 + try: + import psutil + _avail_gb = psutil.virtual_memory().available / (1024**3) + except Exception: + _avail_gb = 4.0 # 保守兜底 + # 计算安全点数:留 50% 余量给 Python 开销 + _MAX_VARIOGRAM_PTS = int(np.sqrt(max(_avail_gb * 0.5, 0.5) * 1024**3 / 8)) + _MAX_VARIOGRAM_PTS = np.clip(_MAX_VARIOGRAM_PTS, 3000, 20000) + + if len(points) > _MAX_VARIOGRAM_PTS: + # 空间分层抽样:网格覆盖全水域,每格保留1点 + _grid = int(np.ceil(np.sqrt(_MAX_VARIOGRAM_PTS))) + _x_bins = np.linspace(points[:, 0].min(), points[:, 0].max(), _grid + 1) + _y_bins = np.linspace(points[:, 1].min(), points[:, 1].max(), _grid + 1) + _keep = np.zeros(len(points), dtype=bool) + for _ix in range(_grid): + for _iy in range(_grid): + _cell = ( + (points[:, 0] >= _x_bins[_ix]) & + (points[:, 0] < _x_bins[_ix + 1]) & + (points[:, 1] >= _y_bins[_iy]) & + (points[:, 1] < _y_bins[_iy + 1]) + ) + if _cell.any(): + _keep[np.where(_cell)[0][0]] = True + _kept_idx = np.where(_keep)[0] + if len(_kept_idx) < _MAX_VARIOGRAM_PTS: + _remaining = np.where(~_keep)[0] + _extra = np.random.default_rng(42).choice( + _remaining, + min(_MAX_VARIOGRAM_PTS - len(_kept_idx), len(_remaining)), + replace=False, + ) + _kept_idx = np.concatenate([_kept_idx, _extra]) + _vario_pts = points[_kept_idx] + _vario_vals = values[_kept_idx] + print(f" [Kriging] 采样点 {len(points)} > {_MAX_VARIOGRAM_PTS}" + f"(可用内存 {_avail_gb:.1f}GB)," + f"空间分层抽样 → {len(_kept_idx)} 点" + f"(网格 {_grid}×{_grid},全覆盖)") + _vario_models = [ ('spherical', {'nugget': 1e-6}), ('exponential', {'nugget': 1e-6}), @@ -684,7 +729,7 @@ class ContentMapper: for _vm_name, _vm_kw in _vario_models: try: ok_model = OrdinaryKriging( - points[:, 0], points[:, 1], values, + _vario_pts[:, 0], _vario_pts[:, 1], _vario_vals, variogram_model=_vm_name, verbose=False, enable_plotting=False, **_vm_kw,