MotionSolveのカスタム関数の記述

以下の手順で、MotionSolve入力デックのカスタム関数の記述方法について説明します。例では、MotionSolvePythonスクリプトサポートを利用します。付録Aには、Cプログラミング言語を使用して記述されたカスタム関数の例が含まれています。

カスタムマッピングファイルの作成

次のXML要素をコピーしてファイル(C:/test/my_custom_mapping.xmlなど)に貼り付けます。
  <?xml version="1.0"?>
  <!-- MotionSolve custom mapping definition file -->
  <MSolve_Custom_Mapping>
    <CustomFunction
        symbol           = "MyCustomFnc"
        interpreter      = "Python"
        script_name      = "C:/my_python_scripts/test.py"
        usrsub_fnc_name  = "CustomFnc"      
        num_param        = "5"
    /> 
  </MSolve_Custom_Mapping>

パラメータsymbolで定義された名前は、MotionSolveによってカスタム関数名として使用されます。つまり、symbolの名前は、パラメータscript_nameで定義されたスクリプトファイル内に含まれるパラメータusrsub_fnc_nameで定義された関数の別名にすぎません。そのため、スクリプトファイル(この場合はtest.py)にはメソッドCustomFncが含まれているはずです。

環境変数の定義

環境変数MS_CUSTOM_MAPPING_FILEを定義して設定します。


図 1.

上記手順を完了すると、カスタム関数MyCustomFnc(..,..)CUBSPL(..)などの適切なMotionSolve式として使用できるようになります。

解釈されたスクリプトの代わりにコンパイルされたCコードを利用するユーザーサブルーチンを使用する場合には、上記と同じ手順を使用できます。この場合、カスタム関数を次のように定義する必要があります:
<CustomFunction
    symbol           = "MyCustomFnc"
    usrsub_dll_name  = "valid_path_name"
    usrsub_fnc_name  = "CustomFnc"
    num_param        = "5"
  />

付録A

下の例は、マーカーJの単位軸とマーカーIの別の単位軸のドット積を計算するために記述されたカスタム関数を示しています。

DOT1(I,1,J,3) = UVX(I)*UVZ(J).

<!-- Custom Function Mapping section-->
  
  <CustomFunction
      symbol           = "DOT1"
      usrsub_dll_name  = "NULL"
      usrsub_fnc_name  = "VARSUB_DOT1"
      num_param        = "4"
  />
DOT1に関連付けられた対応するusersubの実装:
DLLFUNC void STDCALL VARSUB_DOT1 
                  (int *id, double *time, double *par, int *npar,  int *dflag, int *iflag, double *value)
{
    int nstates,errflg;
    int i_marker_id = (int)par[0];
    int i_axis_idx = (int)par[1];
    int j_marker_id = (int)par[2];
    int j_axis_idx = (int)par[3];
    double axis_i[3], axis_j[3];
    switch (i_axis_idx)
    {
    case 1:
        c_sysary("uvx",&i_marker_id,1,axis_i, &nstates, &errflg);
        break;
    case 2:
        c_sysary("uvy",&i_marker_id,1,axis_i, &nstates, &errflg);
        break;
    case 3:
        c_sysary("uvz",&i_marker_id,1,axis_i, &nstates, &errflg);
        break;
    default:
        break;
    }
    switch (j_axis_idx)
    {
    case 1:
        c_sysary("uvx",&j_marker_id,1,axis_j, &nstates, &errflg);
        break;
    case 2:
        c_sysary("uvy",&j_marker_id,1,axis_j, &nstates, &errflg);
        break;
    case 3:
        c_sysary("uvz",&j_marker_id,1,axis_j, &nstates, &errflg);
        break;
    default:
        break;
    }
    *value = axis_i[0]*axis_j[0]+axis_i[1]*axis_j[1]+axis_i[2]*axis_j[2];
}

これで、関数DOT1を使用できます。例えば、DOT1(I,1,J,3)は単にUVX(I)*UVZ(J)になります。