为 d 维中的 i 阶偏导数生成模式

Posted

技术标签:

【中文标题】为 d 维中的 i 阶偏导数生成模式【英文标题】:Generate a pattern for i-th order partial derivative in d-dimension 【发布时间】:2016-12-27 16:24:14 【问题描述】:

我正在尝试制定一个有限元代码,我需要在其中计算 d 维的偏导数。在有限元中基函数N(x,y,z)=N(x)N(y)N(z),所以一阶导数为:

N(x)'N(y)N(z) N(x)N(y)'N(z) N(x)N(y)N(z)'

二阶导数是

N(x)''N(y)N(z) N(x)'N(y)'N(z) N(x)'N(y)N(z)' N(x)N(y)''N(z) N(x)N(y)N(z)' N(x)N(y)N(z)''

我想要一个带有输入 (i,d) 的函数来告诉我下表中的这些模式:

我认为必须有一个简单的算法来实现这个目标。有人可以给我一些帮助吗?太棒了

【问题讨论】:

请注意,术语的数量是choose (i + d - 1, i):您必须列出所有交错的方法i“对当前术语求导”操作和d - 1“继续下一个术语”行动。 您的意思是对于 3D 中的二阶导数,问题是从 (4,2) 的矩阵中选择吗? 他的意思是combinatorial choose 感谢您的解释@NimrodMorag,这正是与重复问题的组合。 【参考方案1】:

这可以通过嵌套循环来解决:

int * part_deriv(int i, int d)
    int *res;
    int *curr;
    int num_el = fact(i+d-1) / ( fact(i) * fact(d-1) ); //fact() is the factorial function
    int el_size = d*sizeof(int);
    int el;

    res = calloc(num_el,el_size);
    curr = calloc(d,sizeof(int));
    *curr = i;
    memcpy(res,curr,el_size); //put the first element in the array

    el = 0;
    while(el<num_el)
       if(*curr != 0)
           for( d_idx = 1 ; d_idx<d ; d_idx++, *cur++)
              *curr--; // "move" one derivative from the first variable to 'd_idx' variable
              *(curr+d_idx)++;
              el++;
              memcpy(res+(el*el_size),curr,el_size); //put the element in the array
           
           *curr--;
        else
           break; //shouldn't be reached, but added to be sure
       
    
    return res;

我还没有完全理解你想如何输出结果,所以你可以解析我以d为块输出的数组。

【讨论】:

【参考方案2】:

i'th 导数的模式视为基数-i+1 整数。出现了不错的序列。例如,在二维情况下,它们是

0
2, 1
6, 4, 2
12, 9, 6, 3
20, 16, 12, 8, 4

等等

【讨论】:

【参考方案3】:

我是通过调用函数递归实现的。

#include <vector>
#include <iostream>
using namespace std;


void func (int d, int i, vector<int> &k, int n, int start, vector<vector<int>> &a)
    if (n==i)
    
        vector<int> m;
        int it=0;
            for(int it1=0;it1<d;++it1)
                int amount=0;
                while(find(k.begin(),k.end(),it)!= k.end())
                    amount++;
                    it++;
                
                m.push_back(amount);
                it++;
            
        a.push_back(m);
    
    else
        for(int jj=start;jj<d+i-(i-n);++jj)
            k[n]=jj;
            func(d,i,k,n+1,jj+1, a
                 );
        
    

vector<vector<int>> test(int d, int i)
    vector<int> kk(i);
    vector<vector<int>> a;
    func(d,i,kk,0,0, a);
    return a;

int main()
    auto f = test(4,2);
    for(auto it1=f.begin();it1!=f.end();++it1)
        for(auto it2= it1->begin();it2!=it1->end();++it2)
            cout<<*it2<<" ";
         cout<<endl;
    


这是我对 i=2,d=4 的结果:

2 0 0 0 
1 1 0 0 
1 0 1 0 
1 0 0 1 
0 2 0 0 
0 1 1 0 
0 1 0 1 
0 0 2 0 
0 0 1 1 
0 0 0 2 

【讨论】:

以上是关于为 d 维中的 i 阶偏导数生成模式的主要内容,如果未能解决你的问题,请参考以下文章

泰勒公式中,一阶导数怎么求?

一元函数的梯度和雅可比矩阵是否想用

求多变量函数的最小值

Hessian矩阵

opencv python:图像梯度

matlab数值微分函数是啥?