You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

LTSpice压敏电阻参数拟合问题:minimize算法无法输出正确结果

压敏电阻仿真参数优化问题

我编写了脚本,以9个随机参数为初始值,填入LTSpice的.asc配置文件进行压敏电阻(Varistor)仿真,将仿真结果传入scipy minimize函数迭代优化,最终将优化结果与实测数据对比绘图。脚本运行正常,但minimize始终无法输出正确结果,仅随初始参数的调整接近或偏离目标值,且无法计算出准确的初始参数。目前已尝试更换优化方法、调整初始参数,但问题仍未解决,相关实现代码如下:

import PyLTSpice as lt
from PyLTSpice.LTSpice_RawRead import RawRead
import matplotlib.pyplot as plt
import openpyxl
import numpy as np
import lmfit as lm
from sklearn.metrics import mean_squared_error as mse
from scipy.stats import linregress

sheet1_row = []
sheet2_row = []

def getInput(string, default):
    #val = input(string)
    return default
    if val != "":
        return val
    else:
        return default

def createWorkbook(path):
    return 

def getData(worksheet, productcode, productmode):
    data = []
    rows = worksheet.max_row
    cols = worksheet.max_column
    for j in range(1, rows):
        if worksheet.cell(row = j, column = 3).value == productcode and worksheet.cell(row = j, column = 4).value == productmode:
            for i in range(5, cols):
                if worksheet.cell(row = j, column = i).value is not None:
                    data.append(float(worksheet.cell(row = j, column = i).value))
            break

    if data == []:
        print("Product not found")
    return data

global_voltage = []

def array_to_string():
    string = ""

    for nbr in global_voltage:
        string = string + str(nbr) + " "
    return string

def inputRonRoff(output_filename, a1, a2, a3, a4, a5, a6, a7, a8,a9):
    file = open(r"./res/D_ideal_3.asc", 'r').read()
    new_file = (file.replace("Ron=a1", f"Ron={a1}")
    .replace("Roff=a2", f"Roff={a2}")
    .replace("Vfwd=a3", f"Vfwd={a3}")
    .replace("Vrev=a4", f"Vrev={a4}")
    .replace("Ilimit=a5", f"Ilimit={a5}")
    .replace("RevIlimit=a6", f"RevIlimit={a6}")
    .replace("Epsilon=a7", f"Epsilon={a7}")
    .replace("RevEpsilon=a8", f"RevEpsilon={a8}")
    .replace("Rrev=a9", f"Rrev={a9}")
    .replace("1 2 3 4 5 6 7 8 9", array_to_string()))
    print("String is " + array_to_string()) 
    output_filepath = "./" + output_filename + ".asc"
    open(output_filepath, 'w').write(new_file)

def Simulation(filename):
    filepath = "./" + filename + ".asc"
    sim = lt.SimCommander(filepath)
    sim.run()
    sim.wait_completion()
    
def Get_Results_From_Raw(output_filename):
    raw_filepath = "./" + output_filename + "_1.raw" # or + 
    print(raw_filepath)
    raw = RawRead(raw_filepath)
    voltage = raw.get_trace("V(n001)").data #v1
    current = raw.get_trace("I(D1)").data
    return voltage, current

def run_simulation(r1, r2, r3, r4, r5, r6, r7, r8,r9):
    output_filename = "test"
    inputRonRoff(output_filename, r1, r2, r3, r4, r5, r6, r7, r8,r9)
    Simulation(output_filename)
    return 
    
def calculate_loss(v_params, meas_current):
    r1 = v_params["r1"].value
    r2 = v_params["r2"].value
    r3 = v_params["r3"].value
    r4 = v_params["r4"].value
    r5 = v_params["r5"].value
    r6 = v_params["r6"].value
    r7 = v_params["r7"].value
    r8 = v_params["r8"].value
    r9 = v_params["r9"].value
    run_simulation(np.log(r1), np.log(r2), np.log(r3), np.log(r4), np.log(r5), np.log(r6), np.log(r7), np.log(r8), np.log(r9))
    calc_voltage, calc_current = Get_Results_From_Raw("test")
    loss = mse(meas_current, calc_current)
    return loss

#sperdoret
def init_parameters():
    v_params_init = [1,1,1,1,1,1,1,1,1]
    r1i,r2i,r3i,r4i,r5i,r6i,r7i,r8i,r9i = v_params_init
    return [r1i,r2i,r3i,r4i,r5i,r6i,r7i,r8i,r9i]

def init_minimizer(r1i,r2i,r3i,r4i,r5i,r6i,r7i,r8i,r9i):
    v_params = lm.Parameters()
    v_params["r1"] = lm.Parameter(name="r1", value=r1i, min=1e-5, max=1, vary=True)
    v_params["r2"] = lm.Parameter(name="r2", value=r2i, min=3, max=3e5, vary=False)
    v_params["r3"] = lm.Parameter(name="r3", value=r3i, min=36, max=100, vary=False)
    v_params["r4"] = lm.Parameter(name="r4", value=r4i, min=-1, max=-36, vary=False)
    v_params["r5"] = lm.Parameter(name="r5", value=r5i, min=-1e24, max=1e24, vary=True)
    v_params["r6"] = lm.Parameter(name="r6", value=r6i, min=-1e24, max=1e24, vary=True)
    v_params["r7"] = lm.Parameter(name="r7", value=r7i, min=-1e24, max=1e24, vary=False)
    v_params["r8"] = lm.Parameter(name="r8", value=r8i, min=-1e24, max=1e24, vary=False)
    v_params["r9"] = lm.Parameter(name="r9", value=r9i, min=1e1, max=1e5, vary=True)
    return v_params
    
def solver(v_params, meas_current, meas_voltage):    
    result = lm.Minimizer(calculate_loss, v_params, fcn_args=([meas_current])).minimize(method='least_squares')
    return result

def solver_result(result):
    r1 = float('{:.3e}'.format(((result.params["r1"].value))))
    r2 = float('{:.3e}'.format(((result.params["r2"].value))))
    r3 = float('{:.3e}'.format(((result.params["r3"].value))))
    r4 = float('{:.3e}'.format(((result.params["r4"].value))))
    r5 = float('{:.3e}'.format(((result.params["r5"].value))))
    r6 = float('{:.3e}'.format(((result.params["r6"].value))))
    r7 = float('{:.3e}'.format(((result.params["r7"].value))))
    r8 = float('{:.3e}'.format(((result.params["r8"].value))))
    r9 = float('{:.3e}'.format(((result.params["r9"].value))))

    print("r1 is " + str(r1))
    print("r2 is " + str(r2))
    print("r3 is " + str(r3))
    print("r4 is " + str(r4))
    print("r5 is " + str(r5))
    print("r6 is " + str(r6))
    print("r7 is " + str(r7))
    print("r8 is " + str(r8))
    print("r9 is " + str(r9))

    run_simulation(r1, r2, r3, r4, r5, r6, r7, r8,r9)
    calc_voltage, calc_current = Get_Results_From_Raw("test")
    
    return calc_voltage, calc_current


def plot_result(c, v, current, voltage):
    plt.loglog()
    plt.plot(c, v, color="red", label="Final Result") # output is red
    plt.plot(current, voltage, color="blue", label="Sample")
    plt.xlabel("Voltage")
    plt.ylabel("Current")
    plt.legend(loc="upper left")
    plt.show()

def calc_Ron(current, voltage):
    delta_current = current[1] - current[0]
    delta_voltage = voltage[1] - voltage[0]
    Ron = delta_voltage / delta_current if delta_current != 0 else 1
    return Ron

def calc_Roff(current, voltage):
    delta_current = current[1] - current[0]
    delta_voltage = voltage[1] - voltage[0]
    return (delta_voltage / delta_current)

def calc_Vfwd(current, voltage):
    return voltage[5]

#MAIN FUNCTION
def main():
    #productcode = getInput("Enter Product Code: ", "820412001")820413001
    productcode = getInput("Enter Product Code: ", "820412001")
    productmode = getInput("Enter Product Mode: ", "combined")
    workbook = openpyxl.load_workbook("./Varistors.xlsx", data_only=True)
    current = getData(workbook.worksheets[1], productcode, productmode)
    voltage = getData(workbook.worksheets[2], productcode, productmode)
    global global_voltage
    global_voltage = voltage
    result = solver( init_minimizer(calc_Ron(current, voltage),
                                    calc_Roff(current, voltage),
                                    36.3, 
                                    -29.7, 0, 0, 0.01, 0.01, 2.5e4), current, voltage)
    v, c = solver_result(result)
    plot_result(c, v, current, voltage)

if __name__ == "__main__":
    main()

附上对比曲线图:
仿真结果与实测数据对比图

内容的提问来源于stack exchange,提问作者itnera

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 17:03:10