Update TO_Cal.py
This commit is contained in:
parent
976d2cb704
commit
fdc33b608c
|
@ -1,14 +1,15 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Created on Thu Apr 23 15:08:01 2020
|
||||
|
||||
@author: zzy
|
||||
|
||||
Object: 存储TO计算过程所需的函数
|
||||
1. 所有函数均可jit
|
||||
2. 在调用时 选择在最外层封装jit 内层函数则将jit注释
|
||||
3. 对于部分确定的static variable 应采用numpy定义(仅限CPU)
|
||||
"""
|
||||
'''
|
||||
@ Copyright (c) 2022 by Zeyu Zhang, All Rights Reserved.
|
||||
@ Author : Zeyu Zhang
|
||||
@ Email : zhangzeyu_work@outlook.com
|
||||
@ Date : 2021-11-17 10:52:26
|
||||
@ LastEditTime : 2022-10-25 09:33:11
|
||||
@ FilePath : /ZZY_CODE/Env_JAX/IDRL/Linear_TO/TO_Cal.py
|
||||
@
|
||||
@ Description : 存储TO计算过程所需的函数
|
||||
@ Reference :
|
||||
'''
|
||||
|
||||
import numpy as np
|
||||
import jax
|
||||
|
@ -26,90 +27,28 @@ config.update("jax_enable_x64", True)
|
|||
|
||||
@partial(jax.jit, static_argnums=(5, 6, 7))
|
||||
def design_variable(x, design_area_indices, nondesign_area_indices, filter_kernal, filter_weight, beta_x, volfrac, projection=False):
|
||||
"""
|
||||
Parameters
|
||||
----------
|
||||
x : shape:[nely, nelx](2D) 经过reshape的NN输出
|
||||
design_area_indices : 设计域的单元编号索引
|
||||
nondesign_area_indices : 非设计域的单元编号索引
|
||||
filter_kernal : TOP88中的H 卷积过滤中的卷积核 计算影响域内每一个单元的权重
|
||||
filter_weight : TOP88中的HS 设计域内每一个单元的总权重 与网格划分同维度
|
||||
beta_x : Projection参数
|
||||
volfrac : 目标体积
|
||||
projection : 是否采用Projection
|
||||
|
||||
Returns
|
||||
-------
|
||||
xPhys_1D : shape:[Total_ele](1D) 参与有限元计算的单元相对密度阵
|
||||
"""
|
||||
|
||||
# density filtering 用在了转换之前 目前看也是有效果的
|
||||
x = filter(x, filter_kernal, filter_weight)
|
||||
x_1D = x.flatten(order='F')
|
||||
x_designed = design_and_volume_constraints(
|
||||
x_1D[design_area_indices], volfrac, beta_x)
|
||||
xPhys_1D = matrix_set_0(
|
||||
x_designed, design_area_indices, nondesign_area_indices)
|
||||
# 直接等于xPhys_1D 但尚需要在真实存在非设计域时验证
|
||||
# 原始方案
|
||||
# x_in = x[design_map_bool]
|
||||
# x_designed = design_and_volume_constraints(x_in, volfrac, beta_x) # x[design_map_bool]内含了一步matrix.flatten()
|
||||
# x_flat = matrix_set_0(x_designed, jnp.flatnonzero(design_map_bool, size=num_design_ele), Total_ele, num_nondesign_ele)
|
||||
# 因为x_designed内含flatten() 所以这里对应要复原 由于flatten时没有传入order='F' 这里也不能传入
|
||||
# xPhys = x_flat.reshape(x.shape)
|
||||
return xPhys_1D
|
||||
|
||||
|
||||
def projection(x, beta_TONR):
|
||||
"""
|
||||
实现projection 将[-z, z]的数值映射至(0, 1)
|
||||
目前
|
||||
原理 tanh能够将元素映射至(-1, 1) 因此 tanh_out * 0.5 + 0.5可以映射至(0, 1)
|
||||
注意 sigmoid(x) = 0.5 * tanh(0.5 * x) + 0.5
|
||||
Parameters
|
||||
----------
|
||||
x : 待映射的矩阵
|
||||
beta_TONR : projection函数斜率的控制参数
|
||||
|
||||
Returns
|
||||
-------
|
||||
output : sigmoid/projection变换后的矩阵
|
||||
"""
|
||||
output = jnp.tanh(beta_TONR * 0.5 * x)*.5 + 0.5
|
||||
return output
|
||||
|
||||
|
||||
def logit(obj_V):
|
||||
"""
|
||||
根据obj_V确定sigmoid分母部分e ** (x-b)中 b搜索的初始上下界
|
||||
np.clip(a, a_min, a_max) 将a的取值截断在(a_min, a_max)内
|
||||
Parameters
|
||||
----------
|
||||
obj_V : 目标体积
|
||||
|
||||
Returns
|
||||
-------
|
||||
"""
|
||||
p = jnp.clip(
|
||||
obj_V, 0, 1)
|
||||
return jnp.log(p) - jnp.log1p(-p) # p从-inf到inf p取0.5为0 以0.5为界限 大于小于符号相反 数值相同
|
||||
return jnp.log(p) - jnp.log1p(-p)
|
||||
|
||||
|
||||
# @partial(jax.jit, static_argnums=(1, 2))
|
||||
def design_and_volume_constraints(x, obj_V, beta_TONR):
|
||||
"""
|
||||
用来将神经网络的输出转化为满足设计约束 体积约束和projection的用于有限元计算的单元密度
|
||||
x_design = 1/(1 + e ** (x - b(x, obj_V)))
|
||||
Parameters
|
||||
----------
|
||||
x : 经过密度过滤后的单元相对密度阵
|
||||
obj_V : 目标体积.
|
||||
beta_TONR : Projection参数
|
||||
|
||||
Returns
|
||||
-------
|
||||
x_design : 满足设计约束和体积约束的相对密度 向量形式
|
||||
"""
|
||||
def find_yita(y, x, beta):
|
||||
projection_out = projection(x + y, beta)
|
||||
volume_diff = jnp.mean(projection_out) - obj_V
|
||||
|
@ -118,28 +57,12 @@ def design_and_volume_constraints(x, obj_V, beta_TONR):
|
|||
upper_bound = logit(obj_V) - jl.stop_gradient(np.min(x))
|
||||
bisec = Bisection(optimality_fun=find_yita, lower=lower_bound, upper=upper_bound, tol=1e-12, maxiter=64, check_bracket=False)
|
||||
yita = bisec.run(x=x, beta=beta_TONR).params
|
||||
# yita = TPA.binary_search(find_yita, x, beta_TONR, lower_bound, upper_bound) # 自编二分法
|
||||
# 用来搜索yita的取值 由二分法获得 本质上这里和保体积projection搜索yita的过程完全相同
|
||||
# 实验和公式表明 在保体积projection和此处添加体积约束的sigmoid中 对yita的求解均是一个关于(x, obj_V)的函数
|
||||
# 其敏度必然要考虑
|
||||
x_design = projection(x + yita, beta_TONR)
|
||||
x_design = x_design + 0.00001
|
||||
return x_design
|
||||
|
||||
|
||||
def filter_define(design_map, filter_width):
|
||||
"""
|
||||
定义TO中过滤器的卷积核 权重等参数
|
||||
Parameters
|
||||
----------
|
||||
design_map : 设计域和非设计域定义矩阵
|
||||
filter_width : 过滤半径
|
||||
|
||||
Returns
|
||||
-------
|
||||
filter_kernal : TOP88中的H 卷积过滤中的卷积核 计算影响域内每一个单元的权重
|
||||
filter_weight : TOP88中的HS 设计域内每一个单元的总权重 与网格划分同维度
|
||||
"""
|
||||
dy, dx = jnp.meshgrid(jnp.arange(-jnp.ceil(filter_width)+1, jnp.ceil(filter_width)),
|
||||
jnp.arange(-jnp.ceil(filter_width)+1, jnp.ceil(filter_width)))
|
||||
filter_kernal = jnp.maximum(0, filter_width - jnp.sqrt(dx ** 2 + dy ** 2))
|
||||
|
@ -149,17 +72,6 @@ def filter_define(design_map, filter_width):
|
|||
|
||||
# @jax.jit
|
||||
def filter(matrixA, filter_kernal, filter_weight):
|
||||
"""
|
||||
Parameters
|
||||
----------
|
||||
matrixA : 待过滤的矩阵
|
||||
filter_kernal : TOP88中的H 卷积过滤中的卷积核 计算影响域内每一个单元的权重
|
||||
filter_weight : TOP88中的HS 设计域内每一个单元的总权重 与网格划分同维度
|
||||
|
||||
Returns
|
||||
-------
|
||||
new_matrix : 过滤后的矩阵
|
||||
"""
|
||||
new_matrix = jss.convolve2d(matrixA, filter_kernal, 'same') / filter_weight
|
||||
return new_matrix
|
||||
|
||||
|
@ -173,24 +85,6 @@ def inverse_permutation(indices):
|
|||
|
||||
# @jax.jit
|
||||
def matrix_set_0(nonzero_values, nonzero_indices, zero_indices):
|
||||
"""
|
||||
补齐矩阵 对原始矩阵指定区域置0 可用于非设计域进行置0 以及节点位移添加指定节点的位移
|
||||
Parameters
|
||||
----------
|
||||
nonzero_values : 已存在数值的矩阵 如设计域的相对密度阵 freedofs对应的节点位移
|
||||
nonzero_indices : size=存在数值的个数 已存在数值矩阵对应的索引编号 如设计域对应的索引
|
||||
注意 这里为根据design_map自动生成的 是基于行展开编号的 仅用于此处计算 并非真正TO中的单元编号
|
||||
zero_indices : 矩阵中未存在数值的单元对应的索引编号
|
||||
origin_matrix_size : 原始矩阵元素个数 即包含设计域和非设计域
|
||||
zero_size : 矩阵中0元素的个数 代表非设计域的单元个数
|
||||
|
||||
Returns
|
||||
-------
|
||||
new_matrix : 补齐后的矩阵
|
||||
"""
|
||||
# all_indices = np.arange(origin_matrix_size, dtype=jnp.int64)
|
||||
# zero_indices = jnp.setdiff1d(
|
||||
# all_indices, nonzero_indices, size=zero_size, assume_unique=True) # setdiff1d通常不支持jit 需要指定size
|
||||
index_map = inverse_permutation(
|
||||
jnp.concatenate([nonzero_indices, zero_indices]))
|
||||
u_values = jnp.concatenate([nonzero_values, jnp.zeros(len(zero_indices))])
|
||||
|
@ -200,19 +94,6 @@ def matrix_set_0(nonzero_values, nonzero_indices, zero_indices):
|
|||
|
||||
@partial(jax.jit, static_argnums=(2, 3))
|
||||
def matrix_set_1(nonzero_values, nonzero_indices, origin_matrix_size, zero_size):
|
||||
"""
|
||||
补齐矩阵 对原始矩阵指定区域置1
|
||||
Parameters
|
||||
----------
|
||||
nonzero_values : 已存在数值的矩阵
|
||||
nonzero_indices : 已存在数值矩阵对应的索引编号
|
||||
origin_matrix_size : 原始矩阵元素个数 即包含设计域和非设计域
|
||||
zero_size : 矩阵中0元素的个数 代表非设计域的单元个数
|
||||
|
||||
Returns
|
||||
-------
|
||||
new_matrix : 补齐后的矩阵
|
||||
"""
|
||||
all_indices = jnp.arange(origin_matrix_size, dtype=jnp.int64)
|
||||
zero_indices = jnp.setdiff1d(
|
||||
all_indices, nonzero_indices, size=zero_size, assume_unique=True)
|
||||
|
@ -225,29 +106,9 @@ def matrix_set_1(nonzero_values, nonzero_indices, origin_matrix_size, zero_size)
|
|||
|
||||
@partial(jax.jit, static_argnums=(1, 2, 10))
|
||||
def objective(xPhys_1D, young, young_min, freedofs, fext, s_K_predefined, dispTD_predefined, idx, edofMat, ke, penal):
|
||||
"""
|
||||
Parameters
|
||||
----------
|
||||
xPhys_1D : shape:[Total_ele](1D) 参与有限元计算的相对密度
|
||||
young : 杨氏模量
|
||||
young_min : 弱单元的杨氏模量
|
||||
freedofs : 有限元的自由节点
|
||||
fext : Python中的1D矢量 外力
|
||||
s_K_predefined : 预定义的刚度阵
|
||||
dispTD_predefined : 预定义的位移阵
|
||||
idx : 刚度阵组装编号
|
||||
edofMat : shape:[Total_ele, 8](2D) 按照单元顺序存储每一个单元的自由度编号
|
||||
ke : 单元刚度阵 不考虑杨氏模量
|
||||
penal : 惩罚因子
|
||||
|
||||
Returns
|
||||
-------
|
||||
obj : 目标函数输出 此处为结构的柔度
|
||||
"""
|
||||
# xPhys_1D = xPhys.T.flatten()
|
||||
disp = TO_FEA.FEA(young, young_min, ke, xPhys_1D, freedofs,
|
||||
penal, idx, fext, s_K_predefined, dispTD_predefined)
|
||||
obj = TO_Obj.compliance(young, young_min, ke,
|
||||
xPhys_1D, edofMat, penal, disp)
|
||||
# print('obj is running')
|
||||
return obj
|
Loading…
Reference in New Issue