numpy向量加一个常数=向量中的每个值加上这个常数,最后返回一个同维的向量

import numpy as np
x=[[-0.60116],
 [-0.94159],
 [-0.74565],
 [ 0.89583]]
w = [0]
b=1
z= np.matmul(x,w) + b

print(z)

#结果

[1. 1. 1. 1.]
import numpy as np import matplotlib.pyplot as plt from scipy.sparse import diags from scipy.sparse.linalg import spsolve import matplotlib.colors as colors from matplotlib.widgets import Slider, Button from matplotlib.patches import Rectangle import time class NMOSIonDiffusionSimulator: def __init__(self): # 物理参数设置 self.D0 = 5e-15 # 基础扩散系数 (m²/s) self.activation_energy = 1.2 # 激活能量 (eV) self.dose = 1e20 # 注入剂量 (ions/cm²) self.Rp = 100e-9 # 投影射程 (100 nm) self.ΔRp = 30e-9 # 投影射程偏差 (30 nm) self.substrate_temp = 1000 # 基底温度 (K) # 数模拟参数 self.depth = 500e-9 # 模拟深度 (500 nm) self.dz = 1e-9 # 空间步长 (1 nm) self.dt = 0.1 # 时间步长 (0.1 s) self.simulation_time = 3600 # 总模拟时间 (3600 s = 1小时) # 计算网格 self.z = np.arange(0, self.depth, self.dz) self.nz = len(self.z) self.nt = int(self.simulation_time / self.dt) # 初始化离子浓度(高斯分布) self.C = self.dose * np.exp(-(self.z - self.Rp) ** 2 / (2 * self.ΔRp ** 2)) # 结果存储 self.time_points = [] self.concentration_profiles = [] # 热力学参数 self.k_boltzmann = 8.617333e-5 # 玻尔兹曼常数 (eV/K) # 计算温度依赖的扩散系数 self.D = self.D0 * np.exp(-self.activation_energy / (self.k_boltzmann * self.substrate_temp)) print(f"计算扩散系数: {self.D:.2e} m²/s") # 设置扩散矩阵 self.setup_diffusion_matrix() def setup_diffusion_matrix(self): """设置用于求解扩散方程的系数矩阵(隐式格式)""" r = self.D * self.dt / self.dz ** 2 # 创建三对角矩阵 diagonals = [ -r * np.ones(self.nz - 1), # 下对角线 (1 + 2 * r) * np.ones(self.nz), # 主对角线 -r * np.ones(self.nz - 1) # 上对角线 ] offsets = [-1, 0, 1] # 创建稀疏矩阵 self.A = diags(diagonals, offsets, shape=(self.nz, self.nz), format='csc') # 边界条件(表面无扩散) self.A[0, 0] = 1 self.A[0, 1] = 0 self.A[-1, -1] = 1 self.A[-1, -2] = 0 def solve_diffusion(self): """求解扩散方程""" self.time_points = [] self.concentration_profiles = [self.C.copy()] current_C = self.C.copy() start_time = time.time() for t in range(self.nt): # 创建右侧向量 b = current_C.copy() b[0] = 0 # 表面边界条件:浓度固定为0 b[-1] = 0 # 底部边界条件:浓度固定为0 # 求解线性系统 new_C = spsolve(self.A, b) # 更新浓度 current_C = new_C # 每10秒保存一次结果 # 保存结果时时记录时间点 if t % 100 == 0: current_time = t * self.dt self.time_points.append(current_time) # 时保存时间点 self.concentration_profiles.append(new_C.copy()) end_time = time.time() print(f"扩散模拟完成! 耗时: {end_time - start_time:.2f} 秒") print(f"存储了 {len(self.concentration_profiles)} 个时间点的浓度分布") def draw_nmos_structure(self, ax): """绘制NMOS器件结构示意图""" # 清除原有内容 ax.clear() # 绘制衬底 substrate = plt.Rectangle((0, 0), 100, 40, facecolor='sandybrown', alpha=0.6) ax.add_patch(substrate) # 绘制栅氧化层 gate_oxide = plt.Rectangle((30, 40), 40, 5, facecolor='gray', alpha=0.7) ax.add_patch(gate_oxide) # 绘制多晶硅栅极 gate = plt.Rectangle((35, 45), 30, 10, facecolor='silver', alpha=0.8) ax.add_patch(gate) # 绘制源极 source = plt.Rectangle((10, 40), 15, 15, facecolor='blue', alpha=0.5) ax.add_patch(source) # 绘制漏极 drain = plt.Rectangle((75, 40), 15, 15, facecolor='blue', alpha=0.5) ax.add_patch(drain) # 添文本标签 ax.text(15, 47, "Source", fontsize=10, ha='center') ax.text(85, 47, "Drain", fontsize=10, ha='center') ax.text(50, 50, "Gate", fontsize=10, ha='center') ax.text(50, 20, "Substrate", fontsize=10, ha='center') # 设置坐标范围 ax.set_xlim(0, 100) ax.set_ylim(0, 60) ax.set_aspect('equal') ax.axis('off') # 隐藏坐标轴 # 添标题 ax.set_title('NMOS Device Structure', fontsize=12) def interactive_visualization(self): """创建交互式可视化界面""" # 创建更大的图形,包含三个子图 fig = plt.figure(figsize=(16, 10)) gs = fig.add_gridspec(2, 2, width_ratios=[2, 1], height_ratios=[1, 1]) # 创建三个轴 ax1 = fig.add_subplot(gs[0, 0]) # 浓度深度曲线 ax2 = fig.add_subplot(gs[1, 0]) # 时间热图 ax3 = fig.add_subplot(gs[:, 1]) # NMOS器件图 plt.subplots_adjust(bottom=0.15, left=0.1, right=0.95, top=0.95, hspace=0.3, wspace=0.2) # 绘制初始器件结构 self.draw_nmos_structure(ax3) # 在器件图中添扩散效果可视化 diffusion_line = ax3.axvline(x=50, ymin=0.67, ymax=1.0, color='red', linewidth=3, alpha=0.7, visible=False) diffusion_text = ax3.text(50, 55, '', fontsize=10, ha='center', bbox=dict(facecolor='white', alpha=0.7)) # 主图设置 ax1.set_title('Ion Concentration Profile', fontsize=14) ax1.set_xlabel('Depth from Surface (nm)', fontsize=12) ax1.set_ylabel('Ion Concentration (ions/cm³)', fontsize=12) ax1.grid(True) # 转换为nm单位 z_nm = self.z * 1e9 # 绘制初始浓度分布 line, = ax1.plot(z_nm, self.concentration_profiles[0], 'b-', lw=2) # 添浓度标签 text = ax1.text(0.05, 0.95, '', transform=ax1.transAxes, bbox=dict(facecolor='white', alpha=0.8)) # 添深度标记 depth_line = ax1.axvline(x=0, color='r', linestyle='--', alpha=0) depth_text = ax1.text(0.05, 0.85, '', transform=ax1.transAxes, bbox=dict(facecolor='white', alpha=0.8)) # 创建时间滑块 ax_time = plt.axes([0.25, 0.05, 0.5, 0.03]) time_slider = Slider( ax_time, 'Time (s)', 0, self.simulation_time, valinit=0, valstep=self.dt * 100 ) # 在下方创建热图 time_arr = np.array(self.time_points) # 时间点数组形状 conc_arr = np.array(self.concentration_profiles).T # 确保度匹配 print(f"时间点数组形状: {time_arr.shape}") # 应该是 (361,) print(f"浓度数组形状: {conc_arr.shape}") # 应该是 (500, 361) # 创建网格坐标 - 确保使用正确的度 Z_nm = self.z * 1e9 # 深度转换为nm T, Z = np.meshgrid(time_arr, Z_nm) # 对浓度取对数以更好显示 log_conc = np.log10(conc_arr + 1e10) # 加上避免log(0) # 创建更全面的热图显示 fig = plt.figure(figsize=(16, 12)) # 增图形大小 gs = fig.add_gridspec(3, 2, width_ratios=[2, 1], height_ratios=[1, 1, 0.2]) # 创建四个轴 (增一个颜色条专用轴) ax1 = fig.add_subplot(gs[0, 0]) # 浓度深度曲线 ax2 = fig.add_subplot(gs[1, 0]) # 时间热图 cax = fig.add_subplot(gs[2, 0]) # 颜色条专用轴 ax3 = fig.add_subplot(gs[:, 1]) # NMOS器件图 # 创建热图 # 改进2: 使用更有表现力的颜色映射和归一化 norm = colors.LogNorm(vmin=1e15, vmax=conc_arr.max()) im = ax2.pcolormesh(T, Z, conc_arr, shading='auto', cmap='viridis', norm=norm) # 使用Viridis颜色映射 # 添更全面的颜色条 cbar = fig.colorbar(im, cax=cax, orientation='horizontal') cbar.set_label('Ion Concentration (ions/cm³)', fontsize=10) cax.xaxis.set_ticks_position('top') cax.xaxis.set_label_position('top') # 添线增强可读性 # X, Y = np.meshgrid(time_arr, self.z * 1e9) levels = np.logspace(np.log10(1e16), np.log10(conc_arr.max()), 10) ax2.contour(T, Z, conc_arr, levels=levels, colors='white', alpha=0.3, linewidths=0.5) # 添时间标记线 time_line = ax2.axvline(x=0, color='cyan', linewidth=2, alpha=0.7) time_text = ax2.text(0.05, 0.95, '', transform=ax2.transAxes, bbox=dict(facecolor='white', alpha=0.8)) # ❓要删吗 # ax2.set_title('Concentration Evolution Over Time', fontsize=14) # ax2.set_xlabel('Time (s)', fontsize=12) # ax2.set_ylabel('Depth (nm)', fontsize=12) # 添颜色条 # cbar = fig.colorbar(im, ax=ax2) # cbar.set_label('log10(Concentration) (ions/cm³)', fontsize=10) # 添时间标记线 # time_line = ax2.axvline(x=0, color='cyan', linewidth=2, alpha=0.7) # time_text = ax2.text(0.05, 0.95, '', transform=ax2.transAxes, # bbox=dict(facecolor='white', alpha=0.8)) # 添半导体结构示意图 # gate_oxide = Rectangle((0.7, 0.05), 0.2, 0.1, transform=fig.transFigure, # facecolor='gray', alpha=0.5) # source = Rectangle((0.6, 0.05), 0.1, 0.1, transform=fig.transFigure, # facecolor='blue', alpha=0.3) # drain = Rectangle((0.9, 0.05), 0.1, 0.1, transform=fig.transFigure, # facecolor='blue', alpha=0.3) # substrate = Rectangle((0.6, 0), 0.4, 0.05, transform=fig.transFigure, # facecolor='sandybrown', alpha=0.5) # # fig.patches.extend([gate_oxide, source, drain, substrate]) # # # 添文本标签 # fig.text(0.75, 0.13, 'Gate Oxide', ha='center') # fig.text(0.65, 0.13, 'Source', ha='center') # fig.text(0.95, 0.13, 'Drain', ha='center') # fig.text(0.8, 0.025, 'Substrate', ha='center') # 浓度分布更新函数 def update(val): time_val = time_slider.val idx = min(int(time_val / (self.dt * 100)), len(self.concentration_profiles) - 1) # 更新浓度曲线 line.set_ydata(self.concentration_profiles[idx]) text.set_text( f'Time: {time_val:.1f} s\nMax Concentration: {self.concentration_profiles[idx].max():.2e} ions/cm³') # 更新热图时间线 time_line.set_xdata([time_val, time_val]) time_text.set_text(f"Time: {time_val:.1f} s") # 更新器件图中的扩散效果 - 显示扩散深度 # 计算最大浓度的深度位置 max_conc_idx = np.argmax(self.concentration_profiles[idx]) max_conc_depth = z_nm[max_conc_idx] # 计算扩散深度(浓度降至最大浓度1%的深度) threshold = self.concentration_profiles[idx].max() * 0.01 above_threshold = np.where(self.concentration_profiles[idx] > threshold)[0] if above_threshold.size > 0: diffusion_depth = z_nm[above_threshold[-1]] else: diffusion_depth = 0 # 更新扩散线位置和文本 # 计算在器件图中的扩散深度(像素高度) # 500nm对应40像素(衬底高度) h_pixels = (diffusion_depth * 40) / 500 # 清除之前的扩散区域 for patch in ax3.patches: if patch.get_facecolor() == (1., 0., 0., 0.3): patch.remove() # 创建渐变扩散效果(多个矩形叠) if diffusion_depth > 0: # 创建5个渐变矩形 steps = 5 for i in range(steps): step_depth = h_pixels * (i + 1) / steps alpha = 0.3 * (1 - i / steps) # 顶部透明度高,底部透明度低 diffusion_area = Rectangle( (30, 40 - step_depth), 40, step_depth, facecolor='red', alpha=alpha ) ax3.add_patch(diffusion_area) diffusion_text.set_text(f'Diffusion Depth: {diffusion_depth:.1f} nm') fig.canvas.draw_idle() time_slider.on_changed(update) # 点击事件处理 def onclick(event): if event.inaxes == ax1: depth_nm = event.xdata depth_m = depth_nm * 1e-9 # 找到时间点 time_idx = min(int(time_slider.val / (self.dt * 100)), len(self.concentration_profiles) - 1) # 找到深度对应的浓度 z_idx = int(depth_nm) # 1nm分辨率 if 0 <= z_idx < len(self.concentration_profiles[time_idx]): conc = self.concentration_profiles[time_idx][z_idx] # 更新深度线和文本 depth_line.set_xdata([depth_nm, depth_nm]) depth_line.set_alpha(1) depth_text.set_text(f'Depth: {depth_nm:.1f} nm\nConcentration: {conc:.2e} ions/cm³') # 更新热图时间线 time_line.set_xdata([time_slider.val, time_slider.val]) fig.canvas.draw_idle() fig.canvas.mpl_connect('button_press_event', onclick) # 添重置按钮 resetax = plt.axes([0.8, 0.01, 0.1, 0.04]) button = Button(resetax, 'Reset', color='lightgoldenrodyellow', hovercolor='0.975') def reset(event): time_slider.reset() # 重置器件图中的扩散效果 diffusion_line.set_visible(False) diffusion_text.set_text('') # 清除扩散区域 for patch in ax3.patches: if patch.get_facecolor() == (1., 0., 0., 0.3): patch.remove() self.draw_nmos_structure(ax3) # 重绘器件结构 fig.canvas.draw_idle() button.on_clicked(reset) # 添截图按钮(模拟电镜观察) screenshotax = plt.axes([0.65, 0.01, 0.1, 0.04]) screenshot_btn = Button(screenshotax, 'Take SEM Image', color='lightblue', hovercolor='0.975') def take_sem_image(event): """模拟电镜下观察离子浓度""" # 获取当前时间点的浓度分布 time_val = time_slider.val idx = min(int(time_val / (self.dt * 100)), len(self.concentration_profiles) - 1) # 创建新的电镜观察图 sem_fig, sem_ax = plt.subplots(figsize=(10, 6)) # 计算扩散深度 threshold = self.concentration_profiles[idx].max() * 0.01 diffusion_depth = z_nm[np.where(self.concentration_profiles[idx] > threshold)[0][-1]] # 显示离子分布 sem_ax.plot(z_nm, self.concentration_profiles[idx], 'b-', lw=2) sem_ax.axvline(x=diffusion_depth, color='r', linestyle='--', label=f'Diffusion Depth: {diffusion_depth:.1f} nm') sem_ax.set_title(f'SEM Observation at {time_val:.1f} s', fontsize=14) sem_ax.set_xlabel('Depth from Surface (nm)', fontsize=12) sem_ax.set_ylabel('Ion Concentration (ions/cm³)', fontsize=12) sem_ax.grid(True) sem_ax.legend() # 添NMOS器件示意图 sem_ax.text(0.95, 0.95, 'NMOS Structure', transform=sem_ax.transAxes, ha='right', va='top', fontsize=12, bbox=dict(facecolor='white', alpha=0.7)) plt.tight_layout() plt.show() screenshot_btn.on_clicked(take_sem_image) plt.show() def run(self): """运行完整模拟和可视化""" self.solve_diffusion() self.interactive_visualization() # 运行模拟 if __name__ == "__main__": simulator = NMOSIonDiffusionSimulator() simulator.run() 为什么报错: Traceback (most recent call last): File "D:\Users\x00708\SRAM_Classification-242终极版\test_code\ion.py", line 419, in <module> simulator.run() File "D:\Users\x00708\SRAM_Classification-242终极版\test_code\ion.py", line 413, in run self.interactive_visualization() File "D:\Users\x00708\SRAM_Classification-242终极版\test_code\ion.py", line 221, in interactive_visualization im = ax2.pcolormesh(T, Z, conc_arr, shading='auto', ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "D:\Users\x00708\SRAM_Classification\.venv\Lib\site-packages\matplotlib\__init__.py", line 1524, in inner return func( ^^^^^ File "D:\Users\x00708\SRAM_Classification\.venv\Lib\site-packages\matplotlib\axes\_axes.py", line 6528, in pcolormesh X, Y, C, shading = self._pcolorargs('pcolormesh', *args, ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "D:\Users\x00708\SRAM_Classification\.venv\Lib\site-packages\matplotlib\axes\_axes.py", line 6060, in _pcolorargs raise TypeError(f"Dimensions of C {C.shape} should" TypeError: Dimensions of C (500, 361) should be one smaller than X(360) and Y(500) while using shading='flat' see help(pcolormesh)
最新发布
11-20
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值