Eigen 数学库介绍及Qt配置

Eigen是一个高层次的C ++库,有效支持线性代数,矩阵和矢量运算,数值分析及其相关的算法。Eigen是一个开源库,从3.1.1版本开始遵从MPL2许可。

我最近在写有限元程序,本来一个基本的框架,已经在python里写好了,但是后来想想还是得使用C++。自然要用到矩阵运算的库,我选择了Eigen。

前几天,问了在大学教计算数学的师妹,他们写论文用什么库,师妹说用Matlab。好吧,这也许就是我们为什么写了大量的代码,不能有产品级的迭代的原因了吧。

1、我为什么要自己写库?

想要写一个自己的方程求解的库,是很早就有的想法了。最近正好我的师兄何晓明教授,在天元基金东北中心做公开课,我也就好好跟师兄学习了一下。希望这次能走的更远一些,做一些基本的库出来。

我们为什么要自己去写库呢?

国外的库有很多,都是开源的。为什么还要自己写呢?因为,不管别人汽车跑得多快,从爬行到走路,还是得我们自己亲自来做的。别人替代不了。否则,我们只能是一个残障人士了。

2、做一个数值仿真的软件,需要哪些方面?

一个数值仿真软件,其实是一个很庞大的系统。涉及到的东西很多。简单说来包含三个部分。

(1)前处理

前处理,负责建立几何模型,也就是CAD的工作。我们熟知的solidworks,UG,3DMax等,都是可以玩成这样的工作。国内的,中望也有3D建模软件。包括,开源的像FreeCAD等。这个事本身就挺复杂的。

(2)计算

这个部分,包含网格剖分,和求解器两大部分。

网格剖分的软件,除了商业软件的内置的外,开源的,有gmsh,tetgen等。

求解器,就很多了,开源的有Calculix等。

计算部分的工作就是求解出方程的解来。也就是计算仿真的数据。然后交给后处理去处理。

(3)后处理

后处理的工作,就是做数据的分析和可视化的工作。以针对问题,对数据进行分析,并用我们可以理解的方式呈现出来。后处理就是为大家使用数据讲一个数据故事,提供工具。

3、代数计算和Eigen库

那么我们的主角Eigen库的作用是什么呢?

Eigen库是做矩阵运算和矩阵处理的。

每一个仿真计算,都是对方程的求解。一个方程的物理量是一个无穷维空间的事,通过有限元或者有限体积或者有限差分等方法,可以将无穷维空间的事,简化成一个有限维空间的事。这也就是为什么这些方法前面都要加一个“有限”两个字的原因。

数学里有一个定理,任何有限维空间的算子,都是一个矩阵

这就是为什么,我们在数值计算中要用到矩阵的原因,也就是为什么今天要说Eigen这个库。

4、Eigen库

上面这个列表,大概可以看出Eigen库的强大的功能。其主要的用途,就是求解矩阵方程。包括,特征值等矩阵的一系列的特征问题。稀疏矩阵的处理,等等。

以下是一些特性:

  • 支持整数、浮点数、复数,使用模板编程,可以为特殊的数据结构提供矩阵操作。比如在用ceres-solver进行做优化问题(比如bundle adjustment)的时候,有时候需要用模板编程写一个目标函数,ceres可以将模板自动替换为内部的一个可以自动求微分的特殊的double类型。而如果要在这个模板函数中进行矩阵计算,使用Eigen就会非常方便。
  • 支持逐元素、分块、和整体的矩阵操作。
  • 内含大量矩阵分解算法包括LU,LDLt,QR、SVD等等。
  • 支持使用Intel MKL加速
  • 部分功能支持多线程
  • 稀疏矩阵支持良好,到今年新出的Eigen3.3,已经自带了SparseLU、SparseQR、共轭梯度(ConjugateGradient solver)、bi conjugate gradient stabilized solver等解稀疏矩阵的功能。同时提供SPQR、UmfPack等外部稀疏矩阵库的接口。
  • 支持常用几何运算,包括旋转矩阵、四元数、矩阵变换、AngleAxis(欧拉角与Rodrigues变换)等等。
  • 更新活跃,用户众多(Google、WilliowGarage也在用),使用Eigen的比较著名的开源项目有ROS(机器人操作系统)、PCL(点云处理库)、Google Ceres(优化算法)。OpenCV自带到Eigen的接口。
  • 5、Qt上的配置

    我使用Qt来写,其实也不一定,只是习惯了。调用Eigen库的方式很简单。我就不在编译上花太多时间了。Eigen的官方地址提供了windows下的包。下载下来,就可以直接调用。

    Qt里只要在pro文件中增加库的地址就可以直接调用。非常方便。我是直接把eigen库放在qt根目录的,其实这样不好,可以单独做一个外部库的目录存放。

    这样,我们就可以做一个简单的测试了。这个案例包含,矩阵定义,向量定义,数据库的提取。


    #include <QCoreApplication>
    #include <iostream>
    #include <Eigen/Dense>
    typedef Eigen::MatrixXd Matrix ;
    typedef Eigen::VectorXd Vector ;
    
    using namespace std;
    int main(int argc, char *argv[])
    {
        QCoreApplication a(argc, argv);
        Matrix m(3,3) ;
        m<<1,2,3,
           4,5,6,
           7,8,9;
        Vector v(3);
        v<<1,2,3;
    //    cout<< "m*v"<<endl<<m*v<<endl;
        cout<<m.block(0,0,2,2)<<endl;
        cout<<m.block<2,2>(0,0)<<endl;
        //从0,0位置开始,向下向右,取1行2列。
        cout<<m.block(0,0,1,2)<<endl;
        cout<<m.block(0,0,3,1)<<endl;
        cout<<m.row(2)<<endl;
        m.row(2)<<11,12,13;
        cout<<m.row(2)<<endl;
        cout<<m<<endl;
        Matrix mm;
    //    mm.resize(1,3);
    //    mm<<4,5,6;
        mm=m;
        cout<<mm<<endl;
        return a.exec();
    }
    

    输出结果为:


    6、结束

    一个有限元库,需要大量的其他的第三方库的帮助。在求解器这个层面,最重要的库就是Eigen这样的矩阵运算库了。而做数值计算,最大的运算的时间也就在这个矩阵运算上了。


    最后,做一个调查,你知道的前处理,计算,后处理的库,都有哪些呢?软件都有哪些呢?

    请在下方留言。

    非常感谢您的支持和关注,我是张麟博士。

    举报
    评论 0