unbanlanced_tension/auto_differentiation.py

320 lines
10 KiB
Python
Raw Normal View History

2020-12-13 16:57:48 +08:00
# 利用自动微分计算
2022-08-22 16:09:08 +08:00
import datetime
2020-12-14 16:05:17 +08:00
from typing import List
2020-12-13 16:57:48 +08:00
import sympy
import data
import exp
import math
import main
2020-12-14 16:05:17 +08:00
import numpy as np
2020-12-13 16:57:48 +08:00
sympy.init_printing()
# h_i 悬点高差
# l_i 悬点档距
# _alpha 导线膨胀系数 1/°C
# _elastic 弹性系数 N/mm2
# _t_e 架线时考虑初伸长的降温取正值。单位°C
# lambda_i 计算不平衡张力时导线比载 N/(m.mm)
# sigma_i 计算不平衡张力时最低点水平应力 单位N/mm2
# t_i 计算不平衡张力时导线温度 单位°C
# _lambda_m 导线架线时时导线比载 N/(m.mm)
# _sigma_m 导线架线时时最低点水平应力 单位N/mm2
# _t_m 导线架线时时导线温度 单位°C
loop_end = data.loop_end # 最大循环次数
# 架线时的状态
# 取外过无风
string_length = data.string_length # 串长 单位m
string_g = data.string_g # 串重 单位N
t_m_data = data.t_m # 导线架设时的气温。单位°C
t_e_data = data.t_e # 架线时考虑初伸长的降温取正值。单位°C
alpha_data = data.alpha # 导线膨胀系数 1/°C
elastic_data = data.elastic # 弹性系数 N/mm2
area_data = data.area # 导线面积 mm2
2020-12-13 16:57:48 +08:00
lambda_m_data = data.lambda_m # 导线比载 N/(m.mm)
sigma_m_data = data.sigma_m # 架线时初伸长未释放前的最低点水平应力。单位N/mm2
span_count = data.span_count # 几个档距
# n个档距,n-1个直线塔
h_array = data.h_array
l_array = data.l_array
t_data = data.t
conductor_n = data.conductor_n
lambda_i_array = data.lambda_i_array
# TODO: 暂时没考虑荷载变化
symbol_delta_l_i = exp.delta_li()
sigma_i = sympy.symbols("sigma_i")
d_delta_l_i_sigma_i = sympy.diff(symbol_delta_l_i, sigma_i)
fx_d_delta_l_i_sigma_i = exp.get_lambdify_d_delta_l_i_sigma_i(d_delta_l_i_sigma_i)
delta_Li__1 = sympy.symbols(
"delta_Li:{span_count}".format(span_count=data.span_count - 1)
)
delta_Li = (
*delta_Li__1,
sympy.symbols("delta_Li_i"),
)
symbol_sigma_i1 = exp.fun_sigma_i1(delta_Li)
delta_Li_i = sympy.symbols("delta_Li_i")
d_sigma_i1_d_l_i = sympy.diff(symbol_sigma_i1, delta_Li_i)
fx_d_sigma_i1_d_l_i = exp.get_lambdify_d_sigma_i1_d_l_i(d_sigma_i1_d_l_i, delta_Li)
# 一共2n个变量n个delta_Lin个sigma_i
# 分 [
# A B
# C D
# E1 E2
# ]
# 6块
# B为dΔli/dσi
def evaluate_d_delta_l_i_sigma_i(val_delta_l_li, val_sigma_i):
val_list = []
for i in range(span_count):
2020-12-14 14:51:44 +08:00
val = sympy.Float(
fx_d_delta_l_i_sigma_i(
val_delta_l_li[i],
l_array[i],
lambda_i_array[i],
alpha_data,
elastic_data,
t_e_data,
t_data,
lambda_m_data,
t_m_data,
sigma_m_data,
val_sigma_i[i],
math.atan(h_array[i] / l_array[i]),
)
)
2022-08-22 16:09:08 +08:00
# manual_val = exp.manual_diff_delta_li_sigma_i(
# h_array[i],
# l_array[i],
# lambda_m_data,
# lambda_i_array[i],
# val_sigma_i[i],
# sigma_m_data,
# alpha_data,
# t_data,
# t_e_data,
# t_m_data,
# elastic_data,
# )
# if math.fabs(val - manual_val) > 1e-5:
# raise Exception("d_delta_l_i_sigma_i 自动和手动微分不匹配")
val_list.append(val)
return val_list
# C为dσi1dΔli
# C只有n-1行
def evaluate_d_sigma_i1_d_delta_l_i(val_delta_l_li, val_sigma_i):
2020-12-13 16:57:48 +08:00
row = []
for i in range(span_count - 1):
col = []
for j in range(span_count):
if i < j:
col.append(0)
else:
_val_delta_l_li = list(val_delta_l_li)
_val_delta_l_li[-1] = _val_delta_l_li[j] # 把需要求导的Δlj放最后一个位置
_val_delta_l_li[j] = 0
# σi1的第i+1行至倒数第2行全部清0
for k in range(i + 1, len(_val_delta_l_li) - 1):
_val_delta_l_li[k] = 0
_val = sympy.Float(
fx_d_sigma_i1_d_l_i(
string_g / conductor_n,
area_data,
lambda_i_array[i],
lambda_i_array[i + 1],
val_sigma_i[i],
h_array[i],
h_array[i + 1],
l_array[i],
l_array[i + 1],
string_length,
val_sigma_i[i + 1],
math.atan(h_array[i] / l_array[i]),
math.atan(h_array[i + 1] / l_array[i + 1]),
*_val_delta_l_li
)
)
2022-08-22 16:09:08 +08:00
# manual_val = exp.manual_diff_sigma_i1_d_l_i(
# h_array[i],
# l_array[i],
# h_array[i + 1],
# l_array[i + 1],
# string_g / conductor_n,
# area_data,
# lambda_i_array[i],
# lambda_i_array[i + 1],
# val_sigma_i[i],
# string_length,
# math.fsum(val_delta_l_li[0 : i + 1]),
# )
# if math.fabs(manual_val - _val) > 1e-5:
# raise Exception("d_sigma_i1_delta_L_i 自动和手动微分不匹配")
2020-12-13 16:57:48 +08:00
col.append(_val)
row.append(col)
return sympy.Matrix(row)
# D为dΔσi1dσi
# D只有n-1行
def evaluate_d_sigma_i1_d_delta_sigma_i(val_delta_li):
row = []
for i in range(span_count - 1):
col = []
for j in range(span_count):
if i == j:
sum_delta_li = math.fsum(val_delta_li)
_val = -(
(
h_array[i] / l_array[i]
+ ((string_g / conductor_n) ** 2 - sum_delta_li ** 2) ** 0.5
)
/ (
((string_g / conductor_n) ** 2 - sum_delta_li ** 2) ** 0.5
+ h_array[i + 1] / l_array[i + 1]
)
)
col.append(_val)
continue
if i == j - 1:
col.append(1)
continue
col.append(0)
row.append(col)
return sympy.Matrix(row)
def solve():
2022-08-22 16:09:08 +08:00
starttime = datetime.datetime.now()
2020-12-13 16:57:48 +08:00
# 初始化
2022-08-22 16:09:08 +08:00
val_delta_li = [data.string_length / (span_count + 1) for _ in range(span_count)]
val_sigma_i = [sigma_m_data for _ in range(span_count)]
2020-12-13 16:57:48 +08:00
loop = 0
while True:
loop += 1
2022-08-22 16:09:08 +08:00
# print("第{loop}次迭代".format(loop=loop))
2020-12-13 16:57:48 +08:00
if loop >= 20:
break
# A为dΔli/dli
M_A = sympy.eye(span_count)
# B为dΔli/dσi
M_B = sympy.diag(
evaluate_d_delta_l_i_sigma_i(val_delta_li, val_sigma_i), unpack=True
)
# C为dΔσi1dli
M_C = evaluate_d_sigma_i1_d_delta_l_i(val_delta_li, val_sigma_i)
# D为dΔσi1dσi
M_D = evaluate_d_sigma_i1_d_delta_sigma_i(val_delta_li)
E1 = [1 for _ in range(span_count)]
E2 = [0 for _ in range(span_count)]
E = list(E1)
E.extend(E2)
M_E = sympy.Matrix([E])
# 解方程
A = sympy.Matrix([[M_A, M_B], [M_C, M_D], [M_E]])
fx_delta_Li = []
fx_sigma_i1 = []
for i in range(span_count):
fx_delta_Li.append(
val_delta_li[i]
- main.delta_li(
h_array[i],
l_array[i],
lambda_i_array[i],
alpha_data,
elastic_data,
2020-12-13 16:57:48 +08:00
t_e_data,
t_data,
val_sigma_i[i],
lambda_m_data,
t_m_data,
sigma_m_data,
)
)
if i < span_count - 1:
fx_sigma_i1.append(
val_sigma_i[i + 1]
- main.fun_sigma_i1(
area_data,
2020-12-13 16:57:48 +08:00
val_sigma_i[i],
math.fsum(val_delta_li[0 : i + 1]),
string_length,
string_g / conductor_n,
h_array[i],
l_array[i],
lambda_i_array[i],
h_array[i + 1],
l_array[i + 1],
lambda_i_array[i + 1],
)
)
fx_sum_Li = [math.fsum(val_delta_li)]
b_list = []
b_list.extend(fx_delta_Li)
b_list.extend(fx_sigma_i1)
b_list.extend(fx_sum_Li)
AA = np.array(A.tolist(), dtype=np.float64)
2020-12-14 16:05:17 +08:00
b = np.array(b_list, dtype=np.float64)
x = np.linalg.solve(-AA, b)
x_list = x
# 强制要求等式满足
abs_min: List[float] = [
math.fabs(_x) for _x in [*x_list, *fx_delta_Li, *fx_sigma_i1]
]
2020-12-13 16:57:48 +08:00
abs_min.sort()
if abs_min[-1] < 1e-5:
2020-12-13 16:57:48 +08:00
break
2022-08-22 16:09:08 +08:00
# print("最大偏差{max_dx}".format(max_dx=abs_min[-1]))
2020-12-13 16:57:48 +08:00
# 更新变量
for i in range(span_count):
val_delta_li[i] += x_list[i]
val_sigma_i[i] += x_list[i + span_count]
if loop >= loop_end:
print("不收敛")
else:
2020-12-14 16:05:17 +08:00
print("经过{loop}次迭代收敛,最大偏差{bias}".format(loop=loop, bias=abs_min[-1]))
# print(val_delta_li)
# print(val_sigma_i)
verify(val_delta_li, val_sigma_i)
2022-08-22 16:09:08 +08:00
endtime = datetime.datetime.now()
# print('执行时间{t}'.format(t=(endtime-starttime).microseconds/1000))
pass
def verify(val_delta_li, val_sigma_i):
main.verify(
area_data,
h_array,
l_array,
string_length,
string_g / conductor_n,
val_sigma_i,
val_delta_li,
lambda_i_array,
t_data,
alpha_data,
elastic_data,
t_e_data,
lambda_m_data,
t_m_data,
sigma_m_data,
1e-5,
)
2020-12-13 16:57:48 +08:00
solve()
2020-12-13 16:57:48 +08:00
print("Finished.")