接口倒置原则对 Python 有限元代码的模块化改造
开源的轻量级有限元软件FEMcy
笔者写过一个开源的有限元软件 FEMcy (github 链接: FEMcy), 是用 Python 结合 Taichi 并行语言写的轻量级有限元软件,可以在CPU/GPU上并行计算,支持变形过程及牛顿迭代过程构型的实现渲染可视化,支持线弹性、非线性(几何非线性、材料非线性),支持一次单元、二次单元等多种单元类型。
对有限元的矩阵组装、边界条件组装、矩阵求解感兴趣的朋友们欢迎 clone 到本地玩玩 (github 链接: FEMcy)。
C3D4 linear element | C3D10 quadritic element |
---|---|
接口倒置原则改造有限元代码
本文通过 SOLID 五大设计原则中的第5个设计原则:接口倒置原则 (Dependency Inverse Principle, DIP, 也叫依赖倒置原则)来对有限元代码框架进行改造。有人说接口倒置原则是五大设计原则中最重要的一条,因为他描述了代码如何通过抽象接口层实现松解耦和模块化,今天就来用这个面向接口编程的原则来改造一下有限元软件FEMcy.
主要思路:用抽象接口类统一多种多样的单元和材料类型
在有限元力学仿真中,单元和材料往往可以有多种不同的类型,比如,
- 单元类型:二维的三角形单元、四边形单元,三维的四面体单元、六面体单元,一次线性单元(edge中间无格点)、二次单元(edge中间有格点,二次函数反映弯曲后的edge构型)等
- 材料类型:二维的平面应变、平面应力材料本构,线弹性材料本构,大变形材料本构,超弹性材料本构如Neo-Hookean等。
这就带来一个需求,即如何把多种多样的单元类型和材料类型统一到一个接口框架中,使得其它模块只需要依赖基础的抽象单元接口和抽象材料接口,而无需依赖具体的多种多样的单元和材料类型。
当我们修改单元类型和材料类型的实现方式,或者增加类型的时候,其它依赖于单元和材料的模块代码无需修改(因为它们只依赖于单元和材料的抽象接口类),从而提高了代码的可扩展性和模块化,节省了咱们程序猿的脑力消耗和时间成本,岂不美滋滋?
有限元代码框架
如图所示为有限元代码框架,反映了单元和材料抽象化为接口类的思路(具体类名和实际代码有出入但抽象架构大体一致)。其中从上往下依次为依赖关系的最底层到最高层(即图中位置越靠上方的处于依赖关系中的越底层,对其它模块的依赖度越小)。图中的黄色部分仅依赖于抽象接口类,而蓝色部分则依赖于单元和材料各种不同类型的具体实现。
- 我们提取单元和材料的基类作为抽象接口类,其它模块尽可能依赖于单元和材料的抽象接口而非具体实现。
- 网格数据类(格点、单元、边界条件对应的格点集与单元集)和方程组类(包含刚度矩阵、右端项、求解器)依赖于抽象的单元接口类和材料接口类;由于没有依赖于具体的单元和材料类型,因此我们增加新的单元或材料时,无需修改这几个模块从而提高了扩展性。
- 文件读入模块和main函数(图中蓝色部分)等需要依赖于单元类和材料类的具体实现,因为主函数需要读入config文件构造出具体的单元类型和材料类型对象进行相应计算。
后续优化
时间所限,后面有时间再写