Main Content

このページの翻訳は最新ではありません。ここをクリックして、英語の最新版を参照してください。

原子のシミュレーションへの動的メモリ割り当ての使用

この例では、弾む原子のシミュレーションを実行し、ある反復回数後に結果を返す MATLAB アルゴリズムにコードを生成する方法ついて説明します。アルゴリズムが受け入れる原子数に上限はないため、この例では動的メモリ割り当てを利用します。

必要条件

この例には必要条件はありません。

関数 run_atoms について

関数 run_atoms.m は、弾む原子のシミュレーションを実行します (重力とエネルギー損失を考慮します)。

help run_atoms
  atoms = run_atoms(atoms,n)
  atoms = run_atoms(atoms,n,iter)
  Where 'atoms' the initial and final state of atoms (can be empty)
        'n' is the number of atoms to simulate.
        'iter' is the number of iterations for the simulation
           (if omitted it is defaulted to 3000 iterations.)

コード生成オプションの設定

コード生成構成オブジェクトを作成します。

cfg = coder.config;
% Enable dynamic memory allocation for variable size matrices.
cfg.DynamicMemoryAllocation = 'AllVariableSizeArrays';

サンプル入力の設定

入力パラメーター型に関する必要な情報がコンパイラに提供されるようにテンプレート構造体 'Atom' を作成します。原子は、直交座標で位置と速度を指定する 4 つのフィールド (x、y、vx、vy) をもつ構造です。

atom = struct('x', 0, 'y', 0, 'vx', 0, 'vy', 0);

テスト用の MEX 関数の生成

次の引数と共に codegen コマンドを使用します。

-args {coder.typeof(atom, [1 Inf]),0,0} は、最初の引数が原子の行ベクトルで、列数が無限となる場合があることを示します。2 番目と 3 番目の引数は、スカラー double 値です。

-config cfg は、ワークスペース変数 cfg で定義される動的メモリ割り当てを有効にします。

codegen run_atoms -args {coder.typeof(atom, [1 Inf]),0,0} -config cfg -o run_atoms_mex

MEX 関数の実行

MEX 関数は、原子の空のリストが与えられると、約 1000 の反復ステップで 10000 の原子のシミュレーションを実行します。戻り値は、シミュレーション完了後のすべての原子の状態です。

atoms = repmat(atom,1,0); 
atoms = run_atoms_mex(atoms,10000,1000)
Iteration: 50
Iteration: 100
Iteration: 150
Iteration: 200
Iteration: 250
Iteration: 300
Iteration: 350
Iteration: 400
Iteration: 450
Iteration: 500
Iteration: 550
Iteration: 600
Iteration: 650
Iteration: 700
Iteration: 750
Iteration: 800
Iteration: 850
Iteration: 900
Iteration: 950
Iteration: 1000
Completed iterations: 1000
atoms=1×10000 struct array with fields:
    x
    y
    vx
    vy

MEX 関数の再実行

500 の反復ステップを実行してシミュレーションを続行します。

atoms = run_atoms_mex(atoms,10000,500)
Iteration: 50
Iteration: 100
Iteration: 150
Iteration: 200
Iteration: 250
Iteration: 300
Iteration: 350
Iteration: 400
Iteration: 450
Iteration: 500
Completed iterations: 500
atoms=1×10000 struct array with fields:
    x
    y
    vx
    vy

スタンドアロン C コード ライブラリの生成

C ライブラリを生成するには、以下のようにライブラリの標準構成オブジェクトを作成します。

cfg = coder.config('lib');

動的メモリ割り当てを有効にします。

cfg.DynamicMemoryAllocation = 'AllVariableSizeArrays';

MATLAB での既定のデータ型は double です。ただし、C コードでは通常は整数が使用されるため、ここでは原子の数と反復回数を表すサンプル値として int32 型の整数を渡します。

codegen run_atoms -args {coder.typeof(atom, [1 Inf]),int32(0),int32(0)} -config cfg

生成されたコードの検証

ライブラリを作成すると、フォルダー codegen/lib/run_atoms/ の中にコードが生成されます。このフォルダー内のコードは、自己完結しています。生成されたヘッダー ファイルとライブラリ ファイルがあれば、コンパイルされた C コードとのインターフェイスを取ることができます。

dir codegen/lib/run_atoms
.                       rtGetNaN.o              run_atoms_emxAPI.o      
..                      rt_nonfinite.c          run_atoms_emxutil.c     
.gitignore              rt_nonfinite.h          run_atoms_emxutil.h     
buildInfo.mat           rt_nonfinite.o          run_atoms_emxutil.o     
codeInfo.mat            rtw_proj.tmw            run_atoms_initialize.c  
codedescriptor.dmr      rtwtypes.h              run_atoms_initialize.h  
compileInfo.mat         run_atoms.a             run_atoms_initialize.o  
defines.txt             run_atoms.c             run_atoms_ref.rsp       
examples                run_atoms.h             run_atoms_rtw.mk        
interface               run_atoms.o             run_atoms_terminate.c   
rtGetInf.c              run_atoms_data.c        run_atoms_terminate.h   
rtGetInf.h              run_atoms_data.h        run_atoms_terminate.o   
rtGetInf.o              run_atoms_data.o        run_atoms_types.h       
rtGetNaN.c              run_atoms_emxAPI.c      
rtGetNaN.h              run_atoms_emxAPI.h      

C の Main 関数の作成

通常、main 関数はレンダリングまたはその他の処理を実行するプラットフォームに依存したコードです。この例では、純粋な ANSI-C 関数を使用して、原子のシミュレーションの最終的な状態 (実行時) を含んでいるファイル run_atoms_state.m を生成します。

type run_atoms_main.c
/* Include standard C libraries */
#include <stdio.h>

/* The interface to the main function we compiled. */
#include "codegen/exe/run_atoms/run_atoms.h"

/* The interface to EMX data structures. */
#include "codegen/exe/run_atoms/run_atoms_emxAPI.h"

int main(int argc, char **argv)
{
    FILE *fid;
    int i;
    emxArray_Atom *atoms;
 
    /* Main arguments unused */
    (void) argc;
    (void) argv;
    
    /* Initially create an empty row vector of atoms (1 row, 0 columns) */
    atoms = emxCreate_Atom(1, 0);
    
    /* Call the function to simulate 10000 atoms in 1000 iteration steps */
    run_atoms(atoms, 10000, 1000);
    
    /* Call the function again to do another 500 iteration steps */
    run_atoms(atoms, 10000, 500);
    
    /* Print the result to a file */
    fid = fopen("atoms_state.txt", "w");
    for (i = 0; i < atoms->size[1]; i++) {
        fprintf(fid, "%f %f %f %f\n",
            atoms->data[i].x, atoms->data[i].y, atoms->data[i].vx, atoms->data[i].vy);
    }
    
    /* Close the file */
    fclose(fid);
    
    /* Free memory */
    emxDestroyArray_Atom(atoms);
    return(0);
}

実行可能ファイル用の構成オブジェクトの作成

cfg = coder.config('exe');
cfg.DynamicMemoryAllocation = 'AllVariableSizeArrays';

スタンドアロン実行可能ファイルの生成

関数 (run_atoms.m) とカスタム C コード (run_atoms_main.c) を渡さなければなりません。codegen コマンドは、最初に MATLAB コードから C コードを自動的に生成します。次に、生成されたこのコードをカスタム C コード (run_atoms_main.c) とまとめるために C コンパイラを起動します。

codegen run_atoms run_atoms_main.c -args {coder.typeof(atom, [1 Inf]),int32(0),int32(0)} -config cfg

実行可能ファイルの実行

シミュレーション完了後に、ファイル atoms_state.txt を生成します。この TXT ファイルは 10000x4 の行列で、各行は原子の位置と速度 (x, y, vx, vy) であり、システム全体の現在の状態を表します。

system(['.' filesep 'run_atoms']);

状態の取得

実行可能ファイルを実行すると atoms_state.txt が生成されました。次に、保存された行列から構造体配列を再作成します。

load atoms_state.txt -ascii
clear atoms
for i = 1:size(atoms_state,1)
    atoms(1,i).x  = atoms_state(i,1);
    atoms(1,i).y  = atoms_state(i,2);
    atoms(1,i).vx = atoms_state(i,3);
    atoms(1,i).vy = atoms_state(i,4);
end

状態のレンダリング

反復回数がゼロの run_atoms_mex をレンダリング専用に呼び出します。

run_atoms_mex(atoms, 10000, 0);