总结

同样APGD也不需要使用大矩阵Z;只用过便宜,也就是编号,做乘子计算。

对于ChSystemDescriptor,也就是说,chrono中的建模阶段是通过对不同块的矩阵进行偏移,也就是编码,然后不组装大矩阵Z,看求解器需要不,如果是直接线性求解器,类比VEROSIM中的dantzig,那么我就按照编号把大矩阵组装好,然后进行线性的求解,但是对于APGD这种迭代的求解器暂时不需要大矩阵,那么他在APGD调用相关数据时,比如N和R时,就可以根据偏移编码,读取出数据,从而进行计算,怎么编写的目的是为“既能装配、也能算子式”的通用接口层,方便不同类型求解器插拔。

为什么要matrix-free(矩阵-自由)?

关于并行化:是在ChSystemMulticore完成的,扁平数组(SoA)+ 并行 kernel(openMP)?这部分之后求解。 matrix-free不绝对是为并行化做准备的。真正把并行吃满的,是 SoA 扁平数组 + 批量 kernel + 颜色/分块避免写冲突(Chrono Multicore 那套)。

算子相对来说更快但是不绝对,主要是出于缓存的考量。

更多的是为了节约缓存

关于ChSystemMulticore是怎么设计完成并行的的,我觉得可以作为后面学习的重点。

关于里面的投影部分,执行约束乘子的投影:将约束的拉格朗日乘子投影到允许的集合上(例如,双边约束不会改变乘子;而对摩擦约束,会把乘子投影到摩擦圆锥上)在CHCONSTRAINT中定义了结构体用来定义Constraint mode,如果时FRICTION选择,ccp投影摩擦锥。

ChConstraintTwoTuplesContactN<Ta,Tb>:法向(Normal, N)约束行

ChConstraintTwoTuplesFrictionT<Ta,Tb>:切向(Tangential, T)约束行(U 与 V 两条)

Simulation system

ChSystem 与两种系统

Time steppers(时间积分器)

经验:DVI/硬接触 ⇒ EULER_IMPLICIT_LINEARIZED软接触/FEA/需要二阶与阻尼 ⇒ HHT/NEWMARK

Solvers(求解器)★重点

时间积分器每步都会调用“求解器”来求未知的加速度与反力。它往往是计算热点

推荐的迭代求解器与特性:

chrono 求解器结构

A P G D

代码

ChVersion : 版本号头文件”(version header)

Chplatform: Chrono 的“跨平台胶水” ,ChApiEXPORT/IMPORT 解决不同平台/构建方式下动态库符号可见性问题;CH_DEPRECATED 用于标记弃用 API并在编译期发出友好提醒。

ChApiCE: ChApi 是一个“可见性贴纸”宏——你把它贴在要对外公开的类/函数前面,它会在编库时展开成“导出符号”,在用库时展开成“导入符号”;如果是静态库或非 Windows,它通常什么也不做。

ChClassFactory:工厂机制

ChSystemDescriptor:

alt text

总结一下chrono的建模逻辑:

如果问的是“在建模阶段(BeginInsertion→EndInsertion)到底有没有把整块大矩阵 Z 真正组装出来?”

——答案是:没有。

在建模阶段只是把对象化的稀疏数据(变量、约束、K/R/M 块)登记到 ChSystemDescriptor 里,并给它们编号/写偏移。此时系统里保存的是:

什么时候才“真的组装大矩阵 Z”?

只有在你明确调用组装相关接口或用直接线性求解器时,才会把整块

\[Z=\begin{bmatrix}H & J^{\top}\\ J & E\end{bmatrix},\quad \text{rhs}=\{f;\,-b\}\]

显式贴到一个稀疏矩阵里。对应接口是 BuildSystemMatrix(&Z,&rhs),内部顺序就是: PasteMassKRMMatrixInto(H)PasteConstraintsJacobianMatrixInto(J)PasteConstraintsJacobianMatrixTransposedInto(J^T)PasteComplianceMatrixInto(E),然后 BuildDiVector(rhs) 生成 ${f;-b}$。

迭代求解时并不需要显式 Z

ChSolverAPGD: