122 lines
5.2 KiB
Python
122 lines
5.2 KiB
Python
import numpy as np
|
||
import matplotlib.pyplot as plt
|
||
from matplotlib import cm
|
||
|
||
def initialize_trapezoid_simulation(depth_max, length_bottom, length_top, T_initial, dz_dx=0.1):
|
||
"""
|
||
Создает заготовку для 2D-моделирования теплопереноса в трапециевидном грунтовом массиве.
|
||
|
||
:param depth_max: Максимальная глубина (Z_MAX), м.
|
||
:param length_bottom: Ширина трапеции на дне (при Z_MAX), м.
|
||
:param length_top: Ширина трапеции на поверхности (при Z=0), м.
|
||
:param T_initial: Начальная равномерная температура грунта, °C.
|
||
:param dz_dx: Размер ячейки сетки (DX = DZ), м.
|
||
:return: Словарь с инициализированными данными (Temperature, Mask, Coordinates).
|
||
"""
|
||
|
||
# 1. Определение параметров сетки
|
||
DX = DZ = dz_dx
|
||
|
||
N_Z = int(depth_max / DZ) + 1
|
||
N_X = int(length_bottom / DX) + 1
|
||
|
||
# 2. Инициализация и геометрическая маска
|
||
|
||
# Создаем 2D-массив температуры, заполненный начальной температурой T_initial
|
||
Temperature = np.full((N_Z, N_X), T_initial, dtype=float)
|
||
|
||
# Создаем булеву маску для определения области трапеции
|
||
mask = np.full((N_Z, N_X), False)
|
||
|
||
for i in range(N_Z):
|
||
depth_i = i * DZ
|
||
|
||
# Линейное изменение ширины по глубине Z
|
||
# W(Z) = L_bottom - (L_bottom - L_top) * (1 - Z/Z_MAX)
|
||
W_z = length_bottom - (length_bottom - length_top) * (1 - depth_i / depth_max)
|
||
|
||
# Центрирование: отступ слева
|
||
offset_x = (length_bottom - W_z) / 2
|
||
|
||
# Индексы X, которые попадают в трапецию
|
||
start_j = int(offset_x / DX)
|
||
end_j = int((length_bottom - offset_x) / DX)
|
||
|
||
# Заполняем маску для текущей глубины
|
||
start_j = max(0, start_j)
|
||
end_j = min(N_X, end_j)
|
||
mask[i, start_j:end_j] = True
|
||
|
||
# Применяем маску: области вне трапеции помечаются как NaN (для визуализации)
|
||
Temperature[~mask] = np.nan
|
||
|
||
# 3. Визуализация Дня 0
|
||
|
||
X_COORD = np.linspace(0, length_bottom, N_X)
|
||
Z_COORD = np.linspace(-depth_max, 0, N_Z)
|
||
|
||
fig, ax = plt.subplots(figsize=(10, 5))
|
||
fig.suptitle(f'Начальное состояние моделирования (День 0)', fontsize=14)
|
||
|
||
# Настройка цветовой карты для NaN
|
||
cmap_base = plt.colormaps['RdYlBu']
|
||
cmap_custom = cmap_base.copy()
|
||
cmap_custom.set_bad('lightgray')
|
||
|
||
im = ax.imshow(Temperature,
|
||
extent=[0, length_bottom, -depth_max, 0],
|
||
origin='upper',
|
||
cmap=cmap_custom,
|
||
aspect='auto',
|
||
vmin=T_initial - 1, # Устанавливаем Vmin/Vmax для старта
|
||
vmax=T_initial + 1)
|
||
|
||
# Наложение контура трапеции
|
||
ax.contour(X_COORD, Z_COORD, mask.astype(int), levels=[0.5], colors='k', linewidths=1.5, linestyles='--')
|
||
|
||
ax.set_title(f'Начальная температура: {T_initial:.1f} °C')
|
||
ax.set_xlabel('Длина (X), м')
|
||
ax.set_ylabel('Глубина (Z), м')
|
||
|
||
cbar = fig.colorbar(im, ax=ax, orientation='vertical', fraction=0.04, pad=0.04)
|
||
cbar.set_label('Температура, °C')
|
||
|
||
plt.tight_layout()
|
||
plt.show()
|
||
|
||
# 4. Возврат данных для дальнейших расчетов
|
||
return {
|
||
'Temperature_Initial': Temperature,
|
||
'Mask': mask,
|
||
'DX': DX,
|
||
'DZ': DZ,
|
||
'N_X': N_X,
|
||
'N_Z': N_Z
|
||
}
|
||
|
||
# ----------------------------------------------------------------------
|
||
## 🚀 Пример использования
|
||
# ----------------------------------------------------------------------
|
||
|
||
# ВХОДНЫЕ ПАРАМЕТРЫ:
|
||
MAX_DEPTH = 2.0 # Глубина 2 м
|
||
WIDTH_BOTTOM = 22.0 # Ширина на дне 22 м
|
||
WIDTH_TOP = 10.0 # Ширина на поверхности 10 м
|
||
INITIAL_TEMP = 5.0 # Начальная температура грунта 5 °C
|
||
CELL_SIZE = 0.1 # Размер ячейки 10 см
|
||
|
||
# Выполнение инициализации и визуализация
|
||
initial_data = initialize_trapezoid_simulation(
|
||
depth_max=MAX_DEPTH,
|
||
length_bottom=WIDTH_BOTTOM,
|
||
length_top=WIDTH_TOP,
|
||
T_initial=INITIAL_TEMP,
|
||
dz_dx=CELL_SIZE
|
||
)
|
||
|
||
print("\n--- Сводка по инициализации ---")
|
||
print(f"Размеры сетки (Z x X): {initial_data['N_Z']} x {initial_data['N_X']}")
|
||
print(f"Размер ячейки: {initial_data['DX']} м")
|
||
|
||
# Теперь initial_data можно передать в цикл моделирования
|
||
# (который мы создавали ранее), чтобы начать расчеты. |