// <summary>ソースコード：ＨＹＭＣＯ演算モデルクラス</summary>
// <author>CommonMP</author>

using System;
using System.Collections.Generic;
using System.Text;

using CommonMP.HYSSOP.CoreImpl.HSData;
using CommonMP.HYSSOP.CoreImpl.HSTools;

using CommonMP.HYMCO.Interface.Model;
using CommonMP.HYMCO.Interface.Data;
using CommonMP.HYMCO.CoreImpl.Data;
using CommonMP.HYMCO.CoreImpl.Tool;

using CommonMP.HYMCO.OptionImple.GAModelSampleLIB.GACtlTools;

// ToDo namespace は　モデル開発者が変更して、ユニークな名称にして下さい
namespace CommonMP.HYMCO.OptionImple.GAModelSampleLIB
{
    /// <summary><para>class outline:</para>
    /// <para>KinematicWave河川モデルを複数配置して河川を構成したモデル</para>
    /// </summary>
    /// <remarks><para>history:</para>
    /// <para>[CommonMP][ver 1.0.3][2010/10/01][新規作成]</para>
    /// <para>remarks</para>
    /// <para>
    /// 内部に配置されたKinematicWave河川モデルのパラメータ調整を遺伝子アルゴリズムにより調整する
    /// GACreatureIFをインプリメントしている事に注意
    /// </para>
    /// </remarks>
    public class GAKinematicWaveEvolutionModel : McForecastModelBase, GACreatureIF  // ← GACreatureIF をインプリメントしている事に注意
    {
        /// <summary> 演算データ（キャスト用） </summary>
        GAKinematicWaveEvolutionModelCalInfo m_KMdlInf = null;   // 便利の為、キャスト用に定義しておく

        /// <summary> 演算要素配列（内部に個々にKinematicWave河道計算処理が入っている） </summary>
        GAKinematicWaveBox[] m_csKinematicWaveBox = null;
 
        //=========================
        // 演算実行前処理関連メソッド
        //=========================

        /// <summary><para>method outline:</para>
        /// <para>入力側の接続情報チェック</para>
        /// </summary>
        /// <example>
        /// <para>usage:</para>
        /// <para>bool bRtn = ReceiveConnectionCheck(ref csErrorInf)</para>
        /// </example>
        /// <param name="csErrorInf">エラー出力</param>
        /// <param name="lInputDataNum">入力情報数</param>
        /// <param name="csInputCellData">演算に必要な入力情報配列</param>
        /// <returns>true :正常 , false:異常</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>受信するデータが自モデルが期待している情報か否かをチェックする</para>
        /// </remarks>
        protected override bool ReceiveConnectionCheck(ref McStructErrorInfo csErrorInf, long lInputDataNum, McReceiveCellDataIF[] csInputCellData)
        {
            bool bRtn = true;
            if (lInputDataNum == 0)
            {
                // 入力が無い場合
                // エラー
               // ver1.5 エラートレース日本語対応
                csErrorInf.AddCheckErrorData(this.GetID(), GeneticAlgorithmSampleDefine.GAKinematicWaveEvolutionModel_MODEL_KIND, 
                     Properties.Resources.STATEMENT_NO_REC_DATA );
               // csErrorInf.AddCheckErrorData(this.GetID(), GeneticAlgorithmSampleDefine.GAKinematicWaveEvolutionModel_MODEL_KIND, "No receive data.");
                bRtn = false;
            }
            for (long lP = 0; lP < lInputDataNum; lP++)
            {   // 入力する伝送データ数分繰り返します。

                if (GeneticAlgorithmSampleDefine.IN_PATTERN_TOP.Equals(csInputCellData[lP].GetReceivePatternID()) == true)
                {
                    // Do Nothing
                }
                else
                {
                   // ver1.5 エラートレース日本語対応
                    csErrorInf.AddCheckErrorData(this.GetID(), GeneticAlgorithmSampleDefine.GAKinematicWaveEvolutionModel_MODEL_KIND,
                         Properties.Resources.STATEMENT_UNEXPECT_REC_DATA_TYPE_R + csInputCellData[lP].GetUpperElementID().ToString() + ")");
                   // csErrorInf.AddCheckErrorData(this.GetID(), GeneticAlgorithmSampleDefine.GAKinematicWaveEvolutionModel_MODEL_KIND,
                   //     "Unexpected receive data type. (Received from " + csInputCellData[lP].GetUpperElementID().ToString() + ")");
                    bRtn = false;
                }
                long lD1 = 0; long lD2 = 0; long lD3 = 0; long lCellDataNum = 0;
                long lCellDim = csInputCellData[lP].GetDimension(ref lD1, ref lD2, ref lD3, ref lCellDataNum);

                if (lCellDim == 1 && lD1 == 1)
                {   // 1次元の１セルでならば
                    if (lCellDataNum < 1)
                    {
                       // ver1.5 エラートレース日本語対応
                        csErrorInf.AddCheckErrorData(this.GetID(), GeneticAlgorithmSampleDefine.GAKinematicWaveEvolutionModel_MODEL_KIND,
                             Properties.Resources.STATEMENT_VAL_NUM_SHORT_R  + csInputCellData[lP].GetUpperElementID().ToString() + ")");
                       // csErrorInf.AddCheckErrorData(this.GetID(), GeneticAlgorithmSampleDefine.GAKinematicWaveEvolutionModel_MODEL_KIND,
                       //     "Variable number in the Cells is too short. (Received from " + csInputCellData[lP].GetUpperElementID().ToString() + ")");
                        bRtn = false;
                    }
                }

            }
            return bRtn;
        }

        /// <summary><para>method outline:</para>
        /// <para>出力側の接続情報チェック</para>
        /// </summary>
        /// <example>
        /// <para>usage:</para>
        /// <para>bool bRtn = SendConnectionCheck(ref csErrorInf)</para>
        /// </example>
        /// <param name="csErrorInf">エラー出力</param>
        /// <param name="lOutputDataNum">出力情報数</param>
        /// <param name="csOutputCellData">出力情報配列</param>
        /// <returns>true :正常 , false:異常</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>送信端子に設定されている伝送データが自モデルが期待している情報か否かをチェックする</para>
        /// </remarks>
        protected override bool SendConnectionCheck(ref McStructErrorInfo csErrorInf, long lOutputDataNum, McSendCellDataIF[] csOutputCellData)
        {
            bool bRtn = true;
            if (lOutputDataNum == 0)
            {
                // 警告（エラーではない）
               // ver1.5 エラートレース日本語対応
                csErrorInf.AddCheckWarningData(this.GetID(), GeneticAlgorithmSampleDefine.GAKinematicWaveEvolutionModel_MODEL_KIND, 
                     Properties.Resources.STATEMENT_NO_SND_PORT );
               // csErrorInf.AddCheckWarningData(this.GetID(), GeneticAlgorithmSampleDefine.GAKinematicWaveEvolutionModel_MODEL_KIND, "No send port.");
            }
            for (long lP = 0; lP < lOutputDataNum; lP++)
            {   // 出力する伝送データ数分繰り返します。

                if (GeneticAlgorithmSampleDefine.OUT_PATTERN_BOTTOM.Equals(csOutputCellData[lP].GetSendPatternID()) == true)
                {   // 最終セルだけの出力ならば
                    // Do Nothing
                }
                else if (GeneticAlgorithmSampleDefine.OUT_PATTERN_ALL.Equals(csOutputCellData[lP].GetSendPatternID()) == true)
                {   // 全体出力ならば
                    // Do Nothing
                }
                else
                {
                    // エラー
                   // ver1.5 エラートレース日本語対応
                    csErrorInf.AddCheckErrorData(this.GetID(), GeneticAlgorithmSampleDefine.GAKinematicWaveEvolutionModel_MODEL_KIND,
                         Properties.Resources.STATEMENT_UNEXPECT_DATA_TYPE );
                   // csErrorInf.AddCheckErrorData(this.GetID(), GeneticAlgorithmSampleDefine.GAKinematicWaveEvolutionModel_MODEL_KIND,
                   //     "Unexpected send data type.");
                    bRtn = false;
                }

                long lD1 = 0; long lD2 = 0; long lD3 = 0; long lCellDataNum = 0;
                long lCellDim = csOutputCellData[lP].GetDimension(ref lD1, ref lD2, ref lD3, ref lCellDataNum);

                if (lCellDim == 1 && lD1 == 1)
                {   // １次元配列の１セルならば
                    // セル配列数が１ならば、最終セルのみ出力するものとする
                    // セル内の変数の数をチェック
                    if (lCellDataNum < 3)
                    {
                       // ver1.5 エラートレース日本語対応
                        csErrorInf.AddCheckErrorData(this.GetID(), GeneticAlgorithmSampleDefine.GAKinematicWaveEvolutionModel_MODEL_KIND,
                             Properties.Resources.STATEMENT_VAL_NUM_SHORT_S + csOutputCellData[lP].GetLowerElementID().ToString() + ")");
                       // csErrorInf.AddCheckErrorData(this.GetID(), GeneticAlgorithmSampleDefine.GAKinematicWaveEvolutionModel_MODEL_KIND,
                       //     "Variable number in the Cells is too short. (Send To " + csOutputCellData[lP].GetLowerElementID().ToString() + ")");
                        bRtn = false;
                    }
                }
                else if (lCellDim == 1 && lD1 > 1)
                {   // １次元配列で複数セルならば
                    // セル配列数が複数ならば、全セルの出力とする
                    // 伝送セルの配列数が　モデル内のセルの配列数よりも小さいならば
                    if (m_KMdlInf.m_lCalElmNumber > lD1)
                    {
                       // ver1.5 エラートレース日本語対応
                        csErrorInf.AddCheckErrorData(this.GetID(), GeneticAlgorithmSampleDefine.GAKinematicWaveEvolutionModel_MODEL_KIND,
                                                Properties.Resources.STATEMENT_SELLDIM + "(" + csOutputCellData[lP].GetTranInfoKind().ToString() + ")"
                                              + Properties.Resources.STATEMENT_IS_TOO_SHORT_S + csOutputCellData[lP].GetLowerElementID().ToString() + ")");
                       // csErrorInf.AddCheckErrorData(this.GetID(), GeneticAlgorithmSampleDefine.GAKinematicWaveEvolutionModel_MODEL_KIND,
                       //                         "Cell dimention(" + csOutputCellData[lP].GetTranInfoKind().ToString() + ") is too short. (send to " + csOutputCellData[lP].GetLowerElementID().ToString() + ")");
                        bRtn = false;
                    }
                    // セル内の変数の数をチェック
                    if (lCellDataNum < 3)
                    {
                       // ver1.5 エラートレース日本語対応
                        csErrorInf.AddCheckErrorData(this.GetID(), GeneticAlgorithmSampleDefine.GAKinematicWaveEvolutionModel_MODEL_KIND,
                            Properties.Resources.STATEMENT_VAL_NUM_SHORT_S + csOutputCellData[lP].GetLowerElementID().ToString() + ")");
                       // csErrorInf.AddCheckErrorData(this.GetID(), GeneticAlgorithmSampleDefine.GAKinematicWaveEvolutionModel_MODEL_KIND,
                       //     "Variable number in the Cells is too short. (Send To " + csOutputCellData[lP].GetLowerElementID().ToString() + ")");
                        bRtn = false;
                    }
                }

            }
            return bRtn;
        }


        /// <summary><para>method outline:</para>
        /// <para>モデルを初期化する</para>
        /// </summary>
        /// <example>
        /// <para>usage:</para>
        /// <para>Initialize(csInitialData,lInputDataNum,csInputCellData)</para>
        /// </example>
        /// <param name="csInitialData">初期化設定情報</param>
        /// <param name="lInputDataNum">入力情報数</param>
        /// <param name="csInputCellData">演算に必要な入力情報配列</param>
        /// <returns>true :正常 , false:異常</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        protected override bool Initialize(ref McPropertyInfoRoot csInitialData, long lInputDataNum, ref McReceiveCellDataIF[] csInputCellData)
        {
            bool bRtn = false;
            // 引数で与えられたデータを　キャストしています。
            McInitialInfo csInDt = csInitialData as McInitialInfo;

            if (csInDt != null)
            {
                bRtn = true;
                // To Do
                // 演算データ等で初期化が必要な情報に対して、引数で与えられた初期化情報の内容を読み取って、設定します。
                double dDtH = 0.0;
                csInDt.GetInfo("H_Initial", ref dDtH);

                double dDtQ = 0.0;
                csInDt.GetInfo("Q_Initial", ref dDtQ);

                double dDtV = 0.0;
                csInDt.GetInfo("V_Initial", ref dDtV);


                if (m_KMdlInf.m_bReadChromosomeFlg == true)
                {   // 遺伝子情報読み込みが必要ならば
                    m_csSupperElite = new GAChromosomeSample();
                    m_csSupperElite.FileIn(m_KMdlInf.m_sChromosomeFile);
                    for (long lLp = 0; lLp < m_KMdlInf.m_lCalElmNumber; lLp++)
                    {
                        m_csKinematicWaveBox[lLp].SetRough(m_csSupperElite.m_dRough[lLp]);
                    }
                }


                for (long lLp = 0; lLp < m_KMdlInf.m_lCalElmNumber; lLp++)
                {
                    m_csKinematicWaveBox[lLp].Initialize();
                }
            }

            //this.ClearFitValue(); <-- 此処に入れると、パターン毎にリセットがかかるためダメ
            
            return bRtn;
        }

        //=======================
        // 演算実行処理関連メソッド
        //=======================

        /// <summary><para>method outline:</para>
        /// <para>モデル演算</para>
        /// </summary>
        /// <example>
        /// <para>usage:</para>
        /// <para>long lRtn = Calculate(lInputDataNum, ref csInputCellData)</para>
        /// </example>
        /// <param name="lInputDataNum">入力情報数</param>
        /// <param name="csInputCellData">演算に必要な入力情報配列</param>
        /// <returns>0 :正常 , -1:異常</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        protected override long Calculate(long lInputDataNum, ref McReceiveCellDataIF[] csInputCellData)
        {
            //McLog.DebugOut(GetSimulationTime(), GetID(), "MyModel", "Calculate", "in");

            double dElmIn = 0.0; // 個別流入量

            double dQTopTotalIn = 0.0; // 上流総合流入量リセット
            long lQIdx = 0;  // 流量は０番目


            HySCellData csCell = null;  // 取得するセル
            for (long lP = 0; lP < lInputDataNum; lP++)
            {   // 入力データ数分
                csCell = csInputCellData[lP].GetInterpolatedCell(0); // セル配列の０番目のセルを取得
                dElmIn = csInputCellData[lP].Data(csCell, lQIdx);   // セル内の０番目の変数値を取得

                if (GeneticAlgorithmSampleDefine.IN_PATTERN_TOP.Equals(csInputCellData[lP].GetReceivePatternID()) == true)
                {   // 上流端入力ならば
                    dQTopTotalIn += dElmIn;
                }
            }

            // 河道内の断面ごとの水位、流速、流量の算定
            m_csKinematicWaveBox[0].m_dQIn = dQTopTotalIn;

            for (long lLp = 0; lLp < m_KMdlInf.m_lCalElmNumber; lLp++)
            {
                m_csKinematicWaveBox[lLp].Calculate();
            }
            
            //McLog.DebugOut(GetSimulationTime(), GetID(), "MyModel", "Calculate", "out");
            return 0;
        }

        /// <summary><para>method outline:</para>
        /// <para>モデル演算結果を外部のエレメントに対して公開する</para>
        /// </summary>
        /// <example>
        /// <para>usage:</para>
        /// <para>long lRtn = DataFusion( lOutputDataNum, ref csOutputCellData)</para>
        /// </example>
        /// <param name="lOutputDataNum">出力情報数</param>
        /// <param name="csOutputCellData">出力情報配列</param>
        /// <returns>0 :正常 , -1:異常</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        protected override long DataFusion(long lOutputDataNum, ref McSendCellDataIF[] csOutputCellData)
        {
            HySCellData[] csSndCellData = null;
            //McLog.DebugOut(GetSimulationTime(), GetID(), "MyModel", "DataFusion", "in");

            for (long lLp = 0; lLp < lOutputDataNum; lLp++)
            {   // 出力する伝送データ数分繰り返します。
                csSndCellData = csOutputCellData[lLp].PrepareSendCellD1();

                if (GeneticAlgorithmSampleDefine.OUT_PATTERN_BOTTOM.Equals(csOutputCellData[lLp].GetSendPatternID()) == true)
                {   // 最終セルだけの出力ならば
                    csSndCellData[0].m_dData[0] = m_csKinematicWaveBox[m_KMdlInf.m_lCalElmNumber - 1].m_dQOut;
                    csSndCellData[0].m_dData[1] = m_csKinematicWaveBox[m_KMdlInf.m_lCalElmNumber - 1].m_dHOut;
                    csSndCellData[0].m_dData[2] = m_csKinematicWaveBox[m_KMdlInf.m_lCalElmNumber - 1].m_dVOut;
                }
                else if (GeneticAlgorithmSampleDefine.OUT_PATTERN_ALL.Equals(csOutputCellData[lLp].GetSendPatternID()) == true)
                {   // 全体出力ならば
                    for (long lP = 0; lP < m_KMdlInf.m_lCalElmNumber; lP++)
                    {
                        csSndCellData[lP].m_dData[0] = m_csKinematicWaveBox[lP].m_dQOut;
                        csSndCellData[lP].m_dData[1] = m_csKinematicWaveBox[lP].m_dHOut;
                        csSndCellData[lP].m_dData[2] = m_csKinematicWaveBox[lP].m_dVOut;
                    }
                }
            }
            //McLog.DebugOut(GetSimulationTime(), GetID(), "MyModel", "DataFusion", "out");
            return 0;
        }


        //====================
        // その他必要なメソッド
        //====================

        /// <summary><para>method outline:</para>
        /// <para>プロパティ情報を設定する</para>
        /// </summary>
        /// <example>
        /// <para>usage:</para>
        /// <para>SetProperty(csCellMdlPropertyInfo)</para>
        /// </example>
        /// <param name="csCellMdlPropertyInfo">セル型プロパティ情報</param>
        /// <returns>true :正常 , false:異常</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public override bool SetProperty(McCellModelPropertyIF csCellMdlPropertyInfo)
        {
            bool bRtn = false;
            // 使用しやすいようにキャストしておく
            m_KMdlInf = (GAKinematicWaveEvolutionModelCalInfo)m_csCalInfo;

            // プロパティ設定
            McCellModelPropertyInfo csPrptyInfo = csCellMdlPropertyInfo as McCellModelPropertyInfo;
            if (csPrptyInfo != null)
            {
                // 演算ステップ時刻設定
                this.m_csDltTime = new HySTime(csPrptyInfo.GetStepTime());

                bRtn = true;

                // 各種係数設定
                csPrptyInfo.GetInfo("m_lCalElmNumber", ref m_KMdlInf.m_lCalElmNumber);
                csPrptyInfo.GetInfo("m_lCelDivNumber", ref m_KMdlInf.m_lCelDivNumber);
                m_csKinematicWaveBox = new GAKinematicWaveBox[m_KMdlInf.m_lCalElmNumber];
                for (long lLp = 0; lLp < m_KMdlInf.m_lCalElmNumber; lLp++)
                {
                    m_csKinematicWaveBox[lLp] = new GAKinematicWaveBox(m_KMdlInf.m_lCelDivNumber);
                    m_csKinematicWaveBox[lLp].SetTimeLag(this.m_csDltTime.GetTime());
                    if (lLp != 0)
                    {
                        m_csKinematicWaveBox[lLp].SetPrev(ref m_csKinematicWaveBox[lLp-1]);
                        m_csKinematicWaveBox[lLp-1].SetNext(ref m_csKinematicWaveBox[lLp]);
                    }
                }
                m_dRefData = new double[m_KMdlInf.m_lCalElmNumber];
                //m_dRefDataDlt = new double[m_KMdlInf.m_lCalElmNumber];

                long lFlg = 0;
                csPrptyInfo.GetInfo("m_bReadChromosomeFlg", ref lFlg);
                if (lFlg == 0) { m_KMdlInf.m_bReadChromosomeFlg = false; }
                else { m_KMdlInf.m_bReadChromosomeFlg = true; }
                //csPrptyInfo.GetInfo("m_sChromosomeFile", ref m_KMdlInf.m_sChromosomeFile);
                string sSuperElite = "";
                csPrptyInfo.GetInfo("m_sChromosomeFile", ref sSuperElite);
                m_KMdlInf.m_sChromosomeFile = this.GetProjectGroupDirectory().ToString() + "\\" + sSuperElite;

            }
            return bRtn;
        }

        /// <summary><para>method outline:</para>
        /// <para>計算開始時に動作する処理</para>
        /// </summary>
        /// <example>
        /// <para>usage:</para>
        /// <para>bool bRtn = ReadyCalculation( )</para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>true :正常 , false:異常</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>計算開始の　最初に１回だけコールされるメソッドです。不要ならば、本メソッドをオーバーライドする必要はありません。</para>
        /// </remarks>
        public override bool ReadyCalculation()
        {
            //McLog.DebugOut(GetSimulationTime(), GetID(), "MyModel", "ReadyCalculation", "in");

            // ToDo
            // 計算開始の　最初に１回だけコールされるメソッドです。不要ならば、本メソッドをオーバーライドする必要はありません。
            // （メソッド自身を削除してください）
            // 比較するデータを取得しておく

            m_dFitValue = 0.0;

            //McLog.DebugOut(GetSimulationTime(), GetID(), "MyModel", "ReadyCalculation", "out");
            return true;
        }

        /// <summary><para>method outline:</para>
        /// <para>計算中断時に動作する処理</para>
        /// </summary>
        /// <example>
        /// <para>usage:</para>
        /// <para>bool bRtn = SuspendCalculation( )</para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>true :正常 , false:異常</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>オペレーター操作等により計算中断時に　コールされるメソッドです。不要ならば、本メソッドをオーバーライドする必要はありません。</para>
        /// </remarks>
        public override bool SuspendCalculation()
        {
            //McLog.DebugOut(GetSimulationTime(), GetID(), "MyModel", "SuspendCalculation", "in");

            // ToDo
            // オペレーター操作等により計算中断時に　コールされるメソッドです。不要ならば、本メソッドをオーバーライドする必要はありません。
            // （メソッド自身を削除してください）

            //McLog.DebugOut(GetSimulationTime(), GetID(), "MyModel", "SuspendCalculation", "out");
            return true;
        }

        /// <summary><para>method outline:</para>
        /// <para>計算終了時に動作する処理</para>
        /// </summary>
        /// <example>
        /// <para>usage:</para>
        /// <para>bool bRtn = CompleteCalculation( )</para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>true :正常 , false:異常</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>計算終了時　最後の最初に１回だけコールされるメソッドです。不要ならば、本メソッドをオーバーライドする必要はありません。</para>
        /// </remarks>
        public override bool CompleteCalculation()
        {
            //McLog.DebugOut(GetSimulationTime(), GetID(), "MyModel", "CompleteCalculation", "in");

            // ToDo
            // 計算終了時　最後の最初に１回だけコールされるメソッドです。不要ならば、本メソッドをオーバーライドする必要はありません。
            // （メソッド自身を削除してください）

            //McLog.DebugOut(GetSimulationTime(), GetID(), "MyModel", "CompleteCalculation", "out");
            return true;
        }

        /// <summary><para>method outline:</para>
        /// <para>演算用刻み時間を自動的に変更する</para>
        /// </summary>
        /// <example>
        /// <para>usage:</para>
        /// <para>ChangeDeltaTimeAutomatically()</para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public override void ChangeDeltaTimeAutomatically()
        {
            //McLog.DebugOut(GetSimulationTime(), GetID(), "MyModel", "ChangeDeltaTimeAutomatically", "in");

            // ToDo
            // 演算中条件によって　自身のδTを(this.m_csDltTime) を変更するメソッドです。
            // 不要ならば、本メソッドをオーバーライドする必要はありません。（メソッド自身を削除してください）

            //McLog.DebugOut(GetSimulationTime(), GetID(), "MyModel", "ChangeDeltaTimeAutomatically", "out");
        }



        // =======================================================================================
        // ↓↓↓　以下は、遺伝子アルゴリズムを動作させるための　固体としての情報／メソッドを記述　↓↓↓
        // =======================================================================================

        /// <summary>適合度 </summary>
        protected double m_dFitValue = 0.0;

        /// <summary>進化時に適合度計算基準となるデータ：配列（KinematicWave河道計算処理数）</summary>
        protected double[] m_dRefData = null;

        /// <summary>外部から遺伝子情報を読み出した時の保存クラス</summary>
        protected GAChromosomeSample m_csSupperElite;

        /// <summary><para>method outline:</para>
        /// <para>固体の環境適合度取得</para>
        /// </summary>
        /// <example>
        /// <para>usage:</para>
        /// <para>　double dFitVal = GetFitValue()</para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>固体の環境適合度</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>大きいほど固体は環境に適合している</para>
        /// </remarks>
        public virtual double GetFitValue()
        {
            return m_dFitValue;
        }
        /// <summary><para>method outline:</para>
        /// <para>固体の環境適合度値リセット</para>
        /// </summary>
        /// <example>
        /// <para>usage:</para>
        /// <para>　ResetFitness()</para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public virtual void ResetFitness()
        {
            this.ClearFitValue();
        }

        /// <summary><para>method outline:</para>
        /// <para>進化計算前にモデルを初期化する</para>
        /// </summary>
        /// <example>
        /// <para>usage:</para>
        /// <para>bool bRtn = InitalCompetition(csInitialData,lInputDataNum,csInputCellData)</para>
        /// </example>
        /// <param name="csInitialData">初期化設定情報</param>
        /// <param name="lInputDataNum">入力情報数</param>
        /// <param name="csInputCellData">演算に必要な入力情報配列</param>
        /// <returns>true :正常 , false:異常</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public virtual bool InitalCompetition(ref McPropertyInfoRoot csInitialData, long lInputDataNum, ref McReceiveCellDataIF[] csInputCellData)
        {
            return this.Initialize(ref csInitialData, lInputDataNum, ref csInputCellData);
        }

        // 固体の動作
        /// <summary><para>method outline:</para>
        /// <para>進化計算する</para>
        /// </summary>
        /// <example>
        /// <para>usage:</para>
        /// <para>long lRtn = Competition(lInputDataNum,csInputCellData)</para>
        /// </example>
        /// <param name="lInputDataNum">入力情報数</param>
        /// <param name="csInputCellData">演算に必要な入力情報配列</param>
        /// <returns>0 :正常 , -1:異常</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public virtual long Competition(long lInputDataNum, ref McReceiveCellDataIF[] csInputCellData)
        {
            return this.Calculate(lInputDataNum, ref csInputCellData);
        }
        
        // 適合度計算
        /// <summary><para>method outline:</para>
        /// <para>適合度計算</para>
        /// </summary>
        /// <example>
        /// <para>usage:</para>
        /// <para>double dFitVal = CalFitness(csCellDtArry)</para>
        /// </example>
        /// <param name="csCellDtArry">適合度計算の為の比較基準データ</param>
        /// <returns>double 適合度</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public virtual double CalFitness(ref HySCellData[] csCellDtArry)
        {
            for (long lLp = 0; lLp < csCellDtArry.Length; lLp++)
            {
                m_dRefData[lLp] = csCellDtArry[lLp].m_dData[0];  // 水位
            }
            this.CalFitValue();
            return m_dFitValue;
        }


        /// <summary><para>method outline:</para>
        /// <para>進化計算中にモデル演算結果を外部のエレメントに対して公開する</para>
        /// </summary>
        /// <example>
        /// <para>usage:</para>
        /// <para>long lRtn = OutCompetition( lOutputDataNum, ref csOutputCellData)</para>
        /// </example>
        /// <param name="lOutputDataNum">出力情報数</param>
        /// <param name="csOutputCellData">出力情報配列</param>
        /// <returns>0 :正常 , -1:異常</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public virtual long OutCompetition(long lOutputDataNum, ref McSendCellDataIF[] csOutputCellData)
        {
            return this.DataFusion(lOutputDataNum, ref csOutputCellData);
        }


        /// <summary><para>method outline:</para>
        /// <para>固体の環境適合度値クリア</para>
        /// </summary>
        /// <example>
        /// <para>usage:</para>
        /// <para>　ResetFitness()</para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        protected virtual void ClearFitValue()
        {
            m_dFitValue = 0.0;
        }
        
        /// <summary><para>method outline:</para>
        /// <para>固体の環境適合度値を計算する</para>
        /// </summary>
        /// <example>
        /// <para>usage:</para>
        /// <para>　CalFitValue()</para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        protected virtual void CalFitValue()
        {
            // 実際は、ここでの計算が評価関数となる
            //  本例では、ln(水位の２乗誤差の逆数)を　評価値として計算している
            //  モデルに応じて、評価関数を色々と作成する必要がある
            double dSum = 0.0;
            double dErr2 = 0.0;


            for (long lLp = 0; lLp < m_KMdlInf.m_lCalElmNumber; lLp++)
            {
                dErr2 = (m_csKinematicWaveBox[lLp].m_dHOut - m_dRefData[lLp])/(m_dRefData[lLp]+0.001);
                //dErr2 = (m_csKinematicWaveBox[lLp].m_dHOut - m_dRefData[lLp]);

                dErr2 = dErr2 * dErr2; // 2乗誤差
                dSum += dErr2;
            }
            dSum = dSum / (double)(m_KMdlInf.m_lCalElmNumber);
            m_dFitValue += Math.Log( 1.0/(dSum+0.00000001) ) * 0.01;
                        // 固体が死ぬまで、適合値を累積する
                        // 此処で、+0.00000001を行っているのは、０割によるエラー発生を防ぐ為
        }


        /// <summary><para>method outline:</para>
        /// <para>遺伝子情報を解読し、固体内部のパラメーターを調整する</para>
        /// </summary>
        /// <example>
        /// <para>usage:</para>
        /// <para>　GeneDecipher(csChromosome)</para>
        /// </example>
        /// <param name="csChromosome">遺伝子情報</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        internal void GeneDecipher( GAChromosomeSample csChromosome )
        {
            m_KMdlInf = (GAKinematicWaveEvolutionModelCalInfo)m_csCalInfo;

            m_KMdlInf.m_lCalElmNumber = csChromosome.m_lBoxNum;
            m_KMdlInf.m_lCelDivNumber = csChromosome.m_lCelDivNumber;
            
            m_csKinematicWaveBox = new GAKinematicWaveBox[m_KMdlInf.m_lCalElmNumber];
            for (long lLp = 0; lLp < m_KMdlInf.m_lCalElmNumber; lLp++)
            {
                m_csKinematicWaveBox[lLp] = new GAKinematicWaveBox(m_KMdlInf.m_lCelDivNumber);
                m_csKinematicWaveBox[lLp].SetRough(csChromosome.m_dRough[lLp]);
                
                if (lLp != 0)
                {
                    m_csKinematicWaveBox[lLp].SetPrev(ref m_csKinematicWaveBox[lLp-1]);
                    m_csKinematicWaveBox[lLp-1].SetNext(ref m_csKinematicWaveBox[lLp]);
                }
            }
            m_dRefData = new double[m_KMdlInf.m_lCalElmNumber];

        }
    }
    //
}
