Files
irrigation-model/irrgiation/mathuntils.py
2025-12-23 08:38:08 +08:00

372 lines
13 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#根据日期计算当年天数
import numpy as np
import pandas as pd
from matplotlib import pyplot as plt
def is_leap_year(year):
return (year % 4 == 0 and year % 100 != 0) or (year % 400 == 0)
def day_of_year(date_str):
date_part = date_str.split()[0]
year = int(date_str[:4]) # 取前4位 → 2025
month = int(date_str[5:7]) # 取第5-6位 → 06 → 6
day = int(date_str[8:10]) # 取第8-9位 → 30
month_days = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
if is_leap_year(year):
month_days[1] = 29 # 闰年2月29天
total = sum(month_days[:month-1]) + day
return total
#计算每天有效日照时长
def count_above_threshold(data, threshold,date):
filtered = filter(lambda x: float(x['value_cal']) >= threshold and x['datetime'].split(" ")[0] == date, data)
return len(list(filtered))
# 示例计算函数Lux转W/m²
def lux_to_wm2(lux_value):
"""将Lux值转换为W/m²使用标准系数0.0081"""
return lux_value * 0.0081
def convert_lux_to_Radiant_Flux(data_dict):
"""
递归地将字典中的所有'timestamp'字段转换为可读的日期时间格式
保留原始时间戳的同时添加新的'datetime'字段
"""
if 'value' in data_dict:
radiant_Flux=data_dict["value"]*0.001496
data_dict["value_radiant"] =radiant_Flux
return data_dict
def lux_to_solar_rad(lux,h):
return lux * 0.001496*h * 3.6 / 1000
def plot(soil_data,name):
import matplotlib.dates as mdates
# 创建画布
plt.figure(figsize=(14, 8))
# 处理并绘制地表湿度数据
surface_df = pd.DataFrame(soil_data["SOIL_MOISTURE_SURFACE"])
surface_df['datetime'] = pd.to_datetime(surface_df['datetime'])
surface_df['value'] = surface_df['value'].astype(float)
plt.plot(surface_df['datetime'], surface_df['value'],
label='Surface Moisture (0-5cm)', color='#FF6B6B', linewidth=2, marker='o', markersize=5)
# 处理并绘制中层湿度数据
middle_df = pd.DataFrame(soil_data["SOIL_MOISTURE_MIDDLE"])
middle_df['datetime'] = pd.to_datetime(middle_df['datetime'])
middle_df['value'] = middle_df['value'].astype(float)
plt.plot(middle_df['datetime'], middle_df['value'],
label='Middle Layer Moisture', color='#4ECDC4', linewidth=2, marker='s', markersize=5)
# 处理并绘制中层湿度数据
middle_df = pd.DataFrame(soil_data["SOIL_MOISTURE_BOTTOM"])
middle_df['datetime'] = pd.to_datetime(middle_df['datetime'])
middle_df['value'] = middle_df['value'].astype(float)
plt.plot(middle_df['datetime'], middle_df['value'],
label='BOTTOM Layer Moisture', color='blue', linewidth=2, marker='s', markersize=5)
# 设置图表格式
plt.title('Soil Moisture Variation (Jun 18 - Jul 3, 2025)', fontsize=16, pad=20)
plt.xlabel('Date', fontsize=12)
plt.ylabel('Soil Moisture (%)', fontsize=12)
plt.grid(True, linestyle='--', alpha=0.7)
# 设置x轴日期格式
ax = plt.gca()
ax.xaxis.set_major_locator(mdates.DayLocator(interval=2))
ax.xaxis.set_major_formatter(mdates.DateFormatter('%m/%d'))
plt.xticks(rotation=45)
# 添加图例和注释
plt.legend(loc='upper right', fontsize=10)
plt.tight_layout()
# 保存图片到本地
output_path = 'D:\悦柠\遥感\甘草\ceshi/'+name+".png"
plt.savefig(output_path, dpi=300, bbox_inches='tight')
# 显示图表
# plt.show()
def rh_to_theta_vg(rh, soil_params, temperature=25):
"""使用Van Genuchten模型将相对湿度转换为体积含水量"""
# 计算土壤水势(kPa)
psi = -145 * np.log(rh / 100)
# 提取土壤参数
theta_s = soil_params["theta_s"] # 饱和含水量
theta_r = soil_params["theta_r"] # 残余含水量
alpha = soil_params["alpha"] # Van Genuchten参数
n = soil_params["n"] # Van Genuchten参数
m = 1 - 1 / n
# 计算体积含水量
theta = theta_r + (theta_s - theta_r) / ((1 + (alpha * abs(psi)) ** n) ** m)
print(theta)
return theta
def calculate_soil_moisture_after_irrigation(
initial_moisture: float,
field_capacity: float,
irrigation_volume: float,
soil_volume: float,
area: float = None,
verbose: bool = False
) -> float:
"""
不考虑降雨量和蒸散量时,计算灌溉后的土壤相对湿度
参数:
initial_moisture: 初始土壤相对湿度 (%)
field_capacity: 田间持水量 (%)
irrigation_volume: 灌溉量 (m³)
soil_volume: 土壤体积 (m³)
area: 灌溉面积 (㎡,可选,仅用于打印提示)
verbose: 是否打印详细计算过程
返回:
float: 灌溉后土壤相对湿度 (%)
"""
# 参数验证
if not (0 <= initial_moisture <= 100):
raise ValueError("初始湿度必须在0-100%之间")
if not (0 < field_capacity <= 100):
raise ValueError("田间持水量必须在0-100%之间且大于0")
if irrigation_volume < 0:
raise ValueError("灌溉量不能为负数")
if soil_volume <= 0:
raise ValueError("土壤体积必须大于0")
# 计算初始土壤含水量
initial_water = (initial_moisture / 100) * (field_capacity / 100) * soil_volume
# 灌溉后总含水量
total_water = initial_water + irrigation_volume
# 计算田间持水总量
max_water = (field_capacity / 100) * soil_volume
# 计算灌溉后湿度超过田间持水量时取100%
final_moisture = min((total_water / max_water) * 100, 100.0)
# if verbose:
# area_info = f"(面积: {area}㎡)" if area else ""
# print(f"===== 不考虑降雨与蒸散的灌溉计算 {area_info} =====")
# print(f"初始湿度: {initial_moisture}%")
# print(f"田间持水量: {field_capacity}%")
# print(f"土壤体积: {soil_volume}m³")
# print(f"灌溉量: {irrigation_volume}m³")
# print(f"初始含水量: {initial_water:.2f}m³")
# print(f"灌溉后含水量: {total_water:.2f}m³")
# print(f"田间最大持水量: {max_water:.2f}m³")
# print(f"灌溉后土壤湿度: {final_moisture:.2f}%")
return final_moisture
def calculate_irrigation_volume(
initial_moisture: float,
target_moisture: float,
field_capacity: float,
soil_volume: float
) -> float:
"""
计算为达到目标土壤相对湿度所需的灌溉量
参数:
initial_moisture: 初始土壤相对湿度 (%)
target_moisture: 目标土壤相对湿度 (%)
field_capacity: 田间持水量 (%)
soil_volume: 土壤体积 (m³)
area: 灌溉面积 (㎡,可选,仅用于打印提示)
verbose: 是否打印详细计算过程
返回:
float: 需要的灌溉量 (m³)
"""
# 参数验证
if not (0 <= initial_moisture <= 100):
raise ValueError("初始湿度必须在0-100%之间")
if not (0 <= target_moisture <= 100):
raise ValueError("目标湿度必须在0-100%之间")
if not (0 < field_capacity <= 100):
raise ValueError("田间持水量必须在0-100%之间且大于0")
if soil_volume <= 0:
raise ValueError("土壤体积必须大于0")
if target_moisture <= initial_moisture:
raise ValueError("目标湿度必须大于初始湿度")
# 计算初始土壤含水量
initial_water = (initial_moisture / 100) * (field_capacity / 100) * soil_volume
# 计算目标含水量
target_water = (target_moisture / 100) * (field_capacity / 100) * soil_volume
# 需要的灌溉量
irrigation_volume = target_water - initial_water
return irrigation_volume
def irriDepth_irrvolume(area,irrDepth):
volume=area*667*(irrDepth/1000)
return volume
def calculate_irrigation(dry_soil_weight, current_humidity, target_humidity,
irrigation_efficiency=0.8, water_density=1000):
"""
计算达到目标湿度所需的灌溉量
Args:
dry_soil_weight (float): 土壤干重kg
current_humidity (float): 当前相对湿度(%
target_humidity (float): 目标相对湿度(%
irrigation_efficiency (float): 灌溉效率0~1
water_density (float): 水密度kg/m³
Returns:
float: 灌溉量(立方米)
"""
if current_humidity >= target_humidity:
return 0.0
delta_humidity = (target_humidity - current_humidity) / 100
water_weight = dry_soil_weight * delta_humidity
water_volume = water_weight / water_density
return water_volume / irrigation_efficiency
def calculate_rh_target(
initial_moisture: float,
root: float,
field_capacity: float,
irrigation:float
) -> float:
initial_moisture=(initial_moisture / 100) * field_capacity
iir_volume=irrigation/(10*root)
target_moisture = initial_moisture + (iir_volume/field_capacity)
return target_moisture
def calculate_rh_target(
initial_moisture: float, # 初始土壤相对湿度(%)
root: float, # 根系深度(cm)
field_capacity: float, # 田间持水量(体积含水量 cm³/cm³)
irrigation: float # 灌溉量(mm)
) -> float:
"""
计算灌溉后的目标土壤相对湿度(%)
参数:
initial_moisture: 初始土壤相对湿度(%)
root: 根系深度(cm)
field_capacity: 田间持水量(体积含水量 cm³/cm³)
irrigation: 灌溉量(mm)
返回:
float: 灌溉后的目标土壤相对湿度(%)
"""
# 参数验证
if initial_moisture < 0 or initial_moisture > 100:
raise ValueError("初始湿度必须在0-100%之间")
if root <= 0:
raise ValueError("根系深度必须大于0")
if field_capacity <= 0 or field_capacity > 1:
raise ValueError("田间持水量必须在0-1 cm³/cm³之间")
if irrigation < 0:
raise ValueError("灌溉量不能为负值")
# 将相对湿度转为体积含水量
initial_volume_moisture = (initial_moisture / 100) * field_capacity
# 计算灌溉增加的体积含水量
# 将mm转为cm并除以根系深度得到体积含水量增量
moisture_increase = (irrigation / 10) / root
# 计算灌溉后的体积含水量
target_volume_moisture = initial_volume_moisture + moisture_increase
# 转换回相对湿度(%)
target_rh = (target_volume_moisture / field_capacity) * 100
# 确保不超过100%
target_rh = min(target_rh, 100.0)
# # 3. 计算目标体积含水量 (不超过田间持水量)
# target_volume = min(initial_volume + moisture_increase, field_capacity)
#
# # 4. 转换回相对湿度 (%)
# target_rh = (target_volume / field_capacity) * 100
return target_rh
def calculate_rh_target_rz(
initial_moisture: float, # 初始土壤相对湿度(%)
soil_root: float, # 根系深度(cm)
area: float, # 灌溉面积(亩)
irrigation: float, # 灌溉量(mm)
field_capacity: float = 28.84, # 田间持水量(%)默认35%
soil_bulk_density: float = 1.5 # 土壤容重(g/cm³)默认1.5
) -> float:
"""
计算灌溉后的目标根区土壤相对湿度
参数:
initial_moisture: 初始土壤相对湿度(%)
soil_root: 根系深度(cm)
area: 灌溉面积(亩)
irrigation: 灌溉量(mm)
field_capacity: 田间持水量(%)默认35%
soil_bulk_density: 土壤容重(g/cm³)默认1.5
返回:
float: 灌溉后的目标土壤相对湿度(%)
"""
# 参数验证
if initial_moisture < 0 or initial_moisture > 100:
raise ValueError("初始湿度必须在0-100%之间")
if soil_root <= 0:
raise ValueError("根系深度必须大于0")
if area <= 0:
raise ValueError("面积必须大于0")
if irrigation < 0:
raise ValueError("灌溉量不能为负值")
# 计算根区体积
root_volume = area * 667 * (soil_root / 100) # m³将cm转为m
# 计算灌溉水体积
water_volume = (irrigation / 1000) * area * 667 # m³将mm转为m
# 计算灌溉增加的土壤湿度(%)
moisture_increase = (water_volume / (root_volume * soil_bulk_density)) * 100
# 计算目标湿度
target_moisture = initial_moisture + moisture_increase
# 确保不超过田间持水量
target_moisture = min(target_moisture, field_capacity)
return target_moisture
if __name__ == '__main__':
# volume=irriDepth_irrvolume(10.95,11.123)
# soil_volume_dk1 = 10.95 * 667 * 0.15
# soil_volume_dk2 = 8.92 * 667 * 0.15
# result1 = calculate_soil_moisture_after_irrigation(
# initial_moisture=15.2,
# field_capacity=28.84,
# irrigation_volume=168,
# soil_volume=soil_volume_dk1,
# verbose=True
# )
# print(f"\n示例1结果: 灌溉后湿度 = {result1:.2f}%\n")
# print(soil_volume_dk1)
# result2=calculate_irrigation_volume(initial_moisture=15.44,
# field_capacity=28.84,
# target_moisture=70,
# soil_volume=soil_volume_dk1)
# print(f"\n达到目标湿度所需灌溉量 = {result2:.2f}\n")
# # 调用示例
# dry_soil_weight=10.95*667*0.1*1200
# volume = calculate_irrigation(
# dry_soil_weight=dry_soil_weight,
# current_humidity=15.4,
# target_humidity=70
# )
# print(f"灌溉量: {volume:.2f} m³") # 输出: 0.09 m³
rh=calculate_rh_target(67.96,6,0.2884,33.14)
rh1 = rh*0.7
print(rh,rh1)