从 Affine Particle-In-Cell (APIC) 到 Material Point Method (MPM 物质点法)

APIC与MPM

    • Particle-In-Cell (PIC)
    • Affine Particle-In-Cell (APIC)
    • Material Point Method (MPM)
    • 关于边界投影等额外操作

Material Point Method (MPM 物质点法)是一种混合欧拉-拉格朗日视角物理仿真方法。

欧拉视角即网格视角,将空间划分为网格,通过表示网格表示仿真物体的信息,比如用网格存储该格子内或格点附近是否有液体,以及液体的速度,质量等。欧拉视角的优势在于其容易离散化,容易查找邻居网格,对于碰撞等处理更快速方便,但其精度受限于网格大小,并且空间开销很大,受限于格点信息的表示,容易造成能量损耗导致仿真精度问题。

拉格朗日视角即粒子视角,在物体上采样许多点作为粒子,通过仿真粒子的运动,模拟整个物体的运动。这种方式优点在于粒子表示更精确,但更难以离散化,必须用特殊手段对仿真物体采样,并且需要数据结构查找邻居处理相关信息以及碰撞等。

MPM将两种视角结合起来,通过将信息顺着“粒子-网格-粒子”的方向传输,结合两者的优点进行仿真。这种方法称作PIC (Particle-In-Cell)。

朴素的PIC方法仅传输粒子的动量 m v m\textbf{v} mv和质量 m m m到网格,再传输回粒子,但这样传输仍存在信息损失,能量损失的问题,于是APIC (Affine Particle-In-Cell) 方法通过添加仿射速度矩阵 C p C_p Cp改进了这一问题。再基于APIC方法,改进为MPM方法(这里的MPM是指2018年的MLS-MPM,其相比2013年MPM第一次被用在实际场景冰雪奇缘中更简单快捷先进)

本文主要参考GAMES201的第7讲和第8讲,并结合原论文进行了部分补充和错误修正

符号定义:

在文中所有以 i i i为下标的表示网格点的数据,如 m i , v i m_i, \textbf{v}_i mi,vi

所有以 p p p 为下标的表示粒子的数据,如 m p , v p m_p, \textbf{v}_p mp,vp

右上角的 n n n均表示算法迭代到第 n n n

Particle-In-Cell (PIC)

PIC算法需要的流程:

  1. 对动量或速度进行时间积分(如 m v n + 1 = m v n + f Δ t m\textbf{v} ^ {n+1} = m\textbf{v}^n + f \Delta t mvn+1=mvn+fΔt)后,将粒子上的信息(如质量,动量等)传递到网格上
  2. 在网格上处理网格方便处理的事,如边界碰撞,液体不可压缩性等,计算好网格的数据(质量、动量)
  3. 将数据从网格传回粒子,并对粒子进行时间积分(如 x n + 1 = x n + v n + 1 Δ t \textbf{x}^{n+1} = \textbf{x}^n + \textbf{v}^{n+1} \Delta t xn+1=xn+vn+1Δt

在传递数据时,粒子需要将自己的数据按照一定权重加到网格上,越远的粒子权重越低,并且需要保证每个粒子到其周围所有格点的权重之和为1

B-Spline(B样条曲线)正好解决了这一问题。B-Spline原本是用于通过函数插值若干个控制点得到一个平滑的曲线,这里的插值方法确保了曲线上每个点由周围控制点贡献的权重和一定为1,并且B-Spline的平滑性确保了离控制点越远,权重越小,权重导数也越小,使得数值计算更加稳定。

在这里我们一般使用2阶(Quadratic,下图红色)或3阶(Cubic,下图蓝色)的B-Spline核函数。

格点-粒子传输(图源GAMES201)

这里的2阶B-Spline核函数实际上是通过3阶B样条参数改造得来,在使用Quadratic时: N ( x ) = B 0 , 3 ( x 2 + 1 ) N(x)=B_{0,3}(\frac x 2+1) N(x)=B0,3(2x+1)

Quadratic B-Spline:
N ( x ) = { 3 4 − ∣ x ∣ 2 0 ≤ ∣ x ∣ < 1 2 1 2 ( 3 2 − ∣ x ∣ ) 2 1 2 ≤ ∣ x ∣ < 3 2 0 3 2 ≤ ∣ x ∣ N(x) = \begin{cases} \frac 3 4 - {|x|}^2 & 0 \leq {|x|} < \frac 1 2 \\ \frac 1 2 {\left (\frac 3 2 - {|x|} \right ) }^2 & \frac 1 2 \leq {|x|} < \frac 3 2 \\ 0 & \frac 3 2 \leq {|x|} \end{cases} N(x)= 43x221(23x)200x<2121x<2323x
Cubic B-Spline:
N ( x ) = { 1 2 ∣ x ∣ 3 − ∣ x ∣ 2 + 2 3 0 ≤ ∣ x ∣ < 1 1 6 ( 2 − ∣ x ∣ ) 3 1 ≤ ∣ x ∣ < 2 0 2 ≤ ∣ x ∣ N(x) = \begin{cases} \frac 1 2 {|x|}^3 - {|x|} ^2 + \frac 2 3 & 0 \leq {|x|} < 1 \\ \frac 1 6 {\left( 2 - {|x|} \right) } ^3 & 1 \leq {|x|} < 2 \\ 0 & 2 \leq {|x|} \end{cases} N(x)= 21x3x2+3261(2x)300x<11x<22x
其中 ∣ x ∣ |x| x根据格点距离进行了归一化处理,即保证两个格点的距离为 1

计算粒子到格点的权重时,需要将每一维(x,y,z轴)的距离按照B-Spline计算权重,再乘起来

即令权重 w i p w_{ip} wip即格子 i i i对粒子 p p p的权重,则 w i p = N i ( x p / Δ x ) w_{ip} = N_i (\textbf{x}_p / \Delta x) wip=Ni(xpx) Δ x \Delta x Δx为格点距离

因此B-Spline确保了 ∑ i w i p = 1 \sum_i w_{ip} = 1 iwip=1

于是PIC的流程为:

  1. P2G:

    ( m v ) i n + 1 = ∑ p w i p ( m v ) p n \left( m \textbf{v} \right)_i^{n+1} = \sum_p w_{ip} \left( m \textbf{v} \right)_p^n (mv)in+1=pwip(mv)pn

    m i n + 1 = ∑ p w i p m p m_i^{n+1} = \sum_p w_{ip} m_p min+1=pwipmp

  2. Grid opertaions

    v ^ i n + 1 = ( m v ) i n + 1 / m i n + 1 \hat{\textbf{v}}_i^{n+1} = \left( m \textbf{v} \right)_i^{n+1} / m_i^{n+1} v^in+1=(mv)in+1/min+1

    处理网格操作,如边界等: v i n + 1 = Project ( v ^ i n + 1 ) \textbf{v}_i^{n+1} = \text {Project} \left(\hat{\textbf{v}}_i^{n+1}\right) vin+1=Project(v^in+1)

    边界处理的操作将在本文末尾讲述

  3. G2P

    v p n + 1 = ∑ i w i p v i n + 1 \textbf{v} _p^{n+1} = \sum_i w_{ip} \textbf{v}_i^{n+1} vpn+1=iwipvin+1

    x p n + 1 = x p n + v p n + 1 Δ t \textbf{x}_p^{n+1} = \textbf{x}_p^n + \textbf{v}_p^{n+1} \Delta t xpn+1=xpn+vpn+1Δt

Affine Particle-In-Cell (APIC)

注:APIC原作者发了两篇文章,一篇在2015年,一篇在2017年,2015年的简单易懂,2017年的详细证明但是复杂,建议一定要先从2015年那篇看。

在PIC方法中,粒子的信息被传输到格点时,是一种加权平均的操作。在格点信息传回粒子时,同样是加权平均的操作。多次平均的操作会使得信息在传输中损失,同时造成能量损耗。在实践过程中可以看到PIC仅能维持整体动量守恒,但整体角动量守恒会损耗,因为相邻粒子之间的动量差在传输过程中变得更加平均。

要解决这一问题就需要一种表示方法来确保相邻粒子之间的动量差能够保持,APIC的解决方法是添加一个仿射速度矩阵 C p C_p Cp。对每一个粒子 p p p,我们希望表示粒子以及其领域的速度: v ( x ) = v p + C p ( x − x p ) \textbf{v}(\textbf{x}) = \textbf{v}_p +C_p (\textbf{x} - \textbf{x}_p) v(x)=vp+Cp(xxp),其中 x \textbf{x} x为粒子邻域内的一个位置,可以理解为 C p C_p Cp为速度场关于位置的导数。

仿射矩阵 C p C_p Cp将会从粒子周围的格点来估计,从直观上理解,2维情况下的该矩阵每个位置的意义如下图:

仿射矩阵(图源GAMES201)

但是在实践过程中,求速度场关于位置的导数过于复杂并且低效,所以用了一种近似的方法,通过格点的速度与到粒子位移的张量积来估计:(这里以Quadratic B-Spline为例)
C p = 4 Δ x 2 ∑ i w i p v i ( x i − x p ) T C_p = \frac 4 {\Delta x^2} \sum_i w_{ip} \textbf{v}_i (\textbf{x}_i - \textbf{x}_p)^T Cp=Δx24iwipvi(xixp)T

其中系数 4 Δ x 2 \frac 4 {\Delta x^2} Δx24是在Quadratic B-Spline插值权重生效,对于Cubic形式,系数为 3 Δ x 2 \frac 3 {\Delta x^2} Δx23

APIC原论文作者在2017年的论文第20页5.6.3节进行了非常复杂的推导得出该系数。我推测作者是最初是通过实现了一个更复杂的基础版本 C p = B p ( D p ) − 1 C_p = B_p \left( D_p \right)^{-1} Cp=Bp(Dp)1,通过观察得出的一个简洁的系数版本,再去推出证明。

有了仿射矩阵 C p C_p Cp后,将粒子动量传输到网格上时,就需要通过仿射矩阵计算邻域速度的形式,来计算粒子贡献给格点的速度

于是,APIC算法的流程如下:

  1. P2G:

    ( m v ) i n + 1 = ∑ p w i p [ m v p n + m p C p n ( x i − x p n ) ] \left( m \textbf{v} \right)_i^{n+1} = \sum_p w_{ip} \left[m \textbf{v}_p^n + m_p C_p^n \left(\textbf{x}_i - \textbf{x}_p^n \right) \right] (mv)in+1=pwip[mvpn+mpCpn(xixpn)]

    m i n + 1 = ∑ p w i p m p m_i^{n+1} = \sum_p w_{ip} m_p min+1=pwipmp

  2. Grid opertaions

    v ^ i n + 1 = ( m v ) i n + 1 / m i n + 1 \hat{\textbf{v}}_i^{n+1} = \left( m \textbf{v} \right)_i^{n+1} / m_i^{n+1} v^in+1=(mv)in+1/min+1

    处理网格操作,如边界等: v i n + 1 = Project ( v ^ i n + 1 ) \textbf{v}_i^{n+1} = \text {Project} \left(\hat{\textbf{v}}_i^{n+1}\right) vin+1=Project(v^in+1)

  3. G2P

    v p n + 1 = ∑ i w i p v i n + 1 \textbf{v} _p^{n+1} = \sum_i w_{ip} \textbf{v}_i^{n+1} vpn+1=iwipvin+1

    C p n + 1 = 4 Δ x 2 ∑ i w i p v i n + 1 ( x i − x p n ) T C_p^{n+1} = \frac 4 {\Delta x^2} \sum_i w_{ip} \textbf{v}_i^{n+1} (\textbf{x}_i - \textbf{x}_p^n)^T Cpn+1=Δx24iwipvin+1(xixpn)T

    x p n + 1 = x p n + v p n + 1 Δ t \textbf{x}_p^{n+1} = \textbf{x}_p^n + \textbf{v}_p^{n+1} \Delta t xpn+1=xpn+vpn+1Δt

Material Point Method (MPM)

这里的MPM方法将着重处理弹性体。

首先定义弹性体初始每个点的位置为 X X X,弹性体每个点变化后当前的位置为 x = ϕ ( X ) \textbf{x} = \phi(X) x=ϕ(X),一个重要的参数是应变张量 F = ∂ ϕ ( X ) ∂ X = ∂ x ∂ X F = \frac {\partial \phi (X)} {\partial X} = \frac {\partial \textbf{x}} {\partial X} F=Xϕ(X)=Xx。 对于弹性体,整体移动并不会产生内部弹力,所以函数 ϕ \phi ϕ的梯度,即表示相邻位置移动的不同会产生形变,所以弹性体的内部能量一般根据 F F F来定义。

定义弹性体的能量密度为 Ψ ( ϕ , X ) \Psi (\phi, X) Ψ(ϕ,X),即位置 X X X在形变为 ϕ \phi ϕ函数时的能量密度。在各种弹性物质模型下,往往直接用应变张量定义能量密度 Ψ ( F ) \Psi(F) Ψ(F)。此时弹性体总能量为 E ( ϕ ) = ∫ Ψ ( F ) d X E(\phi) = \int \Psi(F) \mathrm{d}X E(ϕ)=Ψ(F)dX

在弹性力学中有时候为了表示某一截面微元上的应力,定义了PK1数(The First Piola-Kirchhoff stress tensor), P ( F ) = ∂ Ψ ( F ) ∂ F P(F) = \frac {\partial \Psi(F)} {\partial F} P(F)=FΨ(F)。这在3维下是一个3×3的矩阵,其乘一个法向量之后就可以表示 X X X位置与法向量垂直截面微元的应力。PK1的推导是在计算内力时,用能量对位置求导的中间变量,不在这里详细叙述,只需知道许多弹性体模型会直接定义出 P ( F ) P(F) P(F),抄公式就可以了。

在MPM中,我们的粒子不仅存储质量 m p m_p mp,动量 ( m v ) i (m \textbf{v})_i (mv)i,还需要存储应变张量 F p F_p Fp。在迭代过程中,应变张量可以按如此迭代 F p n + 1 = ( I + Δ t ∇ v ) F p n F_p^{n+1} = (I + \Delta t \nabla \textbf{v}) F_p^n Fpn+1=(I+Δtv)Fpn。由于我们使用了 C p C_p Cp来近似粒子 p p p邻域的速度梯度,则可以使用这个公式迭代: F p n + 1 = ( I + Δ t C p n ) F p n F_p^{n+1} = (I + \Delta t C_p^n) F_p^n Fpn+1=(I+ΔtCpn)Fpn

在粒子将动量传递给网格时,应先将弹性内力处理了,因为这是粒子更容易操作的事情。所以我们需要通过粒子计算周围格点所受的内力 f i \textbf{f}_i fi,内力一般用弹性势能对位置的梯度来求。

粒子能量: U i = ∑ p V p 0 Ψ p ( F p n + 1 ) U_i = \sum_p V_p^0 \Psi_p(F_p^{n+1}) Ui=pVp0Ψp(Fpn+1),其中 V p 0 V_p^0 Vp0为该粒子在初始状态代表的弹性体部分体积

格点内力计算时用弹性势能对位置求梯度,注意格点位置本来是不变的,但我们现在需要的位置是其在弹性体上的位置,可以假定其会根据格点的速度变化 x ^ i = x i + Δ t v i \hat{\textbf{x}}_i = \textbf{x}_i + \Delta t \textbf{v}_i x^i=xi+Δtvi
f i = − ∂ U ∂ x ^ i = − ∑ p V p 0 ∂ Ψ ( F p n + 1 ) ∂ x ^ i = − ∑ p V p 0 Δ t ∂ Ψ ( F p n + 1 ) ∂ v i = − ∑ p V p 0 Δ t ∂ Ψ ( F p n + 1 ) ∂ F p n + 1 ∂ F p n + 1 ∂ C p n ∂ C p n ∂ v i = − ∑ p V p 0 Δ t ⋅ P p ( F p n + 1 ) ⋅ Δ t ( F p n ) T ⋅ 4 w i p Δ x 2 ( x i − x p n ) = − 4 Δ x 2 ∑ p V p 0 ⋅ P p ( F p n + 1 ) ⋅ ( F p n ) T ⋅ w i p ( x i − x p n ) \begin{align} \textbf{f}_i & = - \frac {\partial U} {\partial \hat{\textbf{x}}_i} \\ & = - \sum_p V_p^0 \frac {\partial \Psi(F_p^{n+1})} {\partial \hat{\textbf{x}}_i} \\\ & = - \sum_p \frac {V_p^0} {\Delta t} \frac {\partial \Psi(F_p^{n+1})} {\partial \textbf{v}_i} \\ & = - \sum_p \frac {V_p^0} {\Delta t} \frac {\partial \Psi(F_p^{n+1})} {\partial F_p^{n+1}} \frac {\partial F_p^{n+1}} {\partial C_p^n} \frac {\partial C_p^n} {\partial \textbf{v}_i} \\ & = - \sum_p \frac {V_p^0} {\Delta t} \cdot P_p(F_p^{n+1}) \cdot \Delta t \left({F_p^n}\right)^T \cdot \frac {4 w_{ip}} {\Delta x^2} (\textbf{x}_i - \textbf{x}_p^n) \\ & = - \frac {4} {\Delta x^2} \sum_p {V_p^0} \cdot P_p(F_p^{n+1}) \cdot \left({F_p^n}\right)^T \cdot w_{ip} (\textbf{x}_i - \textbf{x}_p^n) \end{align} fi =x^iU=pVp0x^iΨ(Fpn+1)=pΔtVp0viΨ(Fpn+1)=pΔtVp0Fpn+1Ψ(Fpn+1)CpnFpn+1viCpn=pΔtVp0Pp(Fpn+1)Δt(Fpn)TΔx24wip(xixpn)=Δx24pVp0Pp(Fpn+1)(Fpn)Twip(xixpn)
在更新格点动量时,即可这样更新: ( m v ) i n + 1 = ∑ p w i p [ m v p n + ( m p C p n + Δ t f i ) ( x i − x p n ) ] \left( m \textbf{v} \right)_i^{n+1} = \sum_p w_{ip} \left[m \textbf{v}_p^n + \left( m_p C_p^n + \Delta t \textbf{f}_i \right) \left(\textbf{x}_i - \textbf{x}_p^n \right) \right] (mv)in+1=pwip[mvpn+(mpCpn+Δtfi)(xixpn)]

于是MPM的总流程为:

  1. P2G:

    F p n + 1 = ( I + Δ t C p n ) F p n F_p^{n+1} = (I + \Delta t C_p^n) F_p^n Fpn+1=(I+ΔtCpn)Fpn

    ( m v ) i n + 1 = ∑ p w i p [ m v p n + ( m p C p n + Δ t f i ) ( x i − x p n ) ] \left( m \textbf{v} \right)_i^{n+1} = \sum_p w_{ip} \left[m \textbf{v}_p^n + \left( m_p C_p^n + \Delta t \textbf{f}_i \right) \left(\textbf{x}_i - \textbf{x}_p^n \right) \right] (mv)in+1=pwip[mvpn+(mpCpn+Δtfi)(xixpn)]

    m i n + 1 = ∑ p w i p m p m_i^{n+1} = \sum_p w_{ip} m_p min+1=pwipmp

  2. Grid opertaions

    v ^ i n + 1 = ( m v ) i n + 1 / m i n + 1 \hat{\textbf{v}}_i^{n+1} = \left( m \textbf{v} \right)_i^{n+1} / m_i^{n+1} v^in+1=(mv)in+1/min+1

    处理网格操作,如边界等: v i n + 1 = Project ( v ^ i n + 1 ) \textbf{v}_i^{n+1} = \text {Project} \left(\hat{\textbf{v}}_i^{n+1}\right) vin+1=Project(v^in+1)

  3. G2P

    v p n + 1 = ∑ i w i p v i n + 1 \textbf{v} _p^{n+1} = \sum_i w_{ip} \textbf{v}_i^{n+1} vpn+1=iwipvin+1

    C p n + 1 = 4 Δ x 2 ∑ i w i p v i n + 1 ( x i − x p n ) T C_p^{n+1} = \frac 4 {\Delta x^2} \sum_i w_{ip} \textbf{v}_i^{n+1} (\textbf{x}_i - \textbf{x}_p^n)^T Cpn+1=Δx24iwipvin+1(xixpn)T

    x p n + 1 = x p n + v p n + 1 Δ t \textbf{x}_p^{n+1} = \textbf{x}_p^n + \textbf{v}_p^{n+1} \Delta t xpn+1=xpn+vpn+1Δt

关于边界投影等额外操作

对于边界,直接找到边界的格点,找到边界的法向量 n \textbf{n} n,把冲出边界的速度消掉即可 v i n + 1 = v ^ i n + 1 + n ⋅ min ⁡ ( n T v ^ i n + 1 , 0 ) \textbf{v}_i^{n+1} = \hat{\textbf{v}}_i^{n+1} + \textbf{n} \cdot \min(\textbf{n}^T \hat{\textbf{v}}_i^{n+1}, 0) vin+1=v^in+1+nmin(nTv^in+1,0)

或者使用各种动量守恒的反射操作也可以

对于外力,重力的添加,可以将其直接添加到粒子或者格点上: v ^ i n + 1 + = Δ t g \hat{\textbf{v}}_i^{n+1} += \Delta t g v^in+1+=Δtg

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

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

相关文章

从一到无穷大 #35 Velox Parquet Reader 能力边界

本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。 本作品 (李兆龙 博文, 由 李兆龙 创作)&#xff0c;由 李兆龙 确认&#xff0c;转载请注明版权。 文章目录 引言源码分析功能描述功能展望 引言 InfluxDB IOX这样完全不使用索引&#xff0c;只…

JavaEE: 深入探索TCP网络编程的奇妙世界(四)

文章目录 TCP核心机制TCP核心机制四: 滑动窗口为啥要使用滑动窗口?滑动窗口介绍滑动窗口出现丢包咋办? TCP核心机制五: 流量控制 TCP核心机制 书接上文~ TCP核心机制四: 滑动窗口 为啥要使用滑动窗口? 之前我们讨论了确认应答策略,对每一个发送的数据段,都要给一个ACK确…

centos7下openssh升级方法(编译安装)

注意&#xff1a; 首先打开两个或以上的shell连接&#xff0c;因为在升级过程中如果升级失败会导致不发新建shell连接&#xff1b;升级后使用xshell6,7连接&#xff0c;openssh版本对应修改&#xff0c;下载地址&#xff1a; https://cdn.openbsd.org/pub/OpenBSD/OpenSSH/por…

Servlet day2(概念理解)

Servlet体系结构 Servlet相关配置 HTTP协议内容

leetcode746. 使用最小花费爬楼梯,动态规划

leetcode746. 使用最小花费爬楼梯 给你一个整数数组 cost &#xff0c;其中 cost[i] 是从楼梯第 i 个台阶向上爬需要支付的费用。一旦你支付此费用&#xff0c;即可选择向上爬一个或者两个台阶。 你可以选择从下标为 0 或下标为 1 的台阶开始爬楼梯。 请你计算并返回达到楼梯顶…

计算机毕业设计 基于SpringBoot的小区运动中心预约管理系统的设计与实现 Java实战项目 附源码+文档+视频讲解

博主介绍&#xff1a;✌从事软件开发10年之余&#xff0c;专注于Java技术领域、Python人工智能及数据挖掘、小程序项目开发和Android项目开发等。CSDN、掘金、华为云、InfoQ、阿里云等平台优质作者✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精…

Java笔试面试题AI答之设计模式(4)

文章目录 16. 简述什么是观察者模式&#xff1f;基本概念主要特点实现方式应用场景优缺点 17. 请列举观察者模式应用场景 &#xff1f;18. 请用Java代码实现观察者模式的案例 &#xff1f;19. 什么是装饰模式&#xff1f;定义与特点结构与角色工作原理优点应用场景示例 20. 请用…

基于大数据的电子产品需求数据分析系统的设计与实现(Python Vue Flask Mysql)

&#x1f497;博主介绍&#x1f497;&#xff1a;✌在职Java研发工程师、专注于程序设计、源码分享、技术交流、专注于Java技术领域和毕业设计✌ 温馨提示&#xff1a;文末有 CSDN 平台官方提供的老师 Wechat / QQ 名片 :) Java精品实战案例《700套》 2025最新毕业设计选题推荐…

【GlobalMapper精品教程】088:按点线面空间位置选择案例

按点线面空间位置选择的原则为:点线面的排列组合。 文章目录 一、选择线要素附近的点二、选择相交或触碰所选线的区和线三、选择包含点的区要素四、选择选定区域内的点要素一、选择线要素附近的点 启动该工具之前,首先要选择线,例如,选择某一段铁路5km范围之内的县城驻地。…

DeepSeek 2.5本地部署的实战教程

大家好,我是herosunly。985院校硕士毕业,现担任算法研究员一职,热衷于大模型算法的研究与应用。曾担任百度千帆大模型比赛、BPAA算法大赛评委,编写微软OpenAI考试认证指导手册。曾获得阿里云天池比赛第一名,CCF比赛第二名,科大讯飞比赛第三名。授权多项发明专利。对机器学…

[Meachines] [Medium] Sniper RFI包含远程SMB+ powershell用户横向+CHM武器化权限提升

信息收集 IP AddressOpening Ports10.10.10.151TCP:80,135,139,445,49667 $ nmap -p- 10.10.10.151 --min-rate 1000 -sC -sV -Pn PORT STATE SERVICE VERSION 80/tcp open http Microsoft IIS httpd 10.0 |_http-server-header: Microsoft-IIS/10.…

三阶魔方还原法 勾上回下 上右左左右

三阶魔方还原法&#xff1a; 1小白花 &#xff08;转3换1&#xff09; 2白十字架 (侧与中心同色 下下) 3第一层 &#xff08;找位置角块放顶点 勾上回下&#xff09; 4 第二层 &#xff08;颜色边 勾上回下 再单白边 勾上回下&#xff09; 5 黄十字架 &#xff08;无黄边 压 勾…

0.设计模式总览——设计模式入门系列

在现代软件开发中&#xff0c;设计模式为我们提供了优秀的解决方案&#xff0c;帮助我们更好地组织代码和架构。本系列专栏将对设计模式的基本思想、原则&#xff0c;以及常用的分类、实现方式&#xff0c;案例对比、以及使用建议&#xff0c;旨在提高开发者对设计模式的理解和…

【算法】BFS系列之 拓扑排序

【ps】本篇有 3 道 leetcode OJ。 目录 一、算法简介 二、相关例题 1&#xff09;课程表 .1- 题目解析 .2- 代码编写 2&#xff09;课程表 II .1- 题目解析 .2- 代码编写 3&#xff09;火星词典 .1- 题目解析 .2- 代码编写 一、算法简介 【补】图的基本概念 &#…

HTML翻牌器:用CSS和HTML元素创造动态数字展示

HTML翻牌器&#xff1a;用CSS和HTML元素创造动态数字展示 前言 翻牌器是一种数字动态展示形式&#xff0c;在生活中常见的例如翻牌计分、翻牌时钟等。 之所以以翻牌的形式是因为其物理设计的原因使其只能滚动翻牌展示数字&#xff0c;在电子显示设备不普及时&#xff0c;使用…

Leetcode - 139双周赛

目录 一&#xff0c;3285. 找到稳定山的下标 二&#xff0c;3286. 穿越网格图的安全路径 三&#xff0c;3287. 求出数组中最大序列值 四&#xff0c;3288. 最长上升路径的长度 一&#xff0c;3285. 找到稳定山的下标 本题就是找[0&#xff0c; n-2]中&#xff0c;height[i]…

C++入门12——详解多态2

上篇文章&#xff08;C入门12——详解多态1&#xff09;中&#xff0c;我们介绍了C多态的概念和用法&#xff0c;但是只知其然而不知其所以然是万万不行的&#xff0c;所以本篇文章将从探案的角度详细介绍多态的原理。 1. 虚函数表 想要弄懂多态的原理&#xff0c;首先要了解一…

数据结构与算法学习day22-回溯算法-分割回文串、复原IP地址、子集

一、分割回文串 1.题目 131. 分割回文串 - 力扣&#xff08;LeetCode&#xff09; 2.思路 分割回文串可以抽象为一棵树形结构。 递归用来纵向遍历&#xff0c;for循环用来横向遍历&#xff0c;切割线&#xff08;就是图中的红线&#xff09;切割到字符串的结尾位置&#xf…

STM32F407单片机编程入门(十三) 单片机IAP(在应用编程)详解及实战源码

文章目录 一.概要二.STM32F407VET6单片机IAP介绍1.STM32F407VET6单片机IAP基本原理2.STM32F407VET6单片机IAP基本流程 三.配置一个BOOT工程四.配置一个APP工程五.工程源代码下载六.小结 一.概要 STM32单片机程序升级方法有很多种&#xff0c;主要有以下几种&#xff1a; 1.将…

【LeetCode】146. LRU缓存

1.题目 2.思想 3.代码 3.1 代码1 下面这是一版错误的代码。错误的原因在于逻辑不正确导致最后的代码也是不正确的。 class LRUCache:def __init__(self, capacity: int):self.time 0 # 用于全局记录访问的时间self.num2time {} # 数字到时间的映射self.key2val {} # 数字…