分子动力学中优化算法和积分算法

news2024/12/28 8:10:15

文章目录

    • 1.优化算法
      • 1.优化算法
      • 2.最速下降法
      • 3.一维搜索算法
      • 4.共轭梯度法
      • 5.多原子体系构型优化
    • 2.积分算法
      • 1.积分算法
      • 2.前向Euler算法
      • 3.Verlet算法
      • 4.Velocity Verlet算法
      • 5.Leapfrog算法
      • 6.积分算法的稳定性

1.优化算法

1.优化算法

  • 优化分为局部最优化全局最优化(网格搜索、模拟退火、遗传算法等),而凸函数的局部最优解就是全局最优解
  • 局部优化分为:
        间接法,利用目标函数的一阶或二阶导数,如最速下降法共轭梯度法牛顿法
        直接法,利用目标函数值,如坐标轮换法鲍威尔法
  • 间接法的收敛速率更高,直接法的可靠性较高
  • 分子的势能面通常是一个复杂的依赖于坐标的多维函数,需要通过优化算法计算得到分子的最优构型 E t o t a l = E ( x 1 , y 1 , z 1 , x 2 , y 2 , z 2 , . . . , x N , y N , z N ) E_{total}=E(x_{1},y_{1},z_{1},x_{2},y_{2},z_{2},...,x_{N},y_{N},z_{N}) Etotal=E(x1,y1,z1,x2,y2,z2,...,xN,yN,zN)
  • 优化算法目标是找到函数的最大值/最小值,一个系统通常有很多的局部最小值,优化将前往最近的局部最小值
  • 优化算法流程:给定初始点 x 0 x^{0} x0
        1.在迭代点 x k x^{k} xk 处,按一定规律确定搜索方向 p k p^{k} pk
        2.沿搜索方向确定适当的搜索步长 α k \alpha_{k} αk
        3.令 x k + 1 = x k + α k p k x^{k+1}=x^{k}+\alpha_{k}p^{k} xk+1=xk+αkpk
            a.若 x k + 1 x^{k+1} xk+1 满足某种终止条件,则停止迭代,得到近似最优解 x ∗ x^{*} x
            b.否则,重复以上步骤
        初始点 x 0 x^{0} x0 、搜索方向 p k p^{k} pk 、迭代步长 α k \alpha_{k} αk 称为优化算法的三要素
        其中搜索方向最为重要和突出,确定搜索方向是研究优化算法的最根本任务之一
  • 负梯度方向是函数值在该点附近的范围内下降最快的方向

2.最速下降法

  • 二次型是 n 个变量上的二次齐次多项式 f ( x ) = 1 2 x T A x − b T x + c f(x)=\frac{1}{2}x^{T}Ax-b^{T}x+c f(x)=21xTAxbTx+c     梯度表达: ∇ f ( x ) = A x − b \nabla f(x)=Ax-b f(x)=Axb
  • 二次型是除线性函数外最简单的函数,具有对称矩阵表示形式,二次型的优化是研究优化问题的基础
  • 二次型的最速下降法
        正定二次型的最优步长可以使用解析法得到 α k = a r g m i n α { φ ( α ) = f ( x k + α p k ) } \alpha_{k}=\underset{\alpha}{argmin}\{ \varphi(\alpha)=f(x^{k}+\alpha p^{k})\} αk=αargmin{φ(α)=f(xk+αpk)}     根据方向导数定义: ∇ p f = ∂ f ∂ x p x + ∂ f ∂ y p y + ∂ f ∂ z p z \nabla_{p}f=\frac{\partial f}{\partial x}p_{x}+\frac{\partial f}{\partial y}p_{y}+\frac{\partial f}{\partial z}p_{z} pf=xfpx+yfpy+zfpz f ( x ) = 1 2 x T A x − b T x + c f(x)=\frac{1}{2}x^{T}Ax-b^{T}x+c f(x)=21xTAxbTx+c     在 ( x k + α p k ) (x^{k}+\alpha p^{k}) (xk+αpk) 点沿着负梯度方向 p k p^{k} pk 的导数为: φ ′ ( α ) = ( x k + α p k ) T A p k − b T p k \varphi^{'}(\alpha)=(x^{k}+\alpha p^{k})^{T}Ap^{k}-b^{T}p^{k} φ(α)=(xk+αpk)TApkbTpk     根据极值条件, α \alpha α 使得该函数取极小值
         令 φ ′ ( α ) = 0 \varphi^{'}(\alpha)=0 φ(α)=0 ,即: α ( p k ) T A p k = − ( ( x k ) T A − b T ) p k \alpha(p^{k})^{T}Ap^{k}=-((x^{k})^{T}A-b^{T})p^{k} α(pk)TApk=((xk)TAbT)pk     而 ( x k ) T A − b T = ( − p k ) T (x^{k})^{T}A-b^{T}=(-p^{k})^{T} (xk)TAbT=(pk)T ,得最优步长 α \alpha α α = ( p k , p k ) ( A p k , p k ) \alpha=\frac{(p^{k},p^{k})}{(Ap^{k},p^{k})} α=(Apk,pk)(pk,pk)
  • Python代码实现
    def steepest_descent(x0,tol=1e-5,max_iter=1000)
        x = x0
        for i in range(max_iter):
            p = -grad_f(x)
            if np.linalg.norm(p) < tol:
                 break
            alpha = p.T @ p / (p.T @ A @ p)
            x = x + alpha * p
        return x
    
  • 最速下降法的缺点:随着迭代步的继续,搜索方向呈现震荡的行为 x k + 1 = x k + α p k x^{k+1}=x^{k}+\alpha p^{k} xk+1=xk+αpk d d α f ( x k + 1 ) = f ′ ( x k + 1 ) T d d α x k + 1 = f ′ ( x k + 1 ) T ⋅ p k ≡ 0 \frac{d}{d\alpha}f(x^{k+1})=f^{'}(x^{k+1})^{T}\frac{d}{d\alpha}x^{k+1}=f^{'}(x^{k+1})^{T}\cdot p^{k}\equiv 0 dαdf(xk+1)=f(xk+1)Tdαdxk+1=f(xk+1)Tpk0      在最速下降法中,相邻两个迭代点上的函数梯度相互垂直。而搜索方向是负梯度方向,相邻两个搜索方向互相垂直

3.一维搜索算法

  • 对于一般的函数形式,往往依赖数值解法来确定最佳步长 α k = a r g m i n α { φ ( α ) = f ( x k + α p k ) } \alpha_{k}=\underset{\alpha}{argmin}\{ \varphi(\alpha)=f(x^{k}+\alpha p^{k})\} αk=αargmin{φ(α)=f(xk+αpk)}     分类精确一维搜索(进退法、分割法、插值法)、非精确一维搜索(Backtracking-Armijo)
  • 一维搜索的步长确定
        1.确定搜索区间,使函数 f(x) 存在一个局部最小值
            a.图行方法:绘制函数图像,通过观察来估计最小值可能存在的区间
            b.分析方法:使用函数的导数或其他数学工具进行分析,以确定可能存在最小值的区间
            c.进退法(Bracketing Method):从一个初始点出发,通过增加或减小 x 的值来找到一个包含最小值的区间
        2.缩小搜索区间,确定最小值的精确位置
            a.黄金分割搜索:使用黄金比率来选点,并根据两个点的函数值来更新区间
            b.二分法:取区间的中点,然后根据中点的函数值或导数值来决定保留哪半个区间
            c.插值方法:使用插值多项式来逼近 f(x),然后选择插值多项式的最小值作为新的点
            d.牛顿法:如果函数的导数信息可用,可以使用牛顿法来快速找到最小值
  • 精确的求解每个一维子问题往往需要较大的计算量,更实际的方法是使用非精确的线搜索,以最小的代价获得使目标函数充分降低的步长
        回溯线搜索法(Armijo准则) f ( x k + α k p k ) − f ( x k ) ≤ α k β g k T p k f(x^{k}+\alpha_{k}p_{k})-f(x^{k})\le\alpha_{k}\beta g_{k}^{T}p_{k} f(xk+αkpk)f(xk)αkβgkTpk

4.共轭梯度法

  • 为避免锯齿的发生,取下一次的迭代搜索方向直接指向极小点,如果选定这样的搜索方向,对于二元二次函数只需进行两次直线搜索就可以求到极小点 x 1 = x 0 + α 0 d 0 x^{1}=x^{0}+\alpha_{0}d^{0} x1=x0+α0d0 ∂ f ∂ α ∣ x 1 = ∇ f ( x 1 ) T d 0 = 0 \frac{\partial f}{\partial \alpha}|_{x^{1}}=\nabla f(x^{1})^{T}d^{0}=0 αfx1=f(x1)Td0=0 x ∗ = x 1 + α 1 d 1 x^{*}=x^{1}+\alpha_{1}d^{1} x=x1+α1d1
  • d 1 d^{1} d1 应满足什么条件?
        对于二次函数 f(x) 在 x* 处取得极小点的必要条件 ∇ f ( x ∗ ) = A x ∗ − b = 0 \nabla f(x^{*})=Ax^{*}-b=0 f(x)=Axb=0 ∇ f ( x ∗ ) = A ( x 1 + α 1 d 1 ) − b = A x 1 − b + α 1 A d 1 \nabla f(x^{*})=A(x^{1}+\alpha_{1}d^{1})-b=Ax^{1}-b+\alpha_{1}Ad^{1} f(x)=A(x1+α1d1)b=Ax1b+α1Ad1 ∇ f ( x ∗ ) = ∇ f ( x 1 ) + α 1 A d 1 = 0 \nabla f(x^{*})=\nabla f(x^{1})+\alpha_{1}Ad^{1}=0 f(x)=f(x1)+α1Ad1=0     等式两边同乘 ( d 0 ) T (d^{0})^{T} (d0)T,得 ( d 0 ) T A d 1 = 0 (d^{0})^{T}Ad^{1}=0 (d0)TAd1=0      d 0 d^{0} d0 d 1 d^{1} d1 是对 A A A共轭方向,如果 A = I A=I A=I,则 d 0 d^{0} d0 d 1 d^{1} d1 正交
  • 共轭梯度法:共轭方向由迭代点的负梯度构造出来 f ( x ) = 1 2 x T A x − b T x + c f(x)=\frac{1}{2}x^{T}Ax-b^{T}x+c f(x)=21xTAxbTx+c     从点 x k x^{k} xk 出发,沿 A A A 某一共轭方向 d k d^{k} dk 作一维搜索,到达 x k + 1 x^{k+1} xk+1 x k + 1 = x k + α k d k x^{k+1}=x^{k}+\alpha_{k}d^{k} xk+1=xk+αkdk     而在点 x k x^{k} xk x k + 1 x^{k+1} xk+1 处的梯度分别为: g k = A x k − b g k + 1 = A x k + 1 − b g^{k}=Ax^{k}-b\quad\quad g^{k+1}=Ax^{k+1}-b gk=Axkbgk+1=Axk+1b      d 0 = − g 0 = − A x 0 + b d^{0}=-g^{0}=-Ax^{0}+b d0=g0=Ax0+b,根据一维精确搜索, ( g 1 ) T d 0 = 0 (g^{1})^{T}d^{0}=0 (g1)Td0=0
        令 d 1 = − g 1 + β 0 d 0 d^{1}=-g^{1}+\beta_{0}d^{0} d1=g1+β0d0,则 ( d 1 ) T = − ( g 1 ) T + β 0 ( d 0 ) T (d^{1})^{T}=-(g^{1})^{T}+\beta_{0}(d^{0})^{T} (d1)T=(g1)T+β0(d0)T     选择 β 0 \beta_{0} β0 使得 ( d 1 ) T A d 0 = 0 (d^{1})^{T}Ad^{0}=0 (d1)TAd0=0,上式两边同乘 A d 0 Ad^{0} Ad0,可得: ( d 1 ) T A d 0 = − ( g 1 ) T A d 0 + β 0 ( d 0 ) T A d 0 = 0 (d^{1})^{T}Ad^{0}=-(g^{1})^{T}Ad^{0}+\beta_{0}(d^{0})^{T}Ad^{0}=0 (d1)TAd0=(g1)TAd0+β0(d0)TAd0=0 β 0 = ( g 1 ) T A d 0 ( d 0 ) T A d 0 \beta_{0}=\frac{(g^{1})^{T}Ad^{0}}{(d^{0})^{T}Ad^{0}} β0=(d0)TAd0(g1)TAd0
  • 共轭梯度法流程
        1.沿 d k − 1 d^{k-1} dk1 方向一维搜索 x k = x k − 1 + α k − 1 d k − 1 x^{k}=x^{k-1}+\alpha_{k-1}d^{k-1} xk=xk1+αk1dk1     2.构筑新的共轭方向 d k = − g k + β k − 1 d k − 1 d^{k}=-g^{k}+\beta_{k-1}d^{k-1} dk=gk+βk1dk1 β k − 1 = ( g k ) T A d k − 1 ( d k − 1 ) T A d k − 1 \beta_{k-1}=\frac{(g^{k})^{T}Ad^{k-1}}{(d^{k-1})^{T}Ad^{k-1}} βk1=(dk1)TAdk1(gk)TAdk1         简化,Fletcher-Reeves公式 β k − 1 = ( g k ) T g k ( g k − 1 ) T g k − 1 \beta_{k-1}=\frac{(g^{k})^{T}g^{k}}{(g^{k-1})^{T}g^{k-1}} βk1=(gk1)Tgk1(gk)Tgk     3.沿新的共轭方向 d k − 1 d^{k-1} dk1 一维搜索 x k + 1 = x k + α k d k x^{k+1}=x^{k}+\alpha_{k}d^{k} xk+1=xk+αkdk     Shewchuk, Jonathan Richard. “An introduction to the conjugate gradient method without the agonizing pain.” (1994): 7.
  • Python代码实现
    def linear_conjugate_gradient(A,b,x0,tol=1e-5,max_iter)
    # 初始化
        x = x0; r = b - A @ x; p = r
        rsold = r.T @ r
        for i in range(max_iter)
            Ap = A @ p
            alpha = rsold / (p.T @ Ap)
            x += alpha * p
            r -= alpha * Ap 
            rsnew = r.T @ r
            # 检查收敛性
            if np.sqrt(rsnew) <  tol:
                 break  
            p = r + (rsnew / rsold) * p
            rsold = rsnew
       return x
    

5.多原子体系构型优化

  • 在原子间相互作用势的作用下,通过改变粒子的几何构型,以能量最小为依据,得到体系的最优构型
  • 约化的LJ势为例,构建一个包含5个原子的二维初始构型,使用优化算法得到能量最低构型 U ( r i j ) = 4 [ ( 1 r i j ) 12 − ( 1 r i j ) 6 ] U(r_{ij})=4[(\frac{1}{r_{ij}})^{12}-(\frac{1}{r_{ij}})^{6}] U(rij)=4[(rij1)12(rij1)6] X = ( x 1 , y 1 , x 2 , y 2 , x 3 , y 3 , x 4 , y 4 , x 5 , y 5 ) X=(x_{1},y_{1},x_{2},y_{2},x_{3},y_{3},x_{4},y_{4},x_{5},y_{5}) X=(x1,y1,x2,y2,x3,y3,x4,y4,x5,y5)
  • 定义Reduced LJ势函数
    def LJ_reduced_pot(r):
        return 4*((1.0/r)**12-(1.0/r)**6)
    
  • 定义导数
    def LJ_reduced_force(r):
        return 24*(2*(1.0/r)**12-(1.0/r)**6)/r
    
  • 生成随机构型
    def genPts(N):
        np.random.seed(10)
        pts = np.zeros(N*2)
        for i in range(N*2):
            pts[i] = np.random.uniform(-2,2)
        return pts
    
  • 定义目标函数
    def E(x):
        N = int(len(x)/2)
        eng_pot = np.zeros(N)
        R = x.reshape(N,2)
        for i in range(N-1):
            for j in range(i+1,N):
                Rij = R[j]-R[i]
                r = np.linalg.norm(Rij)
                eng_pot[i] += 0.5*LJ_reduced_pot(r)
                eng_pot[j] += 0.5*LJ_reduced_pot(r)
        return np.sum(eng_pot) 
    

2.积分算法

1.积分算法

  • N 个原子组成的分子体系,第 i 个原子的坐标、速度、动量及其作用力分别用 r i ( t ) r_{i}(t) ri(t) v i ( t ) v_{i}(t) vi(t) p i ( t ) p_{i}(t) pi(t) f i ( r , t ) f_{i}(r,t) fi(r,t) 表示,其初始值为 r i ( 0 ) r_{i}(0) ri(0) v i ( 0 ) v_{i}(0) vi(0) p i ( 0 ) p_{i}(0) pi(0) f i ( 0 ) f_{i}(0) fi(0)。则第 i 个原子运动的牛顿方程 f i = m i d 2 r i d t 2 = m i r ¨ i ( i = 1 , 2 , 3 , . . . , N ) f_{i}=m_{i}\frac{d^{2}r_{i}}{dt^{2}}=m_{i}\ddot{r}_{i}\quad\quad (i=1,2,3,...,N) fi=midt2d2ri=mir¨i(i=1,2,3,...,N)
  • 无约束条件下,3N 个自由度,3N 个分量微分方程
  • 根据初始时刻系统状态求解 3N 个牛顿运动方程,通过积分算法可以获得系统所有原子的轨迹
  • 第 i 个粒子的运动轨迹 r i ( t ) = ∫ v i ( t ) d t r_{i}(t)=\int v_{i}(t)dt ri(t)=vi(t)dt     未知 v i ( t ) v_{i}(t) vi(t) 解析形式,计算机程序算法: r i ( t ) = ∑ 0 t v i ( t ) Δ t r_{i}(t)=\sum_{0}^{t}v_{i}(t)\Delta t ri(t)=0tvi(t)Δt     使用计算机离散化求解数学问题近似解
  • 分子动力学积分算法要求
        1.速度快,内存小
        2.可以使用一个较长的时间步 Δ t \Delta t Δt
        3.可以接近和重复经典的路径
        4.满足已知的能量和动量守恒以及时间反演性
        5.形式简洁,易编程

2.前向Euler算法

  • 一维谐振子运动方程的解析解
        运动方程: m d 2 x d t 2 = f = − k x \frac{md^{2}x}{dt^{2}}=f=-kx dt2md2x=f=kx     初始条件: x ( 0 ) = 0 , v ( 0 ) = v 0 x(0)=0,\quad v(0)=v_{0} x(0)=0,v(0)=v0     解析解: x ( t ) = v 0 ω s i n ( ω t ) ω = k m x(t)=\frac{v_{0}}{\omega}sin(\omega t)\quad\quad\omega=\sqrt{\frac{k}{m}} x(t)=ωv0sin(ωt)ω=mk     体系总能: E ( t ) = K ( t ) + V ( t ) = 1 2 m v 0 2 = E ( t = 0 ) E(t)=K(t)+V(t)=\frac{1}{2}mv_{0}^{2}=E(t=0) E(t)=K(t)+V(t)=21mv02=E(t=0)
  • Euler算法基本思想
        采用有限差分法中的一阶微分形式表示,即展开到 Δ t \Delta t Δt一阶泰勒展开公式: f ( t + Δ t ) = f ( t ) + Δ t d f d t + O ( Δ t 2 ) f(t+\Delta t)=f(t)+\Delta t\frac{df}{dt}+O(\Delta t^{2}) f(t+Δt)=f(t)+Δtdtdf+O(Δt2)     将 r ( t ) r(t) r(t) v ( t ) v(t) v(t)泰勒展开后,得到前向Euler算法: r ( t + Δ t ) = r ( t ) + v ( t ) Δ t + O ( Δ t 2 ) r(t+\Delta t)=r(t)+v(t)\Delta t+O(\Delta t^{2}) r(t+Δt)=r(t)+v(t)Δt+O(Δt2) v ( t + Δ t ) = v ( t ) + F ( t ) m Δ t + O ( Δ t 2 ) v(t+\Delta t)=v(t)+\frac{F(t)}{m}\Delta t+O(\Delta t^{2}) v(t+Δt)=v(t)+mF(t)Δt+O(Δt2)
  • Python代码实现
    class HarmonicOscillator:
        def __init__(self,k,m):
            self.k = k
            self.m = m
         
        def acceleration(self,x):
            return -self.k * x / self.m
    
    class ForwardEulerIntegrator:
        def step(self,system,x,v)
            # 执行一个时间步
            # x:当前位置  v:当前速度
            a = system.acceleration(x)
            x_new = x + self.dt * v
            v_new = v + self.dt * a
            return x_new,v_new
    
  • 实际求解结果
        在分子动力学用向前Euler法计算体系能量时,经常会发生过热现象,即计算出的能量大于体系的真实能量,甚至可能导致体系的能量不收敛
        真实位置: r ′ ( t + Δ t ) = r ( t ) + v ˉ Δ t r^{'}(t+\Delta t)=r(t)+\bar{v}\Delta t r(t+Δt)=r(t)+vˉΔt     预测位置: r ( t + Δ t ) = r ( t ) + v ( t ) Δ t r(t+\Delta t)=r(t)+v(t)\Delta t r(t+Δt)=r(t)+v(t)Δt     预测位置大于真实位置(势能偏大)
        真实速度: v ′ ( t + Δ t ) = v ( t ) + F ˉ m Δ t v^{'}(t+\Delta t)=v(t)+\frac{\bar{F}}{m}\Delta t v(t+Δt)=v(t)+mFˉΔt     预测速度: v ( t + Δ t ) = v ( t ) + F ( t ) m Δ t v(t+\Delta t)=v(t)+\frac{F(t)}{m}\Delta t v(t+Δt)=v(t)+mF(t)Δt     预测速度大于真实速度(动能偏大)
  • 体系过热现象的理论证明 r ( t + Δ t ) = r ( t ) + v ( t ) Δ t + O ( Δ t 2 ) r(t+\Delta t)=r(t)+v(t)\Delta t+O(\Delta t^{2}) r(t+Δt)=r(t)+v(t)Δt+O(Δt2) v ( t + Δ t ) = v ( t ) + − d V ( t ) m d r Δ t + O ( Δ t 2 ) v(t+\Delta t)=v(t)+\frac{-dV(t)}{mdr}\Delta t+O(\Delta t^{2}) v(t+Δt)=v(t)+mdrdV(t)Δt+O(Δt2)
        忽略二阶小量,代入到体系总能量表达式中,计算相邻两步的能量差 E ( t + Δ t ) − E ( t ) = 1 2 m [ v ( t ) + − d V ( t ) m d r Δ t ] 2 + [ V ( t ) + d V ( t ) d t Δ t ] − 1 2 m v ( t ) 2 − V ( t ) E(t+\Delta t)-E(t)=\frac{1}{2}m[v(t)+\frac{-dV(t)}{mdr}\Delta t]^{2}+[V(t)+\frac{dV(t)}{dt}\Delta t]-\frac{1}{2}mv(t)^{2}-V(t) E(t+Δt)E(t)=21m[v(t)+mdrdV(t)Δt]2+[V(t)+dtdV(t)Δt]21mv(t)2V(t) E ( t + Δ t ) − E ( t ) = − v ( t ) d V ( t ) d r Δ t + d V ( t ) d t Δ t + 1 2 m [ d V ( t ) d r Δ t ] 2 > 0 E(t+\Delta t)-E(t)=-v(t)\frac{dV(t)}{dr}\Delta t+\frac{dV(t)}{dt}\Delta t+\frac{1}{2m}[\frac{dV(t)}{dr}\Delta t]^{2}>0 E(t+Δt)E(t)=v(t)drdV(t)Δt+dtdV(t)Δt+2m1[drdV(t)Δt]2>0     总能增大,体系过热,前向Euler法无法保证能量守恒

3.Verlet算法

  • 在 t 时刻求解 t + Δ t t+\Delta t t+Δt 时刻的坐标和力,分别向前和向后Taylor展开 r ( t + Δ t ) = r ( t ) + r ˙ ( t ) Δ t + r ¨ 2 Δ t 2 + 1 6 r . . . Δ t 3 + O ( Δ t 4 ) r(t+\Delta t)=r(t)+\dot{r}(t)\Delta t+\frac{\ddot{r}}{2}\Delta t^{2}+\frac{1}{6}\overset{...}{r}\Delta t^{3}+O(\Delta t^{4}) r(t+Δt)=r(t)+r˙(t)Δt+2r¨Δt2+61r...Δt3+O(Δt4) r ( t − Δ t ) = r ( t ) − r ˙ ( t ) Δ t + r ¨ 2 Δ t 2 − 1 6 r . . . Δ t 3 + O ( Δ t 4 ) r(t-\Delta t)=r(t)-\dot{r}(t)\Delta t+\frac{\ddot{r}}{2}\Delta t^{2}-\frac{1}{6}\overset{...}{r}\Delta t^{3}+O(\Delta t^{4}) r(tΔt)=r(t)r˙(t)Δt+2r¨Δt261r...Δt3+O(Δt4)     位置更新 r ( t + Δ t ) = 2 r ( t ) − r ( t − Δ t ) + F ( t ) m Δ t 2 + O ( Δ t 4 ) r(t+\Delta t)=2r(t)-r(t-\Delta t)+\frac{F(t)}{m}\Delta t^{2}+O(\Delta t^{4}) r(t+Δt)=2r(t)r(tΔt)+mF(t)Δt2+O(Δt4)
  • 在Verlet算法中,位置的更新不需要知道速度信息。然而想要得到动能信息就必须计算速度
        速度更新 v ( t ) = r ( t + Δ t ) − r ( t − Δ t ) 2 Δ t + O ( Δ t 2 ) v(t)=\frac{r(t+\Delta t)-r(t-\Delta t)}{2\Delta t}+O(\Delta t^{2}) v(t)=tr(t+Δt)r(tΔt)+O(Δt2)
  • Verlet算法的启动 r n + 1 = 2 r n − r n − 1 + ( F n m ) Δ t 2 + O ( Δ t 4 ) . . . r_{n+1}=2r_{n}-r_{n-1}+(\frac{F_{n}}{m})\Delta t^{2}+O(\Delta t^{4})... rn+1=2rnrn1+(mFn)Δt2+O(Δt4)...
        算法启动时, n = 0 n=0 n=0,已知 r 0 r_{0} r0,计算 r 1 r_{1} r1 必须需要知道 r − 1 r_{-1} r1 才能开始更新。为避免计算 r − 1 r_{-1} r1,通常通过Taylor展开来更新第一步: r ( t + Δ t ) = r ( t ) + v ( t ) Δ t + a ( t ) 2 Δ t 2 r(t+\Delta t)=r(t)+v(t)\Delta t+\frac{a(t)}{2}\Delta t^{2} r(t+Δt)=r(t)+v(t)Δt+2a(t)Δt2     经过这一步后,就可以使用计算得到的 r 0 r_{0} r0 r 1 r_{1} r1,根据Verlet算法持续更新位置
  • Python代码实现
    def step(self,system,x,v):
        if self.previous_x is None:
            self.previous_x = x-v0*self.dt+0.5*system.acceleration(x)* self.dt ** 2
        # 使用Verlet算法计算新位置
        a = system.acceleration(x)
        new_x = 2*x - self.previous_x + a * self.dt ** 2
        # 为当前位置计算速度
        if self.previous_x is not None:
             current_v = (new_x - self.previous_x) / (2*self.dt)
        else:
             current_v = 0
         # 为下一步更新previous_x
         self.previous_x = x
         return new_x,current_v
    
  • Verlet算法优点:1.位置精确度高,误差 O ( Δ t 4 ) O(\Delta t^{4}) O(Δt4)   2.每次积分只计算一次力   3.时间可逆
  • Verlet算法缺点:1.速度有较大误差   2.轨迹与速度无关,无法与热浴耦联

4.Velocity Verlet算法

  • r ( t ) r(t) r(t) v ( t ) v(t) v(t)泰勒展开到二阶项: r ( t + Δ t ) = r ( t ) + v ( t ) Δ t + 1 2 a ( t ) Δ t 2 + O ( Δ t 3 ) r(t+\Delta t)=r(t)+v(t)\Delta t+\frac{1}{2}a(t)\Delta t^{2}+O(\Delta t^{3}) r(t+Δt)=r(t)+v(t)Δt+21a(t)Δt2+O(Δt3) v ( t + Δ t ) = v ( t ) + a ( t ) Δ t + 1 2 a ˙ ( t ) Δ t 2 + O ( Δ t 3 ) v(t+\Delta t)=v(t)+a(t)\Delta t+\frac{1}{2}\dot{a}(t)\Delta t^{2}+O(\Delta t^{3}) v(t+Δt)=v(t)+a(t)Δt+21a˙(t)Δt2+O(Δt3)     引入 a ˙ ( t ) = a ( t + Δ t ) − a ( t ) Δ t \dot{a}(t)=\frac{a(t+\Delta t)-a(t)}{\Delta t} a˙(t)=Δta(t+Δt)a(t)
        位置更新 r ( t + Δ t ) = r ( t ) + v ( t ) Δ t + 1 2 a ( t ) Δ t 2 r(t+\Delta t)=r(t)+v(t)\Delta t+\frac{1}{2}a(t)\Delta t^{2} r(t+Δt)=r(t)+v(t)Δt+21a(t)Δt2     速度更新 v ( t + Δ t ) = v ( t ) + 1 2 [ a ( t ) + a ( t + Δ t ) ] Δ t v(t+\Delta t)=v(t)+\frac{1}{2}[a(t)+a(t+\Delta t)]\Delta t v(t+Δt)=v(t)+21[a(t)+a(t+Δt)]Δt
  • 引入半步速度
        位置更新 v ( t + Δ t 2 ) = v ( t ) + Δ t 2 a ( t ) v(t+\frac{\Delta t}{2})=v(t)+\frac{\Delta t}{2}a(t) v(t+2Δt)=v(t)+2Δta(t) r ( t + Δ t ) = r ( t ) + v ( t + Δ t 2 ) Δ t r(t+\Delta t)=r(t)+v(t+\frac{\Delta t}{2})\Delta t r(t+Δt)=r(t)+v(t+2Δt)Δt     速度更新 a ( t + Δ t ) = F ( r ( t + Δ t ) ) m a(t+\Delta t)=\frac{F(r(t+\Delta t))}{m} a(t+Δt)=mF(r(t+Δt)) v ( t + Δ t ) = v ( t + Δ t 2 ) + Δ t 2 a ( t + Δ t ) v(t+\Delta t)=v(t+\frac{\Delta t}{2})+\frac{\Delta t}{2}a(t+\Delta t) v(t+Δt)=v(t+2Δt)+2Δta(t+Δt)
  • Python代码实现
    def step(self,system,x,v):
        a = system.acceleration(x)
        x_new = x + self.dt * v + 0.5 * self.dt**2 * a
        a_new = system.acceleration(x_new)
        v_new = v + 0.5 * self.dt * (a + a_new)
        return x_new,v_new
    

5.Leapfrog算法

  • Leapfrog算法 r ( t + Δ t ) = r ( t ) + Δ t ⋅ v ( t + Δ t 2 ) r(t+\Delta t)=r(t)+\Delta t\cdot v(t+\frac{\Delta t}{2}) r(t+Δt)=r(t)+Δtv(t+2Δt) v ( t + Δ t 2 ) = v ( t − Δ t 2 ) + Δ t m ⋅ F ( t ) v(t+\frac{\Delta t}{2})=v(t-\frac{\Delta t}{2})+\frac{\Delta t}{m}\cdot F(t) v(t+2Δt)=v(t2Δt)+mΔtF(t)
  • Leapfrog算法的自启动 r ( Δ t ) = r ( 0 ) + Δ t ⋅ v ( Δ t 2 ) r(\Delta t)=r(0)+\Delta t\cdot v(\frac{\Delta t}{2}) r(Δt)=r(0)+Δtv(2Δt) v ( Δ t 2 ) = v ( − Δ t 2 ) + Δ t m ⋅ F ( 0 ) v(\frac{\Delta t}{2})=v(-\frac{\Delta t}{2})+\frac{\Delta t}{m}\cdot F(0) v(2Δt)=v(2Δt)+mΔtF(0) v ( − Δ t 2 ) = v ( 0 ) − F ( 0 ) 2 m Δ t v(-\frac{\Delta t}{2})=v(0)-\frac{F(0)}{2m}\Delta t v(2Δt)=v(0)2mF(0)Δt
  • Leapfrog算法优点节约内存,准确性和稳定性较高,速度、计算精度提高
  • Leapfrog算法缺点速度和位置总是差半个时间步,不在同一时间定义,因此动能和势能也不能同时定义,无法直接计算总能

6.积分算法的稳定性

  • 粒子演化涉及到位置对时间的积分,数值计算中必须考虑 Δ t \Delta t Δt 的选取
        1. Δ t \Delta t Δt 的选取是一个折中的方案。 Δ t \Delta t Δt 太小,会导致有限长的时间内无法遍历所有的相空间; Δ t \Delta t Δt 太大,会导致积分算法的不稳定
        2.分子动力学中常用的 Δ t \Delta t Δt 一般介于0.1-10 fs之间(10-15 s)
        3.对于液体的模拟,时间步长需要远小于两个液体分子的平均碰撞时间
        4.对于固体或者分子振动,时间步长通常不大于最短的运动周期的1/10
  • 牛顿运动方程的时间可逆性
    F = m d 2 r d t 2 F=m\frac{d^{2}r}{dt^{2}} F=mdt2d2r     时间反演 t ′ = − t d r d t ′ = − d r d t F = m d 2 r d t ′ 2 t'=-t\quad\quad\frac{dr}{dt'}=-\frac{dr}{dt}\quad\quad F=m\frac{d^{2}r}{dt'^{2}} t=tdtdr=dtdrF=mdt2d2r     牛顿运动方程形式不变
  • 前向Euler算法的可逆性 r ( t + Δ t ) = r ( t ) + v ( t ) Δ t r(t+\Delta t)=r(t)+v(t)\Delta t r(t+Δt)=r(t)+v(t)Δt v ( t + Δ t ) = v ( t ) + F ( t ) m Δ t v(t+\Delta t)=v(t)+\frac{F(t)}{m}\Delta t v(t+Δt)=v(t)+mF(t)Δt     时间反演 r ′ ( t ) = r ( t + Δ t ) − v ( t + Δ t ) Δ t = r ( t ) − F ( t ) m Δ t 2 r'(t)=r(t+\Delta t)-v(t+\Delta t)\Delta t=r(t)-\frac{F(t)}{m}\Delta t^{2} r(t)=r(t+Δt)v(t+Δt)Δt=r(t)mF(t)Δt2 r ′ ( t ) ≠ r ( t ) r'(t)\ne r(t) r(t)=r(t) v ′ ( t ) = v ( t + Δ t ) − F ( t + Δ t ) m Δ t = v ( t ) − F ′ ( t ) m Δ t 2 v'(t)=v(t+\Delta t)-\frac{F(t+\Delta t)}{m}\Delta t=v(t)-\frac{F'(t)}{m}\Delta t^{2} v(t)=v(t+Δt)mF(t+Δt)Δt=v(t)mF(t)Δt2 v ′ ( t ) ≠ v ( t ) v'(t)\ne v(t) v(t)=v(t)
  • Verlet算法的可逆性
        从 r ( t − Δ t ) r(t-\Delta t) r(tΔt) r ( t ) r(t) r(t) 推导 r ( t + Δ t ) r(t+\Delta t) r(t+Δt) r ( t + Δ t ) = 2 r ( t ) − r ( t − Δ t ) + F ( t ) m Δ t 2 r(t+\Delta t)=2r(t)-r(t-\Delta t)+\frac{F(t)}{m}\Delta t^{2} r(t+Δt)=2r(t)r(tΔt)+mF(t)Δt2     时间反演后,从 r ( t + Δ t ) r(t+\Delta t) r(t+Δt) r ( t ) r(t) r(t) 推导 r ( t − Δ t ) r(t-\Delta t) r(tΔt) r ′ ( t − Δ t ) = 2 r ( t ) − r ( t + Δ t ) + F ( t ) m Δ t 2 = r ( t − Δ t ) r'(t-\Delta t) = 2r(t)-r(t+\Delta t)+\frac{F(t)}{m}\Delta t^{2}=r(t-\Delta t) r(tΔt)=2r(t)r(t+Δt)+mF(t)Δt2=r(tΔt)
  • Velocity Verlet算法的可逆性
        正向推导: r ( t + Δ t ) = r ( t ) + v ( t ) Δ t + 1 2 a ( t ) Δ t 2 r(t+\Delta t)=r(t)+v(t)\Delta t+\frac{1}{2}a(t)\Delta t^{2} r(t+Δt)=r(t)+v(t)Δt+21a(t)Δt2 v ( t + Δ t ) = v ( t ) + 1 2 [ a ( t ) + a ( t + Δ t ) ] Δ t v(t+\Delta t)=v(t)+\frac{1}{2}[a(t)+a(t+\Delta t)]\Delta t v(t+Δt)=v(t)+21[a(t)+a(t+Δt)]Δt      逆向推导: r ′ ( t ) = r ( t + Δ t ) − v ( t + Δ t ) Δ t + 1 2 a ( t + Δ t ) Δ t 2 = r ( t ) r'(t)=r(t+\Delta t)-v(t+\Delta t)\Delta t+\frac{1}{2}a(t+\Delta t)\Delta t^{2}=r(t) r(t)=r(t+Δt)v(t+Δt)Δt+21a(t+Δt)Δt2=r(t)
  • Leapfrog算法的可逆性
        正向推导: r ( t + Δ t ) = r ( t ) + v ( t + Δ t 2 ) Δ t r(t+\Delta t)=r(t)+v(t+\frac{\Delta t}{2})\Delta t r(t+Δt)=r(t)+v(t+2Δt)Δt v ( t + Δ t 2 ) = v ( t − Δ t 2 ) + F ( t ) m Δ t v(t+\frac{\Delta t}{2})=v(t-\frac{\Delta t}{2})+\frac{F(t)}{m}\Delta t v(t+2Δt)=v(t2Δt)+mF(t)Δt      逆向推导: r ′ ( t ) = r ( t + Δ t ) − v ( t + Δ t 2 ) Δ t = r ( t ) r'(t)=r(t+\Delta t)-v(t+\frac{\Delta t}{2})\Delta t=r(t) r(t)=r(t+Δt)v(t+2Δt)Δt=r(t) v ′ ( t − Δ t 2 ) = v ( t + Δ t 2 ) − F ( t ) m Δ t = v ( t − Δ t 2 ) v'(t-\frac{\Delta t}{2})=v(t+\frac{\Delta t}{2})-\frac{F(t)}{m}\Delta t=v(t-\frac{\Delta t}{2}) v(t2Δt)=v(t+2Δt)mF(t)Δt=v(t2Δt)
  • 前向Euler算法不满足时间可逆性,而Verlet、Velocity Verlet和Leapfrog算法满足时间可逆性
  • 前向Euler算法不满足辛结构(Symplectic structures),而Verlet、Velocity Verlet和Leapfrog算法满足辛结构

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2266826.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

『大模型笔记』评估大型语言模型的指标:ELO评分,BLEU,困惑度和交叉熵介绍以及举例解释

评估大型语言模型的指标:ELO评分,BLEU,困惑度和交叉熵介绍以及举例解释 文章目录 一. ELO Rating大模型的elo得分如何理解1. Elo评分的基本原理2. 示例说明3. 大模型中的Elo得分总结3个模型之间如何比较计算,给出示例进行解释1. 基本原理扩展到三方2. 示例计算第一场: A A…

使用VS Code开发ThinkPHP项目

【图书介绍】《ThinkPHP 8高效构建Web应用》-CSDN博客 《ThinkPHP 8高效构建Web应用 夏磊 编程与应用开发丛书 清华大学出版社》【摘要 书评 试读】- 京东图书 ThinkPHP 8开发环境安装-CSDN博客 安装ThinkPHP项目的IDE 常用的集成开发环境&#xff08;IDE&#xff09;包括P…

ROS1入门教程6:复杂行为处理

一、新建项目 # 创建工作空间 mkdir -p demo6/src && cd demo6# 创建功能包 catkin_create_pkg demo roscpp rosmsg actionlib_msgs message_generation tf二、创建行为 # 创建行为文件夹 mkdir action && cd action# 创建行为文件 vim Move.action# 定义行为…

Java处理视频思路

1.首先实现断点续传功能。 断点续传实现思路&#xff1a; 前端对文件分块。前端使用多线程一块一块上传&#xff0c;上传前给服务端发一个消息校验该分块是否上传&#xff0c;如果已上传则不再上传。如果从该断点处断网了&#xff0c;下次上传时&#xff0c;前面的分块已经存在…

C#实现调用DLL 套壳读卡程序(桌面程序开发)

背景 正常业务已经支持 读三代卡了&#xff0c;前端调用医保封装好的服务就可以了&#xff0c;但是长护要读卡&#xff0c;就需要去访问万达&#xff0c;他们又搞了一套读卡的动态库&#xff0c;为了能够掉万达的接口&#xff0c;就需要去想办法调用它们提供的动态库方法&…

USB 状态机及状态转换

文章目录 USB 状态机及状态转换连接状态供电状态默认状态地址状态配置状态挂起状态USB 状态机及状态转换 枚举完成之前,USB 设备要经过一系列的状态变化,才能最终完成枚举。这些状态是 连接状态 - attached供电状态 - powered默认状态 - default地址状态 - address配置状态 -…

QT线程 QtConcurrent (深入理解)

QT多线程专栏共有16篇文章,从初识线程到、QMutex锁、QSemaphore信号量、Emit、Sgnals、Slot主线程子线程互相传值同步变量、QWaitCondition、事件循环、QObjects、线程安全、线程同步、线程异步、QThreadPool线程池、ObjectThread多线程操作、 moveToThread等线程操作进行了全…

Linux-Ubuntu之串口通信

Linux-Ubuntu之串口通信 一&#xff0c;串口通信1.串口通信寄存器配置2.串口通信软件实现①手动波特率②自动波特率③主函数 二&#xff0c;printf和scanf实现串口的输入显示 一&#xff0c;串口通信 1.串口通信寄存器配置 串口通信利用接口是这个TTL&#xff0c;下载程序用的…

阿尔萨斯(JVisualVM)JVM监控工具

文章目录 前言阿尔萨斯(JVisualVM)JVM监控工具1. 阿尔萨斯的功能2. JVisualVM启动3. 使用 前言 如果您觉得有用的话&#xff0c;记得给博主点个赞&#xff0c;评论&#xff0c;收藏一键三连啊&#xff0c;写作不易啊^ _ ^。   而且听说点赞的人每天的运气都不会太差&#xff…

41 stack类与queue类

目录 一、简介 &#xff08;一&#xff09;stack类 &#xff08;二&#xff09;queue类 二、使用与模拟实现 &#xff08;一&#xff09;stack类 1、使用 2、OJ题 &#xff08;1&#xff09;最小栈 &#xff08;2&#xff09;栈的弹出压入序列 &#xff08;3&#xf…

wangEditor富文本插件在vue项目中使用和媒体上传的实现

wangEditor是前端一个比较流行的简洁易用&#xff0c;功能强大的前端富文本编辑器&#xff0c;支持 JS Vue React&#xff0c;提供了很多丰富的功能&#xff0c;下面手把手教你实现wangWditor富文本插件在vue项目中配置&#xff0c;保存、图片上传等功能。无脑ctrlc即可 基本功…

VMwareTools安装(ubuntu23)

1.打开VMware&#xff0c;菜单栏虚拟机->安装VMwareTools 2.点开光驱&#xff0c;把压缩包复制到桌面 3.解压 如何开启sudo权限&#xff1a; sudo passwd root 之后输入密码查看解压文件夹&#xff0c;执行vmware-install.pl文件 安装过程中碰见如下报错信息&#xff1a;…

jangow-01-1.0.1靶机

靶机 ip&#xff1a;192.168.152.155 把靶机的网络模式调成和攻击机kali一样的网络模式&#xff0c;我的kali是NAT模式, 在系统启动时(长按shift键)直到显示以下界面 ,我们选第二个&#xff0c;按回车。 继续选择第二个&#xff0c;这次按 e 进入编辑页面 接下来&#xff0c;…

C# GDI+数码管数字控件

调用方法 int zhi 15;private void button1_Click(object sender, EventArgs e){if (zhi > 19){zhi 0;}lcdDisplayControl1.DisplayText zhi.ToString();} 运行效果 控件代码 using System; using System.Collections.Generic; using System.Drawing.Drawing2D; using …

Cilium:BPF 和 XDP 参考指南(2021)

大家觉得有意义和帮助记得及时关注和点赞!!! BPF 是 Linux 内核中一个非常灵活与高效的类虚拟机&#xff08;virtual machine-like&#xff09;组件&#xff0c; 能够在许多内核 hook 点安全地执行字节码&#xff08;bytecode &#xff09;。很多 内核子系统都已经使用了 BPF&a…

LabVIEW条件配置对话框

条件配置对话框&#xff08;Configure Condition Dialog Box&#xff09; 要求&#xff1a;Base Development System 当右键单击**条件禁用结构&#xff08;Conditional Disable Structure&#xff09;**并选择以下选项时&#xff0c;会显示此对话框&#xff1a; Add Subdiagr…

机器学习-高斯混合模型

文章目录 高斯混合模型对无标签的数据集&#xff1a;使用高斯混合模型进行聚类对有标签的数据集&#xff1a;使用高斯混合模型进行分类总结 高斯混合模型 对无标签的数据集&#xff1a;使用高斯混合模型进行聚类 对有标签的数据集&#xff1a;使用高斯混合模型进行分类 总结

GitLab 服务变更提醒:中国大陆、澳门和香港用户停止提供服务(GitLab 服务停止)

目录 前言 一. 变更详情 1. 停止服务区域 2. 邮件通知 3. 新的服务提供商 4. 关键日期 5. 行动建议 二. 迁移指南 三. 注意事项 四. 相关推荐 前言 近期&#xff0c;许多位于中国大陆、澳门和香港的 GitLab 用户收到了一封来自 GitLab 官方的重要通知。根据这封邮件…

MacOS下TestHubo安装配置指南

TestHubo是一款开源免费的测试管理工具&#xff0c; 下面介绍MacOS私有部署的安装与配置。TestHubo 私有部署版本更适合有严格数据安全要求的企业&#xff0c;支持在本地或专属服务器上运行&#xff0c;以实现对数据和系统的完全控制。 1、Mac 服务端安装 Mac安装包下载地址&a…

css绘制圆并绘制圆的半径

<div class"item1"></div>.item1 {position: relative;width: 420px;height: 420px;border-radius: 50%; /* 圆形 */color: white; /* 文本颜色 */background-color: rgba(154, 227, 36, 0.4); } .item1::before {content: "";position: absol…