美文网首页
如何计算出有限元函数在某一点的值

如何计算出有限元函数在某一点的值

作者: 马鹏飞_47c5 | 来源:发表于2020-10-21 21:31 被阅读0次

如何计算出有限元函数在某一点的值

A_i为的局部坐标,\hat{A_i}为参考坐标,从参考单元到局部单元的坐标变换可表示为:
$$
\begin{gathered}
\begin{pmatrix} x\ y \ z\end{pmatrix} =
\begin{pmatrix}
x_2-x_1 & x_3-x_1 & x_4-x_1 \
y_2-y_1 & y_3-y_1 & y_4-y_1 \
z_2-z_1 & z_3-z_1 & z_4-z_1
\end{pmatrix}
\begin{pmatrix}
\hat x\ \hat y \\hat z
\end{pmatrix}+
\begin{pmatrix}
x_1\x_2\x_3
\end{pmatrix}

\end{gathered}
$$
可以简写成A=F\hat{A}+A_1,反过来可以写成\hat{A}=F^{-1}A-F^{-1}A_1

局部坐标系下的的任意一函数f(A),我们都可以写成关于x,y,z的多项式,这个多项式也可以用\hat x, \hat y ,\hat z表示。我们知道,对应参考坐标A_i和局部坐标系\hat{A_i}是相对应的,即f(A_i)=\hat{f}(\hat{A_i})。根据
\begin{pmatrix} 1&\hat x_1&\hat y_1&\hat z_1&\hat x_1\hat y_1&\hat x_1\hat z_1&\hat y_1\hat z_1&\hat x_1^2&\hat y_1^2&\hat z_1^2\\ 1&\hat x_1&\hat y_1&\hat z_1&\hat x_1\hat y_1&\hat x_1\hat z_1&\hat y_1\hat z_1&\hat x_1^2&\hat y_1^2&\hat z_1^2\\1&\hat x_1&\hat y_1&\hat z_1&\hat x_1\hat y_1&\hat x_1\hat z_1&\hat y_1\hat z_1&\hat x_1^2&\hat y_1^2&\hat z_1^2\\1&\hat x_1&\hat y_1&\hat z_1&\hat x_1\hat y_1&\hat x_1\hat z_1&\hat y_1\hat z_1&\hat x_1^2&\hat y_1^2&\hat z_1^2\\1&\hat x_1&\hat y_1&\hat z_1&\hat x_1\hat y_1&\hat x_1\hat z_1&\hat y_1\hat z_1&\hat x_1^2&\hat y_1^2&\hat z_1^2\\1&\hat x_1&\hat y_1&\hat z_1&\hat x_1\hat y_1&\hat x_1\hat z_1&\hat y_1\hat z_1&\hat x_1^2&\hat y_1^2&\hat z_1^2\\1&\hat x_1&\hat y_1&\hat z_1&\hat x_1\hat y_1&\hat x_1\hat z_1&\hat y_1\hat z_1&\hat x_1^2&\hat y_1^2&\hat z_1^2\\1&\hat x_1&\hat y_1&\hat z_1&\hat x_1\hat y_1&\hat x_1\hat z_1&\hat y_1\hat z_1&\hat x_1^2&\hat y_1^2&\hat z_1^2\\1&\hat x_1&\hat y_1&\hat z_1&\hat x_1\hat y_1&\hat x_1\hat z_1&\hat y_1\hat z_1&\hat x_1^2&\hat y_1^2&\hat z_1^2\\1&\hat x_1&\hat y_1&\hat z_1&\hat x_1\hat y_1&\hat x_1\hat z_1&\hat y_1\hat z_1&\hat x_1^2&\hat y_1^2&\hat z_1^2\\ \end{pmatrix} \begin{pmatrix} a\\b\\c\\d\\e\\f\\g\\h\\i\\j \end{pmatrix} = \begin{pmatrix} f(\hat{A_i})\\f(\hat{A_i})\\f(\hat{A_i})\\f(\hat{A_i})\\f(\hat{A_i})\\ f(\hat{A_i})\\f(\hat{A_i})\\f(\hat{A_i})\\f(\hat{A_i})\\f(\hat{A_i})\\ \end{pmatrix}
可以计算出多项式的系数a,b,c,d,e,f,g,h,i,j。上式左边的矩阵G可以提前算出,记为G^{-1},右端项记为B

回到原来的问题,如何计算出有限元函数在某一点的值?

  1. 获取坐标A_i,函数值f(A_i)
  2. 计算矩阵F^{-1},再根据给定坐标A,计算\hat{A}=F^{-1}A-F^{-1}A_1
  3. \hat A计算出基函数(1 x y z xy xz yz x^2 y^2 z^2)
  4. 根据给定的B和矩阵G^{-1}计算出系数
  5. 基函数和系数做点积。

代码

首先要有一个计算基函数的函数

std::vector<double>& evaluate_basis_at_point(std::vecor<double> &point){
    std::vector<double> basis(10);
    basis[0] = 1.0;
    basis[1] = point[0];
    basis[2] = point[1];
    basis[3] = point[2];
    basis[4] = point[0]*point[1];
    basis[5] = point[0]*point[2];
    basis[6] = point[1]*point[2];
    basis[7] = point[0]*point[0];
    basis[8] = point[1]*point[1];
    basis[9] = point[2]*point[2];
    return basis;
}

1. 计算F^{-1}

假设我们的局部坐标A_i是4个3维的向量,用matlab进行符号计算:

syms x0 x1 x2 x3;
syms y0 y1 y2 y3;
syms z0 z1 z2 z3;

F = [x0-x1 x0-x2 x0-x3;
     y0-y1 y0-y2 y0-y3;
     z0-z1 z0-z2 z0-z3];
 
simplify(inv(F))

化简可以得到:

det = (x0*y1*z2 - x0*y2*z1 - x1*y0*z2 + x1*y2*z0 + x2*y0*z1 - x2*y1*z0 - x0*y1*z3 + x0*y3*z1 + x1*y0*z3 - x1*y3*z0 - x3*y0*z1 + x3*y1*z0 + x0*y2*z3 - x0*y3*z2 - x2*y0*z3 + x2*y3*z0 + x3*y0*z2 - x3*y2*z0 - x1*y2*z3 + x1*y3*z2 + x2*y1*z3 - x2*y3*z1 - x3*y1*z2 + x3*y2*z1)
[  (y0*z2 - y2*z0 - y0*z3 + y3*z0 + y2*z3 - y3*z2)/det,
  -(x0*z2 - x2*z0 - x0*z3 + x3*z0 + x2*z3 - x3*z2)/det,  
   (x0*y2 - x2*y0 - x0*y3 + x3*y0 + x2*y3 - x3*y2)/det]
[ -(y0*z1 - y1*z0 - y0*z3 + y3*z0 + y1*z3 - y3*z1)/det,
   (x0*z1 - x1*z0 - x0*z3 + x3*z0 + x1*z3 - x3*z1)/det,
  -(x0*y1 - x1*y0 - x0*y3 + x3*y0 + x1*y3 - x3*y1)/det]
[  (y0*z1 - y1*z0 - y0*z2 + y2*z0 + y1*z2 - y2*z1)/det, 
  -(x0*z1 - x1*z0 - x0*z2 + x2*z0 + x1*z2 - x2*z1)/det,
   (x0*y1 - x1*y0 - x0*y2 + x2*y0 + x1*y2 - x2*y1)/det]
 

写成C++代码是

double det = (x[0]*y[1]*z[2] - x[0]*y[2]*z[1] - x[1]*y[0]*z[2] + x[1]*y[2]*z[0] + x[2]*y[0]*z[1] - x[2]*y[1]*z[0] - x[0]*y[1]*z[3] + x[0]*y[3]*z[1] + x[1]*y[0]*z[3] - x[1]*y[3]*z[0] - x[3]*y[0]*z[1] + x[3]*y[1]*z[0] + x[0]*y[2]*z[3] - x[0]*y[3]*z[2] - x[2]*y[0]*z[3] + x[2]*y[3]*z[0] + x[3]*y[0]*z[2] - x[3]*y[2]*z[0] - x[1]*y[2]*z[3] + x[1]*y[3]*z[2] + x[2]*y[1]*z[3] - x[2]*y[3]*z[1] - x[3]*y[1]*z[2] + x[3]*y[2]*z[1])
double F[3][3] ={
    
    { (y[0]*z[2] - y[2]*z[0] - y[0]*z[3] + y[3]*z[0] + y[2]*z[3] - y[3]*z[2])/det,
     -(x[0]*z[2] - x[2]*z[0] - x[0]*z[3] + x[3]*z[0] + x[2]*z[3] - x[3]*z[2])/det,  
      (x[0]*y[2] - x[2]*y[0] - x[0]*y[3] + x[3]*y[0] + x[2]*y[3] - x[3]*y[2])/det},

    {-(y[0]*z[1] - y[1]*z[0] - y[0]*z[3] + y[3]*z[0] + y[1]*z[3] - y[3]*z[1])/det,
      (x[0]*z[1] - x[1]*z[0] - x[0]*z[3] + x[3]*z[0] + x[1]*z[3] - x[3]*z[1])/det,
     -(x[0]*y[1] - x[1]*y[0] - x[0]*y[3] + x[3]*y[0] + x[1]*y[3] - x[3]*y[1])/det},

    { (y[0]*z[1] - y[1]*z[0] - y[0]*z[2] + y[2]*z[0] + y[1]*z[2] - y[2]*z[1])/det, 
     -(x[0]*z[1] - x[1]*z[0] - x[0]*z[2] + x[2]*z[0] + x[1]*z[2] - x[2]*z[1])/det,
      (x[0]*y[1] - x[1]*y[0] - x[0]*y[2] + x[2]*y[0] + x[1]*y[2] - x[2]*y[1])/det}
}

2. 计算\hat{A}

std::vector<double>& evaluate_basis_at_point(std::vecor<double> &point, double **F){
    std::vector<double> hat_point(3);
    for(size_t i=0;i<3;i++){
        hat_point[0] += F[0][i]*point[i];
        hat_point[1] += F[1][i]*point[i];
        hat_point[2] += F[2][i]*point[i];
    }
    for(size_t i=0;i<3;i++){
        hat_point[0] -= F[0][i]*point1[i];
        hat_point[1] -= F[1][i]*point1[i];
        hat_point[2] -= F[2][i]*point1[i];
    }
    return hat_point;
}

3. \hat A_i

std::vector<double> p0{0.0,0.0,0.0};
std::vector<double> p1{0.5,0.0,0.0};
std::vector<double> p2{1.0,0.0,0.0};
std::vector<double> p3{0.0,0.5,0.0};
std::vector<double> p4{0.0,1.0,0.0};
std::vector<double> p5{0.5,0.5,0.0};
std::vector<double> p6{0.0,0.0,0.5};
std::vector<double> p7{0.0,0.5,0.5};
std::vector<double> p8{0.5,0.0,0.5};
std::vector<double> p9{0.0,0.0,1.0};
auto b1 = evaluate_basis_at_point{p1};
auto b1 = evaluate_basis_at_point{p1};
auto b1 = evaluate_basis_at_point{p1};
auto b1 = evaluate_basis_at_point{p1};
auto b1 = evaluate_basis_at_point{p1};
auto b1 = evaluate_basis_at_point{p1};
auto b1 = evaluate_basis_at_point{p1};
auto b1 = evaluate_basis_at_point{p1};
auto b1 = evaluate_basis_at_point{p1};
auto b1 = evaluate_basis_at_point{p1};

// 利用eigen求逆得到一个10*10的矩阵G_inv,以备用。

4.基函数

// hat_point 是计算出来的参考点
// B 是各个自由度上的值
b = evaluate_basis_at_point(hat_point);
parameters = multiply(B, G_inv);
result = multiply(b, parameters);
// 如果B是多维的,那么就有多个B。

相关文章

  • 如何计算出有限元函数在某一点的值

    如何计算出有限元函数在某一点的值 令为的局部坐标,为参考坐标,从参考单元到局部单元的坐标变换可表示为:$$\beg...

  • 有限元的基函数和高斯积分

    有限元的基函数 何晓明的ppt上将参考元上的基函数通过变量替换计算出局部单元上的基函数,个人认为这没有普遍性,PP...

  • 插值与多项式逼近

    插值与多项式逼近 关于插值,是利用已知函数上的点及其函数值,对某一点求函数值。数学图像上,表现为两个函数形状的相似...

  • 第5章 字段调整(函数)

    5.1 函数简介 函数的作用: 计算工作 有时Excel表格会有缺失值,需要通过函数计算出相关信息并补齐。 例如,...

  • 梯度下降法学习笔记

    1 相关概念 梯度——表示某一函数在该点处的方向导数沿着该方向取得最大值,即函数在该点处沿着该方向(此梯度的方向)...

  • Python 基础系列--函数

    在中学数学中我们知道 y=f(x) 代表着函数,x 是自变量,y 是函数 f(x) 的值,给定 x 可以计算出对应...

  • 数值分析:插值与拟合

    1 插值 定义 设函数在区间上的个点,上的函数值为,若粗在函数,使成立,则称函数为的 插值函数,称为被插值函数,点...

  • 梯度下降法

    梯度:本意是一个向量(矢量),表示某一函数在该点处的方向导数沿着该方向取得最大值,即函数在该点处沿着该方向(此梯度...

  • 2020-07-07

    函数在某一点可导,说明函数的极限存在f(a+0)= f(a-0),函数连续在某一点左导数等于右导数** 讨论函数在...

  • 高等数学基础07:梯度

    梯度的本意是一个向量(矢量),表示某一函数在该点处的方向导数沿着该方向取得最大值,即函数在该点处沿着该方向(此梯度...

网友评论

      本文标题:如何计算出有限元函数在某一点的值

      本文链接:https://www.haomeiwen.com/subject/kkqymktx.html