1

我有一个希望转换为 MEX 文件的函数(代码如下)。我正在尝试使用 matlab 编码器来做到这一点。

%% Inputs
dof = 3;
num_divs = 72;

ind_cr =
     0     0
     1     1
     1     2
     2     2
     1     3
     2     3
     3     3

ind_switch =
     1
     1
     1
     0
     1
     0
     0

len_stat_atoms =
           1
          72
        5184
          72
      373248
        5184
          72

num_stat_atoms =
   108
   111
   111
     3
   111
     3
     3

coordFile = 
    [3x1        double]
    [3x1        double]
    [3x72x3     double]
    [3x5184x3   double]
    [3x373248x4 double]

radii_cell = 
    [108x1x3      double]
    [111x72x3     double]
    [111x5184x3   double]
    [  3x72x3     double]
    [111x373248x4 double]
    [  3x5184x4   double]
    [  3x72x4     double]

stat_cell = 
    [3x1x108      double]
    [3x72x111     double]
    [3x5184x111   double]
    [3x72x3       double]
    [3x373248x111 double]
    [3x5184x3     double]
    [3x72x3       double]    


%% Code that calls function
for i = 1:(dof*(dof+1)/2+1)
    %% Load matrices
    radii_mat = radii_cell{i,1};
    stat_mat = stat_cell{i,1};
    if ind_switch(i)
        coordFile_mat = coordFile{ind_cr(i,2)+2};
    end
    %% Call the function
    potential_mat = func_test(i,coordFile_mat,radii_mat,stat_mat,...
        ind_cr,len_stat_atoms,num_stat_atoms,num_coord_atoms,...
        counter,num_divs,dof);
end


%% Function code
function potential_mat = func_test(i,coordFile_mat,radii_mat,stat_mat,...
    ind_cr,len_stat_atoms,num_stat_atoms,num_coord_atoms,...
    counter,num_divs,dof);

potential_mat = zeros(num_coord_atoms,num_divs^dof);
for j = 1:size(coordFile_mat,3)
    %% Compute distances
    a = zeros(3,len_stat_atoms(i));
    a = coordFile_mat(:,1:len_stat_atoms(i),j);

    b = zeros(3,len_stat_atoms(i),num_stat_atoms(i));
    b = repmat(a,[1 1 num_stat_atoms(i)]);

    c = zeros(1,len_stat_atoms(i),num_stat_atoms(i));
    c = sqrt(sum((b - stat_mat).^2,1));

    d = zeros(len_stat_atoms(i),num_stat_atoms(i));
    d = shiftdim(c,1);

    distances = zeros(num_stat_atoms(i),len_stat_atoms(i));
    distances = d';

    %% Compute clashes and potentials
    clashes = distances < radii_mat(:,:,j);
    potentials = zeros(size(distances));
    potentials(clashes) = (1-(distances(clashes)./radii_mat(find(clashes)+numel(clashes)*(j-1))).^6).^2;

    %% Iterate over nodes
    col = ind_cr(i,1); row = ind_cr(i,2);
    if col == 1
        ind_kron = repmat(1:size(potentials,2),[num_divs^(dof-row) 1]);
        potentials = potentials(:,ind_kron(:)');
    elseif row == dof
        vec_repmat = [1 num_divs^(col-1)];
        potentials = repmat(potentials,vec_repmat);
    elseif col > 0
        vec_repmat = [1 num_divs^(col-1)];
        ind_kron = repmat(1:size(potentials,2),[num_divs^(dof-row) 1]);
        potentials = repmat(potentials(:,ind_kron(:)'),vec_repmat);
    else
        potentials = repmat(sum(potentials),[1 num_divs^dof]);
    end
    counter = counter+1;
    potential_mat(counter,:) = sum(potentials,1);
end

end

问题出现在下面的第二行,因为它无法转置 ND 矩阵而引发错误。

d = shiftdim(c,1);
distances = d';

Matlab 编码器识别c为 size 1 x :? x :?,这是正确的。然后该d = shiftdim(c,1)线应产生一个大小为 2D 的矩阵:? x :?,然后我将其转置。但是,它未能正确移动 的尺寸d,并赋予其尺寸:? x :? x :?。这会导致转置错误。我该如何解决这个问题?此外,为了我自己的启迪,为什么 matlab 编码器无法正确分配我的变量的维度,特别a是 、bcddistances

4

1 回答 1

1

文档将其描述为在确定可变大小 ND 数组的大小时与 MATLAB 不兼容d在循环中创建,因此似乎是可变大小):

对于可变大小的 ND 数组,size 函数在生成的代码中返回的结果可能与在 MATLAB 中不同。在生成的代码中,size(A) 返回一个固定长度的输出,因为它不会丢弃可变大小 ND 数组的尾随单例维度。相比之下,MATLAB中的 size(A)返回可变长度输出,因为它会丢弃尾随单例维度

例如,如果数组的形状A:?x:?x:?and size(A,3)==1,则size(A)返回:

  • 生成代码中的三元素向量
  • MATLAB 代码中的二元素向量

上述文档中解决的问题与size函数的使用有关。但是,在您的情况下,您只希望能够转置。解决方法是使用permute,因为转置是 的一般情况permute

% after shiftdim:
distances = permute(d,[2 1 3])   % same as d' for 2d array, but handles 3d

您也可以shiftdim完全删除:

distances = permute(c,[2 3 1])

另外,我对 Coder 没有太多经验,但它真的需要所有这些初始化zeros吗?他们似乎没有必要。

于 2014-11-11T21:22:44.537 回答