如何在NonlinearSolve.jl中仅求解对称非线性问题的半解以节省计算量?
利用NonlinearSolve.jl通过对称性减半求解椭圆非线性问题
你的代码求解的椭圆非线性问题具有中心对称解(前半部分与后半部分镜像相等),要节省计算时间,只需求解解的一半,再通过对称性还原完整解,具体实现如下:
核心思路
原问题变量长度为N+1=16,解的第i个元素与第17-i个元素相等。我们可以:
- 仅求解前
8个变量(即总长度的上半部分) - 构造适配半变量的残差函数,将对称关系代入原方程,只保留前半部分的残差计算
- 求解完成后,通过对称扩展得到完整解
修改后的代码
using NonlinearSolve, LinearAlgebra, Plots # 参数: p = [h, ω] N = 15 full_len = N + 1 # 原变量总长度16 half_len = (full_len + 1) ÷ 2 # 需求解的半长度:8 # 对称扩展函数:从半长度变量生成完整对称解 extend_sym(u_half) = vcat(u_half, reverse(u_half[1:end-1])) # 适配半变量的残差函数 function g_half(u_half, p) # 先扩展成全长度变量 u_full = extend_sym(u_half) # 计算原问题的完整残差 res_full = p[1] * Tridiagonal(fill(1, N), fill(-2, full_len), fill(1, N)) * u_full - u_full.^3 - p[2] * u_full # 仅返回前半部分残差,对应需要求解的变量 return res_full[1:half_len] end # 初始猜测取原初始值的前半部分,保持对称结构 u0_half = fill(0.3, half_len) probg_half = NonlinearProblem{false}(g_half, u0_half, [0.6, -0.4]) # 求解半维度问题 solver_half = solve(probg_half, NewtonRaphson(), reltol=1e-9) # 扩展得到完整对称解 u_full_sol = extend_sym(solver_half.u) println(u_full_sol)
关键说明
extend_sym函数:将半长度解扩展为完整解,前8个元素保留原半解,后7个元素是前7个元素的逆序,严格匹配原问题的对称结构- 残差函数
g_half:先通过对称扩展得到全变量,计算原残差后只保留前半部分,让求解器仅处理一半维度的变量,大幅降低计算量 - 初始猜测:对应取原初始值的前半部分,保证初始结构对称,帮助求解器快速收敛
内容的提问来源于stack exchange,提问作者KZ-Spectra
相关产品推荐
相关产品推荐

