05_二维梁振动案例注解
在test_2d_oscillating_beam案例中,我们将学到固体力学问题求解的基本流程,包括:
固体材料模型的定义
固体初始条件的定义
固体动力学的求解
固体运动约束
以下是模型的几何。红色是固定的基座,蓝色是可变形的梁。给定梁的初始速度分布,求解梁在之后的运动。

下图是模型在某时刻的PK1应力分布:

固体材料定义
SaintVenantKirchhoffSolid继承于LinearElasticSolid,二者区别是LinearElasticSolid只适用于小应变,而SaintVenantKirchhoffSolid适用于大应变。在elastic_solid源码剖析中有详细解释。
构造函数输入参考密度、杨氏模量、泊松比(ρ0,E,ν),代码计算体积模量K0、剪切模量G0和第一Lame系数λ0:
由上述属性,在每个时间步计算PK2应力:
初始条件
solid_dynamics::ElasticDynamicsInitialCondition其实就是个空壳子,和fluid_dynamics::FluidInitialCondition除了名字不一样其他都一样。用户需要自定义update函数。它继承于LocalDynamics,当用户在构造时传入sph_body时,就会赋给LocalDynamics的sph_body_成员,相当于接管了这个body。在速度场的定义中,我们要用到固体的参考声速。但是无法直接从sph_body_获取,因为getBaseMaterial()返回的是基类BaseMaterial的对象,而BaseMaterial并未定义ReferenceSoundSpeed方法。因此我们需要将返回的BaseMaterial对象经DynamicCast转换为ElasticSolid对象,后者定义了ReferenceSoundSpeed方法。
因为BeamInitialCondition只定义了update函数,所以只需用SimpleDynamics接管这个动力学。在求解开始之前执行一次即可。
固体动力学
修正矩阵
beam_corrected_configuration是修正矩阵,用于确保一阶一致性,详见全拉格朗日SPH入门。因为它只依赖于参考构形,所以只需要在模拟开始前计算一次。
两个最关键的动力学是Integration1stHalf...和Integration2ndHalf这两个积分动力学。在elastic_dynamics中有详细解释。
Integration1stHalfPK2
Integration1stHalfPK2分为三个阶段(对应三个成员函数):initialization、interaction和update。
initialization阶段,将位置、变形梯度、密度更新半步:
然后构造第一PK应力并乘以修正矩阵,结果储存在stress_PK1_B_中:
其中第一PK应力是在材料模型中用第二PK应力算出来的,而第二PK应力又是用最新的变形梯度Fin+1/2算出来的。
interaction阶段只做一件事——计算内力:内力:
fi=j∈N(i)∑ρ0mi(∇WijVj)[PiBiT+PjBjT+αwijPijdamp]eij,其中方括号中的第三项是数值阻尼项,α对应
numerical_dissipation_factor_,wij=Wij/W(r=0),Pijdamp是Pijdamp=21(Fi+Fj)D(ε˙ij,h),D(⋅) 由材料
ElasticSolid::PairNumericalDamping()给出,h是光滑长度,ε˙ij是应变率,在interaction中先计算好:ε˙ij=(rijd)2(xi−xj)⋅(vi−vj),其中d是维数。
update阶段使用计算的合力更新一步速度:vin+1=vin+Δtmifi+fiprior.
Integration2ndHalf
Integration2ndHalf也分为三个阶段(对应三个成员函数):initialization、interaction和update。
initialization阶段将位置推进至$n+1$步:xin+1=xin+1/2+21Δtvin+1.interaction阶段更新变形梯度的变化率:F˙in+1=−j∈N(i)∑(vin+1−vjn+1)⊗(∇WijVj)TBi.update阶段把变形梯度推进到$n+1$时间步:Fin+1=Fin+1/2+21ΔtF˙in+1.
可以看到,SPHinXsys先计算变形梯度变化率,再用其推进变形梯度的更新。在全拉格朗日SPH入门中,我们提到变形梯度可以按下面方式计算:
那么为什么不按照这个式子(位置重构式)直接更新变形梯度,而是大费周章地先求变化率再更新变形梯度呢?
实际上位置重构式在SPHinXsys中也有实现,就是solid_dynamics::DeformationGradientBySummation。它对粒子无序、邻域变化更敏感;每步重算会让 变形梯度出现“跳动”,再通过本构关系放大到应力和力里,容易引入高频噪声或能量漂移。相比之下,用变形梯度变化率去推进通常更“平滑”,因为它在时间上是连续推进的;并且跟Verlet算法用变化率去推进这套模式也是匹配的。
位置重构式更适合做类似density summation的修正,见test_2d_stretching案例。
积分时间步长
固体动力学积分的时间步长使用solid_dynamics::AcousticTimeStep,它按照下式计算时间步长:
我个人认为代码在书写顺序上有点问题。按理说,应该先求时间步,再执行积分。可是这里顺序反过来了。同时,dt被初始化为零,这就导致第一次进行时间积分的时候,时间步长是零,也就是说第一次积分相当于啥也没做。应该把顺序调过来才对。
固体运动约束
我在指定物体运动或变形中简要提过固体运动约束。具体来说,我们先定义一个基座的body part;然后用FixBodyPartConstraint定义运动约束,它的update函数会将位置置为初始位置,速度置零:
因为FixBodyPartConstraint只有一个update函数,所有我们用SimpleDynamics接管它即可。
Last updated