关于类的结构,我参考AMROC的结构,加进了一些自己的修改。最上层,是一个名为Case的类,它描述了一个算例的基本的,与数值方法无关的信息和元件:
1 Mesh:具有一般性的有限元网格类;
2 与具体数值方法无关、描述物理状态的边界条件,BoundaryCondition类;
3 一个控制和调度求解顺序的求解控制器,SolverControl类;
4 定义算例、网格和边界的资源文件;
5 IO控制
下一层,就是具体的Solver类,还有Mesh类可以说跨越两个层次,因为Mesh要提供一些方法和数据以配合具体的Solver。不过这些方法还是完全可以封装在Mesh内部的。同时,Solver类包含了一些与其特定数值方法有关的边界/初始条件实现的类,NumericalBoundaryCondition和InitialCondition。其中NumericalBoundaryCondition是依赖Case类的BoundaryCondition类的。
实际上我从看UML的第二天就开始画类图,当时并没有这样的层次感。画来画去,改来改去的,考虑其中计算中的一些元素到底作为哪个类的成员,一些算法过程到底应该定义在哪个类中,这些反反复复改了几次。我没有按照书中建议那样先做概念设计,然后是说明层次,最后才是实现层次。因为这个东西实际上还是比较简单,而且我不打算做到那么抽象,那么具有可扩展性。我只是打算做某一种具体CFD算法的程序,可扩展的部分只是细节部分(如何插值、如何迭代),而不是可扩展到别的CFD算法(比如FVM算法、SPH算法等等)。所以类图一开始便是实现层次的了。
但是这样就在思考上不容易把握软件的类的层次性。也就是说,软件中类结构是能够体现出所谓的概念层,说明层和实现层的。一开始就切入实现层,然而容易搞晕。我花了2天捉摸,把整个类图全部画在了一个页面上,还觉得页面空间太狭小,一些类在变大,耦合似乎越来越紧。
第三天,我想了想,还是要在思想上把握层次性。因此我便设计了上述的两层结构。我将类图分为两页,分别画出两层的类。
顶层类
Mesh类显得有些大,而且以后估计还会变得更大。我考虑将Mesh简化到只包含基本顶点和单元数据,而采用外部的网格操作类来实现其它数据的创建和计算,然后将数据连接并注册到Mesh的数据列表中去。听起来有些麻烦,所以暂且就这样了。
下层类