(前頁)<<      >>(次頁)          (Up)

3章 CommonMPの要素モデルを作成する
3.6 他の要素モデルから計算結果を 受け取る


 前の章で 要素モデルが計算した結果を 別な要素モデルへ送る方法を実装しました。
 この章では 他の要素モデルが計算した結果を受信する処理を実装していきいます。

 要素モデルの送信機能を実装するには、

@送信パターンの設定
  Factoryクラス: モデルプロパティ情報設定メソッド( CreateModelProperty )

A送信接続チェック
  要素モデルクラス: 出力側の接続情報チェックメソッド( SendConnectionCheck )

B要素モデル演算結果を外部のエレメントに対して公開する
  要素モデルクラス: 出力メソッド( DataFusion )

 を制作する必要がありました。

 受信の場合には次の 実装が必要です。

@受信パターンの設定
  Factoryクラス: モデルプロパティ情報設定メソッド( CreateModelProperty )

A受信接続チェック
  要素モデルクラス: 受信側の接続情報チェックメソッド( ReceiveConnectionCheck )

B接続先から情報を取り込んで演算を行う
  要素モデルクラス: 計算メソッド( Calculate )



 @「受信パターンの設定」は、送信の場合と同様に 受信仕様を「受信パターン」として登録しておく為の処理です。
 
 A「受信接続チェック」は、要素モデルの受信側接続線のチェックを行う機能です。
  例えば、次のようなチェックを行います。
   ・要素モデルが必要とする情報が設定されているかを調べて、エラーや警告を出す。
   ・受信データの型式は?セルの配列数は正しいか?を調べてエラーや警告を出す。
 
 B「計算時の情報取り込み」は、計算に必要な情報を接続線から取得する処理です。 この処理は特別なメソッドを持たず、計算メソッド内で行います。


 以降、「MyDynamicWaveModel」に受信関連の処理を実装します。 具体的には以下の機能を追加します。
 
 前章までの「MyDynamicWaveModel」は、内部で流量を発生させて( private double QIN(double T)メソッド ) それを自モデルの入力として使用していました。

protected override long Calculate(long lInputDataNum, ref McReceiveCellDataIF[] csInputCellData)
{
            double m_DT = m_csDltTime.GetTime();
            double m_T = m_csTotalPassingTime.GetTime();
            double dQIN = QIN(m_T);
            m_csMyInf.Q1[0] = dQIN;
       ・・・・・・・・

 この章では、内部で発生していた流量を 外部から取り込めるようにします。


@送信パターンの設定 
 
 受信パターンとしては、モデルの上流端に「流量」を入力させるパターン1つを追加します。
 受信パターンIDを、Defineクラスに定義しておきます。

public class MyExerciseModelDefine
{
        /// <summary>上流端入力</summary>
        public static readonly HySID IN_PATTERN_TOP = new HySID("TopIn");
       ・・・・・・・・・

 次に、送信パターンと同様に、要素モデルのプロパティデータに受信パターンを登録します。

public override McCellModelPropertyIF CreateModelProperty(HySID csLibraryID, HySObjectKind csModelKind)
{
    ・・・・・・・
     csRtnCellPrptyDt = new McCellModelPropertyInfo(csLibraryID, csModelKind);
    ・・・・・・・
                // 受信可能なパターン
                
                    // 第1パターン
                    McTranInfoPattern csTrnPtn = csRtnCellPrptyDt.CreateTranInforPattern(
                        MyExerciseModelDefine.IN_PATTERN_TOP,
                        McTranInfoDefine.SINGLE_CELL_SERIAL,
                        "上流端流入") as McTranInfoPattern;
                    
                        // セル内変数設定
                        HySDataCharacteristicInCell csCellChara = csTrnPtn.CreateCellDataCharacteristic(1);
                        
                            csCellChara.SetDataKind(0, "流量", HySDataCharacteristicInCell.DATA_KIND.QUANTITY_OF_WATER_FLOW, "m3/sec"); 
                        
                        csTrnPtn.SetCellDataCharacteristic(csCellChara); ; // セル情報設定
                        csTrnPtn.SetInterpolateType(HySDefine.InterpolateType.LINEAR); // 内挿方法設定
                    
                    csRtnCellPrptyDt.AddReceivePattern(csTrnPtn);    // 受信可能パターンの追加
               

 コーディングイメージと GUIの対応を下に示します。
      


 送信パターンの設定とほぼ同じですが、受信パターンには 内挿の種別を設定する SetInterpolateType メソッドが追加されます。
 受信時に 要素モデルが必要な時刻にピッタリ一致する時刻のレコードが存在しない時に、内挿を行うか否かの設定です。 デフォルトでは 線形内挿処理が設定されるため、明示的に設定する必要は有りませんが、ここでは敢えて 設定を行なっています。


A受信接続チェック

 受信チェックとしては、受信側に上流端入力がなされていない時に ”受信未設定”のエラーを出すことにします。
 また、複数の入力があった時も、エラーとすることにします。


protected override bool ReceiveConnectionCheck(ref McStructErrorInfo csErrorInf, long lInputDataNum, McReceiveCellDataIF[] csInputCellData)
{
            bool bRtn = true;

            if (lInputDataNum < 1)
            {
                csErrorInf.AddCheckErrorData(this.GetID(), MyExerciseModelDefine.MY_DYNAMIC_MODEL_KIND, "受信接続が有りません");
                bRtn = false;
            }
            else if (lInputDataNum > 1)
            {
                csErrorInf.AddCheckErrorData(this.GetID(), MyExerciseModelDefine.MY_DYNAMIC_MODEL_KIND, "受信接続は1本だけです");
                bRtn = false;
            }

            HySID csRcvPttnID;
            for (long lLp = 0; lLp < lInputDataNum; lLp++)
            {   // 入力する伝送データ数分繰り返します。

                // To Do
                // 入力する伝送データの型式や設定値等をチェックし、一つでも期待情報でなければ、bRtn=false; を設定します。
                csRcvPttnID = csInputCellData[lLp].GetReceivePatternID(); // 受信パターン取得
                if (MyExerciseModelDefine.IN_PATTERN_TOP.Equals(csRcvPttnID) != true)
                { // 登録された受信パターンと異なっていれば エラーとする
                    csErrorInf.AddCheckErrorData(this.GetID(), MyExerciseModelDefine.MY_DYNAMIC_MODEL_KIND, "受信形式が違います");
                    bRtn = false;
                }
            }
            return bRtn;
 }


 

B計算時の情報取り込み

 前章まで、「MyDynamicWaveModel」要素モデルは、内部関数(QIN)によって モデル上端部に入力する流量を生成し、与えていました。
 ここでは、上端部に入力する流量情報を 接続線から取得して、上端部に入力する処理に置き換えます。

 受信用接続線は、計算(Calculate)メソッドの引数で与えられます。

 受信パターンが ”上流端入力”の時のみ 受信接続線からデータを読み出し、その値を 入力流量として採用します。
 以下に、データ読み出し部分を示します。 セル内情報を取得する方法は 3.5.2 章で説明した通りです。

protected override long Calculate(long lInputDataNum, ref McReceiveCellDataIF[] csInputCellData)
{
            double dQIN = 0.0;

            HySID csRcvPttnID;
            HySCellDataGetter csGetter = null;
            long lReadIdxQ=0;  // 変換後の読み出し位置
            HySCellData csCell = null;
           
            for (long lLp = 0; lLp < lInputDataNum; lLp++)
            {   // 入力する伝送データ数分繰り返します。
                csRcvPttnID = csInputCellData[lLp].GetReceivePatternID();  // 受信パターン取得
                if (MyExerciseModelDefine.IN_PATTERN_TOP.Equals(csRcvPttnID) == true)
                {   // 登録された受信パターン
                    csGetter = csInputCellData[lLp].GetCellDataGetter();  // 接続の対応表の取得
                    lReadIdxQ = csGetter.GetIdx( 0 ); // 実際に読む位置を取得(受信側は0番目が流量と認識している)
 
                    csCell = csInputCellData[lLp].GetInterpolatedCell(0); // セル配列の0番目のセルを取得

                    dQIN += csCell.m_dData[lReadIdxQ]; // 流量を読み出す
                }     
            }
            dQIN = dQIN / m_csMyInf.WIDTH;  // 単位川幅当りの値に変換
         ・・・・・・

 

C#で x += y;  の記述は  x = x+y; と同じです。    

 接続線から取得した流量の単位は m3/sec ですが、これまで使用していたQINは、流量を川幅で割っていた値だったので、取得した流量も 計算開始の前に 川幅で割ります。



  (動作確認)

 実際にディバッグ用CommonMPを起動し ディバッグ実行によって 動作を確認してみます。

 

 もしも、期待通りに動作しない時には、 ブレークポイントを設定して、ステップ実行により動作を行ない バグを発見/修正します。

  

(補足) セル内情報の取得方法
 
 本頁で セル内の情報を取得するのに、 接続の対応表を取得し セルの何番目を読み出すかを計算しました。
 (下コーディング)

            HySCellDataGetter csGetter = null;
            long lReadIdxQ=0;

            csGetter = csInputCellData[lLp].GetCellDataGetter();  // 接続の対応表の取得
            lReadIdxQ = csGetter.GetIdx( 0 ); // 実際に読む位置を取得(受信側は0番目が流量と認識している)
 
            csCell = csInputCellData[lLp].GetInterpolatedCell(0); // セル配列の0番目のセルを取得
                   
            流量 = csCell.m_dData[lReadIdxQ]; // 流量を読み出す


 しかしながら、対応表を意識しないで、セル内情報を取得することも可能です。
 下のコーディング例の様に 接続線のData()メソッドを使用すると、一連の処理を内部で行い、1行で簡潔に表すことが可能です。(引数に対象セルと、受信側で定めている取得位置(ここでは、流量取得は0番目)を引数で与える)

           csCell = csInputCellData[lLp].GetInterpolatedCell(0); // セル配列の0番目のセルを取得

            流量 = csInputCellData[lLp].Data(csCell, 0);   // 流量を取得(受信側は0番目が流量と認識している)

 CommonMPをダウンロードした時に 一緒にダウンロードされるサンプルプログラムは全て Data()メソッドを利用しています。
 本HPのモデルでは、原理を理解するため、敢えて 対応表を使用したコーディングにしました。




 ここで作成した要素モデル開発プロジェクト(Ex06_MyExerciseModel.lzh

 ダウンロードしたら解凍して生成されたフォルダー「MyExerciseModel」を \CommonMP\Source\HYMCO\OptionImpl\ 下に置きます。   
 解凍して生成されたプロジェクト:MyExerciseModel.csproj を ディバッグ用ソリューションに追加し、スタートアッププロジェクト(TestModelDeveloperMainExp)の依存関係に追加します。

 

 またテスト用のCommonMP計算プロジェクト(Ex06_MyExerciseStep1.lzh

 解凍して生成された、「MyExerciseStep1」フォルダーを \CommonMP\CommonMPData\ 下に置きます。

 




(前頁)<<      >>(次頁) 

初版:2013/06/23 |