有限元笔记2-方程求解

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/walkandthink/article/details/51914314

在有限元计算中,方程求解的运算主要针对稀疏矩阵来进行。针对稀疏矩阵计算的包,目前最快的应该是intel之家优化的mkl库,以及特别针对稀疏矩阵直接求解的库Pardiso。这两者目前都是非常成功的库,唯一的缺点就是要钱。本文这里介绍另外一个非常优秀的开源数值计算库Eigen。在使用时,无需安装,下载压缩包后解压缩,然后将该文件夹加入你的include路径里面就可以直接使用。

本文这里主要用了Dense Matrix和Sparse Matrix两种不同类型的矩阵来进行计算,计算结果与Matlab进行对比。

首先是Dense Matrix,其变量申明非常简单 MatrixXd A(n,n)就能得到一个double类型的 nn 的矩阵。稀疏矩阵变量的申明类似:SparseMatrix <double> A(n,n),稀疏矩阵在计算前记得做一次makecompress的操作,不然求解过程可能出错。具体计算代码如下:

#include <iostream>
#include <cstdlib>
#include <ctime>

#include "Eigen/Eigen"
#include "Eigen/Dense"
#include  "Eigen/Core"
#include "Eigen/Sparse"
#include "Eigen/SparseLU"

using namespace std;
using namespace Eigen;

int main()
{
    int n, i, j, k, num, ii, jj;
    cout << "Input N:";
    cin >> n;
    MatrixXd DenseA(n, n);
    SparseMatrix<double> SparseA(n, n);
    VectorXd F(n), DenseX(n), SparseX(n);
    srand(unsigned(time(00)));

    for (i = 0; i < n; i++)
    {
        for (j = 0; j < n; j++)
        {
            DenseA(i, j) = (1 + rand() % 500) / 500.0;
            SparseA.coeffRef(i, j) = (1 + rand() % 500) / 500.0;
        }
        F(i) = (1 + rand() % 500) / 500.0;
        num = rand() % n;
        for (ii = 0; ii < num; ii++)
        {
            jj = rand() % n;
            SparseA.coeffRef(i, jj) = 0.0;
        }
    }


    cout << "The Dense Matrix is:" << endl << DenseA << endl;
    cout << "The Sparse Matrix is:" << endl << SparseA << endl;
    cout << "The Vector F is:" << endl << F << endl;

    //Solve the dense matrix
    DenseX = DenseA.colPivHouseholderQr().solve(F);

    //make sparse compress
    SparseA.makeCompressed();
    //use sparse ldlt solver to solve AX=F equation
    SparseLU<SparseMatrix<double> > solver;
    solver.compute(SparseA);
    SparseX = solver.solve(F);
    cout << "The dense matrix result is:" << endl << DenseX << endl;
    cout << "The sparse matrix result is:" << endl << SparseX << endl;
    return 0;
}

以上代码在VS2013下可以运行,如果是gcc环境可能需要做一些调整。

矩阵的具体系数以及右端项的系数在Matlab代码中可以看到,并且也做了结果对比。Matlab代码如下:

clear all;close all;clc;
DA=[0.388  0.28 0.346 0.208 0.022 0.478 0.074  0.81;
0.276 0.364 0.344 0.482 0.168 0.938 0.702 0.004;
0.748 0.862  0.53 0.552 0.854 0.906  0.55 0.886;
0.722  0.94 0.388 0.428 0.808 0.658 0.958 0.438;
 0.47  0.37 0.154  0.87 0.932 0.808  0.07 0.354;
0.348 0.532 0.362 0.278 0.916   0.2 0.876  0.28;
0.232 0.442  0.26  0.81 0.224 0.656 0.618 0.926;
0.152 0.176  0.24 0.334 0.294 0.442 0.012 0.026];

SA=[0 0.226 0 0.034 0.516 0.192 0.512 0;
0.196 0.18 0.292 0.066 0.444 0.246 0 0;
0.038 0.738 0.354 0.362 0.408 0.206 0.808 0;
0.982 0 0.668 0.684 0.818 0 0.612 0;
0.038 0.496 0 0 0.618 0.552 0.264 0.168;
0 0.4 0 0.866 0.736 0.69 0.334 0.226;
0.08 0 0 0.524 0 0.2 0 0;
0.174 0.54 0 0.28 0 0.32 0.154 0];
F=[0.3;
0.886;
0.562;
0.704;
  0.7;
0.656;
0.876;
 0.84];
DX=DA\F;
SX=SA\F;
fprintf('Dense Result<-------->Sparse Result\n');
for i=1:size(DX,1)
    fprintf('%f<----------->%f\n',DX(i),SX(i));
end

计算结果对比:
这里写图片描述

这里写图片描述

这里写图片描述

猜你喜欢

转载自blog.csdn.net/walkandthink/article/details/51914314