using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using System.Collections;

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

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

using CommonMP.HYMCO.CoreOptionl.HymcoExpansionModel;

using CommonMP.HYMCO._SYSTEM_;


namespace CommonMP.HYMCO.Ocean.McOceanBaseModel
{

    /// <summary><para>class outline:</para>
    /// <para>海洋モデルモデル基底クラス（モデルは本クラスを派生して作成する）</para>
    /// </summary>
    /// <remarks>
    /// <para>history:</para>
    /// <para>
    /// [2021/12/31][メソッド追加]
    /// </para>
    /// <para>remarks:</para>
    /// <para> 補間処理付き </para>
    /// </remarks>
    public abstract class MzOceanModelElement : McInterCnnctModel // : McForecastModelBase
    {
        //========================================================
        // McOceanModelElementCalInfo内に保持
        ///// <summary> XYで区切られた海洋に於いて、自分が含まれる海域のＸ軸番号：将来用 </summary>
        //protected long m_XLonCellPosNo = 0;
        ///// <summary> XYで区切られた海洋に於いて、自分が含まれる海域のＹ軸番号：将来用 </summary>
        //protected long m_YLatCellPosNo = 0;

        //---------------------------------------------------------
        ///// <summary> 海洋の一領域のサイズ m2 </summary>
        // public static double m_gAreaSize = 10 * 1E3 * 10 * 1E3; <-- McOceanModelElementCalInfoにある

        //---------------------------------------------------------

        //---------------------------------------------------------
        /// <summary> 海洋の一領域：グローバルに保持する場合 </summary>
        private static MzOceanAreaColumnModel m_gOceanColumModel = null;
        public static MzOceanAreaColumnModel OceanColumModel
        {
            set {  MzOceanModelElement.m_gOceanColumModel = value; }
        }

        //---------------------------------------------------------
        /// <summary> 海洋の一領域上の大気：グローバルに保持する場合 </summary>
        private static MzOceanAtmosphere m_gOceanAtmosphereModel = null;
        public static MzOceanAtmosphere OceanAtmosphereModel
        {
            set { MzOceanModelElement.m_gOceanAtmosphereModel = value; }
        }
        //---------------------------------------------------------

        ///// <summary> 海洋の一領域上の溶融ガス：グローバルに保持する場合 </summary>
        //private static MzOceanDissolveGass m_gOceanGassModel = null;
        //public static MzOceanDissolveGass OceanGassModel
        //{
        //    set { MzOceanModelElement.m_gOceanGassModel = value; }
        //}

        ///// <summary> 海洋の一領域上の水面：グローバルに保持する場合 </summary>
        //private static MzOceanSeaSurfaceModel m_gOceanSurfaceModel = null;
        //public static MzOceanSeaSurfaceModel OceanSurfaceModel
        //{
        //    set { MzOceanModelElement.m_gOceanSurfaceModel = value; }
        //}


        ///// <summary> 海洋の一領域：ローカル変数 </summary>
        //protected MzOceanAreaColumnModel m_csLocalOceanColumModel = null;
        ///// <summary> 海洋の一領域上の溶融ガス：ローカル変数 </summary>
        //protected static MzOceanDissolveＧasModel m_csOceanGassModel = null;
        ///// <summary> 海洋の一領域上の水面：ローカル変数 </summary>
        //protected MzOceanSeaSurfaceModel m_csOceanSurfaceModel = null;
        ///// <summary> 海洋の一領域上の大気：ローカル変数 </summary>
        //protected MzOceanAtmosphereModel m_csOceanAtmosphereModel = null;
        ////---------------------------------------------------------

        //========================================================
    
        /// <summary> 演算データ（キャスト用） </summary>
        protected MzOceanModelElementCalInfo m_csOcnBacedlInf = null; // 便利の為、キャスト用に定義しておく


        //========================================================
        // 捕食関係： McOceanBaseDefine.PREDATION
        protected McPatternRdvSndTranInfoPair m_csRcvPredationCnnct = new McPatternRdvSndTranInfoPair();
        protected McPatternRdvSndTranInfoPair m_csSndPredationCnnct = new McPatternRdvSndTranInfoPair();

        // 排泄：excretion、または 死、関係： McOceanBaseDefine.EXCRETION_DEATH
        ////protected McPatternRdvSndTranInfoPair m_csSndExcretionDeath = new McPatternRdvSndTranInfoPair();
        protected McPatternRdvSndTranInfoPair m_csSndExcretionDeathCnnct = new McPatternRdvSndTranInfoPair();

        // 呼吸関係： McOceanBaseDefine.BREATHING
        protected McPatternRdvSndTranInfoPair m_csRcvBreathingCnnct = new McPatternRdvSndTranInfoPair();
        protected McPatternRdvSndTranInfoPair m_csSndBreathingCnnct = new McPatternRdvSndTranInfoPair();

        // ディバッグ用送信データ
        protected McPatternRdvSndTranInfoPair m_csDebugSendCnnct = new McPatternRdvSndTranInfoPair();

        //---- ワーク -----
        private double[] m_dWorkSumLayer = null;
        private double[] m_dPredation = null;
//        private double[] m_dCapturedMass = null;
        //  食物の密度計算用変数
        private double[] m_dFoodDcty = null;

        //===================================
        //===================================
        protected  MzOceanAreaColumnModelCalInfo GetOceanAreaColumnCalInfo()
        {
            return m_gOceanColumModel.GetOcnColumModel(m_csOcnBacedlInf.m_XLonCellPosNo, m_csOcnBacedlInf.m_YLatCellPosNo);
        }
        //protected MzOceanDissolveGassCalInfo GetOceanDissolveGasInfo()
        //{
        //    return m_gOceanGassModel.GetDslvGasCalInfo(m_csOcnBacedlInf.m_XLonCellPosNo, m_csOcnBacedlInf.m_YLatCellPosNo);
        //}



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

        /// <summary><para>method outline:</para>
        /// <para>入力側の接続情報チェック</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>bool bRtn = CheckReceiveDataConnection(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 CheckReceiveDataConnection(ref McStructErrorInfo csErrorInf, long lInputDataNum, McReceiveCellDataIF[] csInputCellData)
        {
            bool bRtn = true;
            // 使用しやすいようにキャストしておく
            m_csOcnBacedlInf = (MzOceanModelElementCalInfo)m_csCalInfo;

            // 捕食関連接続
            (m_csRcvPredationCnnct, m_csSndPredationCnnct) = this.PrepareRcvSndPattern(MzOceanBaseDefine.PREDATION);

            // 排泄・死＿関連接続：送信
            m_csSndExcretionDeathCnnct = this.PrepareSndPattern(MzOceanBaseDefine.EXCRETION_DEATH);

            // 呼吸関係： McOceanBaseDefine.BREATHING
            (m_csRcvBreathingCnnct, m_csSndBreathingCnnct) = this.PrepareRcvSndPattern(MzOceanBaseDefine.BREATHING);
            //  呼吸する側は　m_csSndBreathingCnnct　を使用しない

            // ディバッグ用送信データ
            m_csDebugSendCnnct = this.PrepareSndPattern(MzOceanBaseDefine.DEBUG_OUT);

            return bRtn;
        }

        /// <summary><para>method outline:</para>
        /// <para>出力側の接続情報チェック</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>bool bRtn = CheckSendDataConnection(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 CheckSendDataConnection(ref McStructErrorInfo csErrorInf, long lOutputDataNum, McSendCellDataIF[] csOutputCellData)
        {
            bool bRtn = true;
            //-------------------------

            return bRtn;
        }


        /// <summary>
        /// 指定送受信パターン送受信情報
        /// </summary>
        protected virtual (McPatternRdvSndTranInfoPair, McPatternRdvSndTranInfoPair) PrepareRcvSndPattern(HySID csPatternID)
        {
            McPatternRdvSndTranInfoPair csRcvRtn = new McPatternRdvSndTranInfoPair();
            McPatternRdvSndTranInfoPair csSndRtn = new McPatternRdvSndTranInfoPair();
            List<McReceiveCellDataIF>   csRcvIFListD = new List<McReceiveCellDataIF>();
            List<McSendCellDataIF>      csSndIFListD = new List<McSendCellDataIF>();
            List<McReceiveCellDataIF>   csRcvIFListU = new List<McReceiveCellDataIF>();
            List<McSendCellDataIF>      csSndIFListU = new List<McSendCellDataIF>();

            csRcvRtn.m_PatternID = csPatternID;
            csSndRtn.m_PatternID = csPatternID;
            for (int i = 0; i < m_csMutualConnectionPatternList.Count; i++)
            {
//// ★★★
//var SSPP = m_csMutualConnectionPatternList[i].m_RcvSndPairList[i];
//McReceiveCellData zzz = SSPP.Item1 as McReceiveCellData;
//string ptnID = zzz.GetReceivePatternID().ToString();
//string ptnIDSub = ptnID.Substring(3);
//bool bOKFlg = false;
//if (SSPP.Item4 == McSndRcvTypeKbn.Snd && ptnIDSub == csPatternID.ToString() )
//{
//    bOKFlg = true;
//}
                //if (bOKFlg == true || csPatternID.Equals(m_csMutualConnectionPatternList[i].m_PatternID) == true)
                if (csPatternID.Equals(m_csMutualConnectionPatternList[i].m_PatternID) == true)
                {
                    for (int kk = 0; kk < m_csMutualConnectionPatternList[i].m_RcvSndPairList.Count; kk++)
                    {
                        var SDP = m_csMutualConnectionPatternList[i].m_RcvSndPairList[kk];
                        if (SDP.Item4 == McSndRcvTypeKbn.Rcv)
                        {
                            csRcvIFListD.Add(SDP.Item1);
                            csSndIFListD.Add(SDP.Item2);
                        }
                        else if (SDP.Item4 == McSndRcvTypeKbn.Snd)
                        {
                            csRcvIFListU.Add(SDP.Item1);
                            csSndIFListU.Add(SDP.Item2);
                        }
                    }
                    csRcvRtn.m_RcvInfNum = csRcvIFListD.Count;
                    csRcvRtn.m_csRcvInfArry = csRcvIFListD.ToArray();
                    csRcvRtn.m_dRcvRatioData = new double[csRcvRtn.m_RcvInfNum][];
                    csRcvRtn.m_csSndInfArry = csSndIFListD.ToArray();
                    csRcvRtn.m_dSendRatioData = new double[csRcvRtn.m_RcvInfNum][];

                    csSndRtn.m_RcvInfNum = csRcvIFListU.Count;
                    csSndRtn.m_csRcvInfArry = csRcvIFListU.ToArray();
                    csSndRtn.m_dRcvRatioData = new double[csSndRtn.m_RcvInfNum][];
                    csSndRtn.m_csSndInfArry = csSndIFListU.ToArray();
                    csSndRtn.m_dSendRatioData = new double[csSndRtn.m_RcvInfNum][];

                    for (int z = 0; z < csRcvRtn.m_RcvInfNum; z++)
                    {
                        csRcvRtn.m_dRcvRatioData[z] = new double[m_csOcnBacedlInf.m_lLayerNumber];
                        csRcvRtn.m_dSendRatioData[z] = new double[m_csOcnBacedlInf.m_lLayerNumber];
                        for (int j = 0; j < m_csOcnBacedlInf.m_lLayerNumber; j++)
                        {
                            csRcvRtn.m_dRcvRatioData[z][j] = 0.0;
                            csRcvRtn.m_dSendRatioData[z][j] = 1.0;
                        }
                    }
                    for (int z = 0; z < csSndRtn.m_RcvInfNum; z++)
                    {
                        csSndRtn.m_dRcvRatioData[z] = new double[m_csOcnBacedlInf.m_lLayerNumber];
                        csSndRtn.m_dSendRatioData[z] = new double[m_csOcnBacedlInf.m_lLayerNumber];
                        for (int j = 0; j < m_csOcnBacedlInf.m_lLayerNumber; j++)
                        {
                            csSndRtn.m_dRcvRatioData[z][j] = 0.0;
                            csSndRtn.m_dSendRatioData[z][j] = 1.0;
                        }
                    }

                    break;
                }
            }
            return (csRcvRtn, csSndRtn);
        }

        /// <summary>
        /// 指定送信パターン情報生成
        /// </summary>
        /// <param name="csPatternID"></param>
        /// <returns></returns>
        protected virtual McPatternRdvSndTranInfoPair PrepareSndPattern(HySID csPatternID)
        {
            McPatternRdvSndTranInfoPair csSndRtn = new McPatternRdvSndTranInfoPair();
            List<McSendCellDataIF> csSndIFListD = new List<McSendCellDataIF>();

            csSndRtn.m_PatternID = csPatternID;

            for (int i = 0; i < m_csSendOnlyConnectionPatternList.Count; i++)
            {
                if (csPatternID.Equals(m_csSendOnlyConnectionPatternList[i].m_PatternID) == true)
                {
                    for (int kk = 0; kk < m_csSendOnlyConnectionPatternList[i].m_RcvSndPairList.Count; kk++)
                    {
                        var SDP = m_csSendOnlyConnectionPatternList[i].m_RcvSndPairList[kk];
                        if (SDP.Item4 == McSndRcvTypeKbn.OnlySnd)
                        {
                            csSndIFListD.Add(SDP.Item2);
                        }
                    }

                    csSndRtn.m_RcvInfNum = csSndIFListD.Count;
                    csSndRtn.m_csRcvInfArry = null;
                    csSndRtn.m_dRcvRatioData = new double[csSndIFListD.Count][];
                    csSndRtn.m_csSndInfArry = csSndIFListD.ToArray();
                    csSndRtn.m_dSendRatioData = new double[csSndRtn.m_RcvInfNum][];

                    for (int z = 0; z < csSndRtn.m_RcvInfNum; z++)
                    {
                        csSndRtn.m_dRcvRatioData[z] = new double[m_csOcnBacedlInf.m_lLayerNumber];
                        csSndRtn.m_dSendRatioData[z] = new double[m_csOcnBacedlInf.m_lLayerNumber];
                        for (int j = 0; j < m_csOcnBacedlInf.m_lLayerNumber; j++)
                        {
                            csSndRtn.m_dRcvRatioData[z][j] = 0.0;
                            csSndRtn.m_dSendRatioData[z][j] = 1.0;
                        }
                    }
                    break;
                }
            }
            return csSndRtn;
        }
    
        /// <summary>
        /// 指定受信パターン情報生成
        /// </summary>
        /// <param name="csPatternID"></param>
        /// <returns></returns>
        protected virtual McPatternRdvSndTranInfoPair PrepareRcvPattern(HySID csPatternID)
        {
            McPatternRdvSndTranInfoPair csRcvRtn = new McPatternRdvSndTranInfoPair();
            List<McReceiveCellDataIF> csRcvIFListD = new List<McReceiveCellDataIF>();

            csRcvRtn.m_PatternID = csPatternID;
            for (int i = 0; i < m_csRcvOnlyConnectionPatternList.Count; i++)
            {
                if (csPatternID.Equals(m_csRcvOnlyConnectionPatternList[i].m_PatternID) == true)
                {
                    for (int kk = 0; kk < m_csRcvOnlyConnectionPatternList[i].m_RcvSndPairList.Count; kk++)
                    {
                        var SDP = m_csRcvOnlyConnectionPatternList[i].m_RcvSndPairList[kk];
                        if (SDP.Item4 == McSndRcvTypeKbn.OnlyRcv)
                        {
                            csRcvIFListD.Add(SDP.Item1);
                        }
                    }
                    csRcvRtn.m_RcvInfNum = csRcvIFListD.Count;
                    csRcvRtn.m_csRcvInfArry = csRcvIFListD.ToArray();
                    csRcvRtn.m_dRcvRatioData = new double[csRcvRtn.m_RcvInfNum][];
                    csRcvRtn.m_csSndInfArry = null;
                    csRcvRtn.m_dSendRatioData = new double[csRcvRtn.m_RcvInfNum][];

                    for (int z = 0; z < csRcvRtn.m_RcvInfNum; z++)
                    {
                        csRcvRtn.m_dRcvRatioData[z] = new double[m_csOcnBacedlInf.m_lLayerNumber];
                        csRcvRtn.m_dSendRatioData[z] = new double[m_csOcnBacedlInf.m_lLayerNumber];
                        for (int j = 0; j < m_csOcnBacedlInf.m_lLayerNumber; j++)
                        {
                            csRcvRtn.m_dRcvRatioData[z][j] = 0.0;
                            csRcvRtn.m_dSendRatioData[z][j] = 1.0;
                        }
                    }
                    break;
                }
            }
            return csRcvRtn;
        }

        /// <summary><para>method outline:</para>
        /// <para>モデルを初期化する</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>Initialize(csInitialData)</para>
        /// </example>
        /// <param name="csInitialData">初期化設定情報</param>
        /// <param name="lInputDataNum">入力情報数</param>
        /// <param name="csInputCellData">演算に必要な入力情報配列</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        protected override bool Initialize(ref McPropertyInfoRoot csInitialData, long lInputDataNum, ref McReceiveCellDataIF[] csInputCellData)
        {
            McInitialInfo csInDt = csInitialData as McInitialInfo;

            m_csOcnBacedlInf.Clear();

            this.InitMass(ref csInDt);
            for (int ll = 0; ll < m_csOcnBacedlInf.m_lLayerNumber; ll++)
            {
                m_csOcnBacedlInf.m_TotalReqedPredationMass[ll] = m_csOcnBacedlInf.m_TotalSelfMass[ll];  // 要求量を計算
            }
            for (int i = 0; i < m_csSndPredationCnnct.m_RcvInfNum; i++)
            {
                for (int ll = 0; ll < m_csOcnBacedlInf.m_lLayerNumber; ll++)
                {
                     m_csSndPredationCnnct.m_dSendRatioData[i][ll] = 1.0;
                }
            }
            return true;
        }

        /// <summary><para>method outline:</para>
        /// <para>初期値の送信</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>long lRtn = SendInitData()</para>
        /// </example>
        /// <param name="lOnlySendDataNum">出力だけの情報数</param>
        /// <param name="csOnlySelDataCellData">出力だけの情報配列</param>
        /// <param name="lRcvSndDataNum">相互接続報数</param>
        /// <param name="csReceiveCellData">相互接続入力側情報配列</param>
        /// <param name="csSelDataCellData">相互接続出力側情報配列</param>
        /// <returns>=0:正常 -1:異常</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>派生クラス側で必ずオーバライドする必要がある</para>
        /// </remarks>
        protected override bool SendInitData(
                        long lOnlySendDataNum, ref McSendOnlyTranInfo[] csOnlySelDataCellData,
                        long lRcvSndDataNum, ref McRdvSndTranInfoPair[] csRcvSndCelDataCellData
                    )
        {
            SendData();
            return true;
        }

        /// <summary>
        /// 初期重量
        /// </summary>
        /// <param name="csInDt"></param>
        protected virtual void InitMass(ref McInitialInfo csInDt)
        {
            double dDtH = 0.0;
            csInDt.GetInfo("TotalMass_L0", ref dDtH);
            m_csOcnBacedlInf.m_TotalSelfMass[0] = dDtH;
            csInDt.GetInfo("TotalMass_L1", ref dDtH);
            m_csOcnBacedlInf.m_TotalSelfMass[1] = dDtH;
            csInDt.GetInfo("TotalMass_L2", ref dDtH);
            m_csOcnBacedlInf.m_TotalSelfMass[2] = dDtH;
            csInDt.GetInfo("TotalMass_L3", ref dDtH);
            m_csOcnBacedlInf.m_TotalSelfMass[3] = dDtH;
            csInDt.GetInfo("TotalMass_L4", ref dDtH);
            m_csOcnBacedlInf.m_TotalSelfMass[4] = dDtH;
            csInDt.GetInfo("TotalMass_L5", ref dDtH);
            m_csOcnBacedlInf.m_TotalSelfMass[5] = dDtH;
            csInDt.GetInfo("TotalMass_L6", ref dDtH);
            m_csOcnBacedlInf.m_TotalSelfMass[6] = dDtH;
        }

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

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

                m_dWorkSumLayer = new double[m_csOcnBacedlInf.m_lLayerNumber];
                m_dPredation = new double[m_csOcnBacedlInf.m_lLayerNumber];
                //m_dCapturedMass = new double[m_csOcnBacedlInf.m_lLayerNumber];
                m_dFoodDcty = new double[m_csOcnBacedlInf.m_lLayerNumber];

                for ( int j=0;j< m_csOcnBacedlInf.m_lLayerNumber;j++)
                {
                    m_dWorkSumLayer[j] = 0.0;
                    m_dPredation[j] = 0.0;
                    //m_dCapturedMass[j] = 0.0;
                    m_dFoodDcty[j] = 0.0;
                }
            }

            return bRtn;
        }

        /// <summary>
        /// 層数の設定
        /// </summary>
        /// <param name="csPrptyInfo"></param>
        /// <returns></returns>
        protected virtual bool SetLayerProperty(ref McCellModelPropertyInfo csPrptyInfo)
        {
            // 各種係数設定
            long lLayerNumber = 7;
            csPrptyInfo.GetInfo("m_lLayerNumber", ref lLayerNumber);

            csPrptyInfo.GetInfo("m_dDepth", ref m_csOcnBacedlInf.m_dDepth);
            //double dDt = 1.0;
            //csPrptyInfo.GetInfo("m_dFace", ref dDt);
            //McOceanModelElementCalInfo.m_dFace = dDt * 1E3 * 1E3;  // Km2 を m2 に変換
            //csPrptyInfo.GetInfo("m_dFace", ref m_csOcnBacedlInf.m_dFace);  <-- これは、グローバル変数

            m_csOcnBacedlInf.SetLayerNum(lLayerNumber);


            return true;
        }
   
        /// <summary>
        /// 代謝関係設定
        /// </summary>
        /// <param name="csPrptyInfo"></param>
        /// <returns></returns>
        protected virtual bool SetMetabolism(ref McCellModelPropertyInfo csPrptyInfo)
        {
            csPrptyInfo.GetInfo("m_CapturedRatio", ref m_csOcnBacedlInf.m_CapturedRatio);

            csPrptyInfo.GetInfo("m_dSelfSize", ref m_csOcnBacedlInf.m_dSelfSize);
            csPrptyInfo.GetInfo("m_dSelfWeight", ref m_csOcnBacedlInf.m_dSelfWeight);
            csPrptyInfo.GetInfo("m_dBulkDensity", ref m_csOcnBacedlInf.m_dBulkDensity);
            csPrptyInfo.GetInfo("m_dEatK", ref m_csOcnBacedlInf.m_dEatK);
            csPrptyInfo.GetInfo("m_dMetabolismK", ref m_csOcnBacedlInf.m_dMetabolismK);
            csPrptyInfo.GetInfo("m_dEexcretionRatio", ref m_csOcnBacedlInf.m_dEexcretionRatio);
            csPrptyInfo.GetInfo("m_dEexcretionSize", ref m_csOcnBacedlInf.m_dEexcretionSize);
            //            csPrptyInfo.GetInfo("m_dExcrtnDcty", ref m_csOcnBacedlInf.m_dExcrtnDcty);

            csPrptyInfo.GetInfo("m_O2AbsRatio", ref m_csOcnBacedlInf.m_O2AbsRatio);
            csPrptyInfo.GetInfo("m_CO2GenRatio", ref m_csOcnBacedlInf.m_CO2GenRatio);

            return true;
        }
   
        /// <summary>
        /// 代謝関係設定２
        /// </summary>
        /// <param name="csPrptyInfo"></param>
        /// <returns></returns>
        protected virtual bool SetMetabolism2(ref McCellModelPropertyInfo csPrptyInfo)
        {
            csPrptyInfo.GetInfo("m_dMaxProliferation", ref m_csOcnBacedlInf.m_dMaxProliferation);
            csPrptyInfo.GetInfo("m_O2AbsRatio", ref m_csOcnBacedlInf.m_O2AbsRatio);
            csPrptyInfo.GetInfo("m_CO2GenRatio", ref m_csOcnBacedlInf.m_CO2GenRatio);
            return true;
        }
 
        /// <summary>
        /// 排泄設定
        /// </summary>
        /// <param name="csPrptyInfo"></param>
        protected virtual void SetEexcretion(ref McCellModelPropertyInfo csPrptyInfo)
        {
            csPrptyInfo.GetInfo("m_dEexcretionRatio", ref m_csOcnBacedlInf.m_dEexcretionRatio);
            csPrptyInfo.GetInfo("m_dEexcretionSize", ref m_csOcnBacedlInf.m_dEexcretionSize);
        }

        /// <summary>
        /// 死亡関係設定
        /// </summary>
        /// <param name="csPrptyInfo"></param>
        /// <returns></returns>
        protected virtual bool SetDeath(ref McCellModelPropertyInfo csPrptyInfo)
        {
            csPrptyInfo.GetInfo("m_dDeathRatio", ref m_csOcnBacedlInf.m_dDeathRatio);
            //           csPrptyInfo.GetInfo("m_dDeathDcty", ref m_csOcnBacedlInf.m_dDeathDcty);
            return true;
        }



        /// <summary>
        /// 受信
        /// </summary>
        protected override void ReceiveData()
        {
            ClearAllCalValue();
            // 被捕食側が要求量の受信する
            ReceiveReqPREDATION();
            
            // 捕食者側が、捕食した獲物を取得
            ReceivePREDATION();
            // 呼吸関係
            ReceiveBREATHING();
            return;
        }

        /// <summary>
        /// 送信例
        /// </summary>
        protected override void SendData()
        {
            // 被捕食：捕獲された量を計算する
            SendPREDATION(m_csOcnBacedlInf.m_dCapturedMass, 0.1, 0.005);

            // 捕食者側：要求量を送信
            SendReqPREDATION(m_csOcnBacedlInf.m_ReqFoodMass);

            SendBREATHING();

            SendEXCRETION_DEATH(m_csOcnBacedlInf.m_dExcretionDencity, m_csOcnBacedlInf.m_dBulkDensity); 

            return;
        }

        //------------------------------------------------------------------
        protected virtual void ClearAllCalValue()
        {
            for (int ll = 0; ll < m_csOcnBacedlInf.m_lLayerNumber; ll++)
            {
                m_csOcnBacedlInf.m_Death[ll] = 0.0;
            }
        }


        //--------
        /// <summary>
        /// 被捕食者：　　被捕食者側が　要求捕食量を計算
        /// </summary>
        protected virtual void ReceiveReqPREDATION()
        {
            //------------------------
            // 要求される側（非捕食者）
            for (int ll = 0; ll < m_csOcnBacedlInf.m_lLayerNumber; ll++)
            {
                m_dWorkSumLayer[ll] = 1E-64;
                m_csOcnBacedlInf.m_TotalReqedPredationMass[ll] = 0.0;
            }
            for (int i = 0; i < m_csSndPredationCnnct.m_RcvInfNum; i++)
            {
                HySCellData[] csCell = m_csSndPredationCnnct.m_csRcvInfArry[i].GetInterpolatedCellD1();
                if (csCell != null)
                {
                    for (int ll = 0; ll < m_csOcnBacedlInf.m_lLayerNumber; ll++)
                    {
                        m_csOcnBacedlInf.m_TotalReqedPredationMass[ll] += csCell[ll].m_dData[0];
                        m_csSndPredationCnnct.m_dRcvRatioData[i][ll] = csCell[ll].m_dData[0];   // 分配の為、要求量を覚えておく
                        m_dWorkSumLayer[ll] += csCell[ll].m_dData[0];
                    }
                }
            }
            // 送信時の分配
            for (int ll = 0; ll < m_csOcnBacedlInf.m_lLayerNumber; ll++)
            {
                for (int i = 0; i < m_csSndPredationCnnct.m_RcvInfNum; i++)
                {
                    // 分配比計算
                    m_csSndPredationCnnct.m_dSendRatioData[i][ll] = m_csSndPredationCnnct.m_dRcvRatioData[i][ll] / m_dWorkSumLayer[ll];
                }
            }
        }
        /// <summary>
        /// 捕食者側：　　捕食関係、捕食者側が、捕食量の受信
        /// </summary>
        protected virtual void ReceivePREDATION()
        {
            ////------------------------
            //// 要求される側（非捕食者）
            //for (int ll = 0; ll < m_csOcnBacedlInf.m_lLayerNumber; ll++)
            //{
            //    m_dWorkSumLayer[ll] = 1.0E-8;
            //    m_csOcnBacedlInf.m_TotalReqedPredationMass[ll] = 0.0;
            //}
            //for (int i = 0; i < m_csSndPredationCnnct.m_RcvInfNum; i++)
            //{
            //    HySCellData[] csCell = m_csSndPredationCnnct.m_csRcvInfArry[i].GetInterpolatedCellD1();
            //    if (csCell != null)
            //    {
            //        for (int ll = 0; ll < m_csOcnBacedlInf.m_lLayerNumber; ll++)
            //        {
            //            m_csOcnBacedlInf.m_TotalReqedPredationMass[ll] += csCell[ll].m_dData[0];
            //            m_csSndPredationCnnct.m_dRcvRatioData[i][ll] = csCell[ll].m_dData[0];   // 分配の為、要求量を覚えておく
            //            m_dWorkSumLayer[ll] += csCell[ll].m_dData[0];
            //        }
            //    }
            //}
            //// 送信時の分配
            //for (int ll = 0; ll < m_csOcnBacedlInf.m_lLayerNumber; ll++)
            //{
            //    for (int i = 0; i < m_csSndPredationCnnct.m_RcvInfNum; i++)
            //    {
            //        // 分配比計算
            //        m_csSndPredationCnnct.m_dSendRatioData[i][ll] = m_csSndPredationCnnct.m_dRcvRatioData[i][ll] / m_dWorkSumLayer[ll]; 
            //    }
            //}

            //-----------------------
            // 要求する側（捕食者側）：＝被捕食者から提供された量に基づいて自分が捕食したトータル量を累積する       
            for (int ll = 0; ll < m_csOcnBacedlInf.m_lLayerNumber; ll++)
            {
                m_csOcnBacedlInf.m_EatenMass[ll] = 1E-42;
                m_csOcnBacedlInf.m_TotalFoodMass[ll] = 1E-42;
                m_dFoodDcty[ll] = 1E-42;
            }
            for (int i = 0; i < m_csRcvPredationCnnct.m_RcvInfNum; i++)
            {
                HySCellData[] csCell = m_csRcvPredationCnnct.m_csRcvInfArry[i].GetInterpolatedCellD1();
                if (csCell != null)
                {
                    for (int ll = 0; ll < m_csOcnBacedlInf.m_lLayerNumber; ll++)
                    {
                        m_csOcnBacedlInf.m_EatenMass[ll] += csCell[ll].m_dData[0];
                        m_dFoodDcty[ll] += csCell[ll].m_dData[0] * csCell[ll].m_dData[4];
                        m_csOcnBacedlInf.m_TotalFoodMass[ll] += csCell[ll].m_dData[3];
                        m_csRcvPredationCnnct.m_dRcvRatioData[i][ll] = csCell[ll].m_dData[3];   // 要求の為、資源量を覚えておく
                    }
                }
            }
            // 分配係数設定
            for (int ll = 0; ll < m_csOcnBacedlInf.m_lLayerNumber; ll++)
            {
                for (int i = 0; i < m_csRcvPredationCnnct.m_RcvInfNum; i++)
                {
                    // 分配比計算
                    m_csRcvPredationCnnct.m_dSendRatioData[i][ll] = m_csRcvPredationCnnct.m_dRcvRatioData[i][ll] / m_csOcnBacedlInf.m_TotalFoodMass[ll];
                }
                m_dFoodDcty[ll] = m_dFoodDcty[ll] / m_csOcnBacedlInf.m_EatenMass[ll];
            }

            // 食べたものの比重を計算する
            if (m_csRcvPredationCnnct.m_RcvInfNum > 0)
            {
                for (int ll = 0; ll < m_csOcnBacedlInf.m_lLayerNumber; ll++)
                {
                    // 食べたものの比重を計算する
                    if (m_csOcnBacedlInf.m_EatenMass[ll] <= 0.0)
                    {
                        m_csOcnBacedlInf.m_dExcretionDencity[ll] = m_csOcnBacedlInf.m_dBulkDensity;
                    }
                    else
                    {
                        m_csOcnBacedlInf.m_dExcretionDencity[ll]
                            = (m_csOcnBacedlInf.m_dBulkDensity * m_csOcnBacedlInf.m_TotalSelfMass[ll] + m_dFoodDcty[ll] * m_csOcnBacedlInf.m_EatenMass[ll]) / (m_csOcnBacedlInf.m_TotalSelfMass[ll] + m_csOcnBacedlInf.m_EatenMass[ll]);
                    }

                    m_csOcnBacedlInf.m_EatenMass[ll] -= 1E-42;
                    m_csOcnBacedlInf.m_TotalFoodMass[ll] -= 1E-42;
                }  // end of for(ll)
            }
            else
            {
                for (int ll = 0; ll < m_csOcnBacedlInf.m_lLayerNumber; ll++)
                {
                    m_dFoodDcty[ll] = m_csOcnBacedlInf.m_dBulkDensity;
                }
            }
        }

        /// <summary>
        /// 被捕食者：　　　捕食関係、被捕食者が提供捕食量の送信
        /// </summary>
        /// <param name="dSendFoodDt">各レイヤー毎のの捕獲された有機物数</param>
        /// <param name="dCRatio">有機物無機物比率</param>
        /// <param name="dMRatio">無機物無機物比率</param>
        protected virtual void SendPREDATION(double[] dSendFoodDt, double dCRatio, double dMRatio)
        {
            HySCellData[] csSndDt = null;

            //------------------------------
            // 非捕食者側：要求量から、捕食者への分配を計算し、捕食者側に送る
            //double dSum = 1.0E-8;
            //for (int ll = 0; ll < m_csOcnBacedlInf.m_lLayerNumber; ll++)
            //{
            //    m_dWorkSumLayer[ll] = 1.0E-8;
            //    for (int i = 0; i < m_csSndPredationCnnct.m_RcvInfNum; i++)
            //    {
            //        m_dWorkSumLayer[ll] += m_csSndPredationCnnct.m_dRcvRatioData[i][ll];
            //        dSum += m_csSndPredationCnnct.m_dRcvRatioData[i][ll];
            //    }
            //}
            // m_dWorkSumLayer[ll]は　 ReceivePREDATION()内ですでに計算されているので、此処で改めて計算しない

            // 非捕食者：捕食者へ要求量を 与える
            for (int i = 0; i < m_csSndPredationCnnct.m_RcvInfNum; i++)
            {
                csSndDt = m_csSndPredationCnnct.m_csSndInfArry[i].PrepareSendCellD1();
                if (csSndDt == null) { break; }
                for (int ll = 0; ll < m_csOcnBacedlInf.m_lLayerNumber; ll++)
                {
                    csSndDt[ll].m_dData[0] = dSendFoodDt[ll] * m_csSndPredationCnnct.m_dSendRatioData[i][ll];
                    csSndDt[ll].m_dData[1] = dCRatio * csSndDt[ll].m_dData[0];
                    csSndDt[ll].m_dData[2] = dMRatio * csSndDt[ll].m_dData[0];
                    csSndDt[ll].m_dData[3] = m_csOcnBacedlInf.m_TotalSelfMass[ll];
                    csSndDt[ll].m_dData[4] = m_csOcnBacedlInf.m_dBulkDensity;
                }
            }
            // 送信した分量だけ減らす
            if (m_csSndPredationCnnct.m_RcvInfNum > 0)
            {
                for (int ll = 0; ll < m_csOcnBacedlInf.m_lLayerNumber; ll++)
                {
                    // m_csOcnBacedlInf.m_TotalSelfMass[ll] -= dSendDt[ll]; <-- 既に別の場所で行っている
                    m_csOcnBacedlInf.m_dCapturedMass[ll] = 0.0;
                }
            }
        }

        /// <summary>
        /// 捕食者側：　　捕食関係、捕食者が要求量の送信
        /// </summary>
        /// <param name="dReqFoodDt">各レイヤー毎の要求書供物料</param>
        protected virtual void SendReqPREDATION(double[] dReqFoodDt)
        {
            HySCellData[] csSndDt = null;
            //------------------------------
            //捕食者側：相手の資源量から相手に対する要求量を送信する
            // この時相手の資源量をの比別に設定する
            //for (int i = 0; i < m_csSndPredationCnnct.m_RcvInfNum; i++)
            //{
            //    csSndDt = m_csSndPredationCnnct.m_csSndInfArry[i].PrepareSendCellD1();
            //    if (csSndDt == null) { break; }
            //    for (int ll = 0; ll < m_csOcnBacedlInf.m_lLayerNumber; ll++)
            //    {
            //        csSndDt[ll].m_dData[0] = dReqFoodDt[ll] * m_csSndPredationCnnct.m_dSendRatioData[i][ll];
            //    }
            //}
            for (int i = 0; i < m_csRcvPredationCnnct.m_RcvInfNum; i++)
            {
                csSndDt = m_csRcvPredationCnnct.m_csSndInfArry[i].PrepareSendCellD1();
                if (csSndDt == null) { break; }
                for (int ll = 0; ll < m_csOcnBacedlInf.m_lLayerNumber; ll++)
                {
                    csSndDt[ll].m_dData[0] = dReqFoodDt[ll] * m_csRcvPredationCnnct.m_dSendRatioData[i][ll];
                }
            }
        }
      
        //-------- 
        /// <summary>
        /// 呼吸：受信
        /// </summary>
        protected virtual void ReceiveBREATHING()
        {
            //// 蓄えの一部を無駄にする
            //for (int ll = 0; ll < m_csOcnBacedlInf.m_lLayerNumber; ll++)
            //{
            //    m_csOcnBacedlInf.m_O2[ll] = 0.9 * m_csOcnBacedlInf.m_O2[ll];
            //}
            //------------------------
            //// 要求される側（ガス側）
            //for (int ll = 0; ll < m_csOcnBacedlInf.m_lLayerNumber; ll++)
            //{
            //}
            //for (int i = 0; i < m_csSndBreathingCnnct.m_RcvInfNum; i++)
            //{
            //    HySCellData[] csCell = m_csSndBreathingCnnct.m_csRcvInfArry[i].GetInterpolatedCellD1();
            //    if (csCell != null)
            //    {
            //        for (int ll = 0; ll < m_csOcnBacedlInf.m_lLayerNumber; ll++)
            //        {
            //        }
            //    }
            //}
            // 呼吸者：
            for (int i = 0; i < m_csRcvBreathingCnnct.m_RcvInfNum; i++)
            {
                HySCellData[] csCell = m_csRcvBreathingCnnct.m_csRcvInfArry[i].GetInterpolatedCellD1();
                if (csCell != null)
                {
                    for (int ll = 0; ll < m_csOcnBacedlInf.m_lLayerNumber; ll++)
                    {
                        m_csOcnBacedlInf.m_O2[ll] += csCell[ll].m_dData[0];
                    }
                }
            }
        }

        /// <summary>
        /// 呼吸：送信
        /// </summary>
        protected virtual void SendBREATHING()
        {
            HySCellData[] csSndDt = null;
            //呼吸者
            // 供給O2量、排気ガス
            for (int i = 0; i < m_csRcvBreathingCnnct.m_RcvInfNum; i++)
            {
                csSndDt = m_csRcvBreathingCnnct.m_csSndInfArry[i].PrepareSendCellD1();
                if (csSndDt == null) { break; }
                for (int ll = 0; ll < m_csOcnBacedlInf.m_lLayerNumber; ll++)
                {
                    csSndDt[ll].m_dData[0] = m_csOcnBacedlInf.m_ReqO2[ll];
                    csSndDt[ll].m_dData[1] = m_csOcnBacedlInf.m_CO2[ll];
                    csSndDt[ll].m_dData[2] = m_csOcnBacedlInf.m_Gass1[ll];
                    csSndDt[ll].m_dData[3] = m_csOcnBacedlInf.m_Gass2[ll];
                }
            }
            //大気側
            // O2量
            //for (int i = 0; i < m_csSndBreathingCnnct.m_RcvInfNum; i++)
            //{
            //    csSndDt = m_csSndBreathingCnnct.m_csSndInfArry[i].PrepareSendCellD1();
            //    if (csSndDt == null) { break; }
            //    for (int ll = 0; ll < m_csOcnBacedlInf.m_lLayerNumber; ll++)
            //    {
            //        csSndDt[ll].m_dData[0] = m_csOcnBacedlInf.m_ReqO2[ll];
            //    }
            //}
        }

        //-------- 
        /// <summary>
        /// 排泄、死の送信
        /// </summary>
        /// <param name="dDensityExt">各レイヤー毎の糞密度(層別配列)</param>
        /// <param name="dDensityDth">死体密度</param>
        protected virtual void SendEXCRETION_DEATH( double[] dDensityExt, double dDensityDth)
        {
            HySCellData[] csSndDt = null;
            double dDivRto = 1.0;
            for (int i = 0; i < m_csSndExcretionDeathCnnct.m_RcvInfNum; i++)
            {
                // 複数へ送る場合等分配する
                dDivRto = 1.0 / m_csSndExcretionDeathCnnct.m_RcvInfNum;

                csSndDt = m_csSndExcretionDeathCnnct.m_csSndInfArry[i].PrepareSendCellD1();
                if (csSndDt == null) { break; }
                for (int ll = 0; ll < m_csOcnBacedlInf.m_lLayerNumber; ll++)
                {
                    csSndDt[ll].m_dData[0] = m_csOcnBacedlInf.m_ExcretionMass[ll] * dDivRto;
                    //csSndDt[ll].m_dData[1] = 
                    csSndDt[ll].m_dData[2] = m_csOcnBacedlInf.m_dSelfSize * m_csOcnBacedlInf.m_dEexcretionSize;
                    csSndDt[ll].m_dData[3] =  dDensityExt[ll] * m_csOcnBacedlInf.m_dIncDctyRatio;

                    csSndDt[ll].m_dData[4] = m_csOcnBacedlInf.m_Death[ll] * dDivRto;
                    //csSndDt[ll].m_dData[5] =
                    csSndDt[ll].m_dData[6] = m_csOcnBacedlInf.m_dSelfSize;
                    csSndDt[ll].m_dData[7] = dDensityDth * m_csOcnBacedlInf.m_dIncDctyRatio;
                }
            }
            //// 送信した分量だけ減らす　＜－－すでに別の場所で行っている
            //if (m_csSndExcretionDeath.m_RcvInfNum > 0)
            //{
            //    for (int ll = 0; ll < m_csOcnBacedlInf.m_lLayerNumber; ll++)
            //    {
            //        m_csOcnBacedlInf.m_TotalSelfMass[ll] -= m_csOcnBacedlInf.m_Death[ll];
            //    }
            //}
        }

        //------------------------------------------------------------------
        //------------------------------------------------------------------
        /// <summary>
        /// 代謝計算：吸収、排泄、増殖
        /// </summary>
        protected virtual void CalMetabolism()
        {
            double dltM = 0.0;
            for (int ll = 0; ll < m_csOcnBacedlInf.m_lLayerNumber; ll++)
            {
                // 増殖計算
                //double dNum = m_csOcnBacedlInf.m_TotalEatenMass[ll] / m_csOcnBacedlInf.m_dMultiplesK;

                // 質量の増加と、排泄物の形成
                m_csOcnBacedlInf.m_ExcretionMass[ll] = m_csOcnBacedlInf.m_EatenMass[ll] * m_csOcnBacedlInf.m_dEexcretionRatio;
                dltM = m_csOcnBacedlInf.m_EatenMass[ll] * (1.0 - m_csOcnBacedlInf.m_dEexcretionRatio);
                m_csOcnBacedlInf.m_TotalSelfMass[ll] += dltM;

                // 飢餓死計算
            }
        }

        /// <summary>
        /// 要求に応じて提供できる捕獲量
        /// </summary>
        /// <returns></returns>
        protected virtual double[] CalCapture()
        {
            for (int ll = 0; ll < m_csOcnBacedlInf.m_lLayerNumber; ll++)
            {
                if (m_csOcnBacedlInf.m_TotalSelfMass[ll] > m_csOcnBacedlInf.m_TotalReqedPredationMass[ll] / m_csOcnBacedlInf.m_CapturedRatio)
                {   // 要求量に対して、十分な量がある時
                    m_csOcnBacedlInf.m_dCapturedMass[ll] = m_csOcnBacedlInf.m_TotalReqedPredationMass[ll];
                }
                else
                {   // 要求量に対して、不足するとき
                    m_csOcnBacedlInf.m_dCapturedMass[ll] = m_csOcnBacedlInf.m_TotalSelfMass[ll] * m_csOcnBacedlInf.m_CapturedRatio * 0.99;
                }

                if ( m_csOcnBacedlInf.m_dCapturedMass[ll] > m_csOcnBacedlInf.m_TotalSelfMass[ll] * m_csOcnBacedlInf.m_CapturedRatio * 0.99)
                {
                    m_csOcnBacedlInf.m_dCapturedMass[ll] = m_csOcnBacedlInf.m_TotalSelfMass[ll] * m_csOcnBacedlInf.m_CapturedRatio * 0.99;
                }
                
                m_csOcnBacedlInf.m_TotalSelfMass[ll] -= m_csOcnBacedlInf.m_dCapturedMass[ll];
            }
            return m_csOcnBacedlInf.m_dCapturedMass;
        }

        /// <summary>
        ///死亡計算（自然死）
        /// </summary>
        /// <returns></returns>
        protected virtual void CalDeath()
        {
            for (int ll = 0; ll < m_csOcnBacedlInf.m_lLayerNumber; ll++)
            {
                m_csOcnBacedlInf.m_Death[ll] += m_csOcnBacedlInf.m_TotalSelfMass[ll] * m_csOcnBacedlInf.m_dDeathRatio;
                m_csOcnBacedlInf.m_TotalSelfMass[ll] -= m_csOcnBacedlInf.m_Death[ll];
            }
        }

        /// <summary>
        /// 餓死
        /// </summary>
        //protected virtual void Starvation()
        //{
        //}

        //------------------------------------------------------------------
        //------------------------------------------------------------------
        // 重力加速度

        static double GG = 9.8;  // [m/sec2]

        /// <summary> 海水温 </summary>
        static public double D0_Temperature = 21.0;
        static public double D100_Temperature = 15.0;
        static public double D250_Temperature = 10.0;
        static public double D600_Temperature = 5.0;
        static public double D1000_Temperature = 3.0;
        static public double D2000_Temperature = 2.0;
        static public double D3000_Temperature = 1.5;
 
        //------------------------------------------------------------------
        //------------------------------------------------------------------

        /// <summary>
        /// 沈降速度
        /// </summary>
        /// <param name="dH">m</param>
        /// <param name="Radius">mm</param>
        /// <param name="BulkDensity">g/cm^3</param>
        /// <returns> 沈降速度 m/sec </returns>
        public static double DroppingV(double dH, double Radius, double BulkDensity)
        {
            double dVV = 2.0 * GG * (Radius * 0.1) * (Radius * 0.1);
            dVV = dVV * (BulkDensity - WaterDensity(dH));
            dVV = dVV / 9.0;
            dVV = dVV / Co_Viscosity(dH);
            return dVV;
        }

        /// <summary><para>method outline:</para>
        /// <para>水温</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> bool bRtn = MzOceanWaterLayerModel.Temperature(dH) </para>
        /// </example>
        /// <param name="dH">水深 m </param>
        /// <returns> double 水温 °C </returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public static double Temperature(double dH)
        {
            double dT = D0_Temperature;
            if (dH <= 100)
            {
                dT = D0_Temperature - (D0_Temperature - D100_Temperature) * (dH) / 100;
            }
            else if (dH <= 250)
            {
                dT = D100_Temperature - (D100_Temperature - D250_Temperature) * (dH - 100) / (250 - 100);
            }
            else if (dH <= 600)
            {
                dT = D250_Temperature - (D250_Temperature - D600_Temperature) * (dH - 250) / (600 - 250);
            }
            else if (dH <= 1000)
            {
                dT = D600_Temperature - (D600_Temperature - D1000_Temperature) * (dH - 600) / (1000 - 600);
            }
            else if (dH <= 2000)
            {
                dT = D1000_Temperature - (D1000_Temperature - D2000_Temperature) * (dH - 1000) / (2000 - 1000);
            }
            else if (dH <= 3000)
            {
                dT = D2000_Temperature - (D2000_Temperature - D3000_Temperature) * (dH - 2000) / (3000 - 2000);
            }
            else
            {
                dT = D3000_Temperature;
            }
            return dT;
        }

        /// <summary>
        /// 水圧
        /// </summary>
        /// <param name="dH"></param>
        /// <returns> 水圧を kgf/ cm ^ 2 </returns>
        public static double Presser(double dH)
        {
            //double P = (1029.1 * dH + 0.0022 * dH * dH) * 9.80665 / 101325 + 1.0;  // 単位：アトム

            double P = ((1029.1 * dH + 0.0022 * dH * dH) + 101325 / 9.80665) / 10000.0;
            // 水圧を kgf/ cm ^ 2 （または工業気圧（at））で求めたければ
            return P;
        }

        /// <summary><para>method outline:</para>
        /// <para>海水密度   [g/cm^3]密度は  1.02 - 1.035 g/cm3</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para> bool bRtn = MzOceanWaterLayerModel.WaterDensity(dH) </para>
        /// </example>
        /// <param name="dH">水深 m </param>
        /// <returns> double 海水密度 g/cm^3 </returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>
        ///密度は深さによって変化します（海水35 ppm、0°C）
        ///深さ（m）	圧力（デシバール）	密度（g / cm 3）
        ///    0 	    0	    1.02813
        ///    1000 	1,000	1.03285
        ///    2000 	2,000	1.03747
        ///    4000 	4,000	1.04640
        ///    6000 	6,000	1.05495
        ///    8000 	8,000	1.06315
        ///    10000	10,000	1.07104
        /// </para>
        /// </remarks>
        public static double WaterDensity(double dH)
        {
            //return 1.025;
            //----------------------------

            double dR = 1.02813; // 1.025;
            if (dH <= 1000)
            {
                dR = 1.02813 + (1.03285 - 1.02813) * (dH) / 1000;
            }
            else if (dH <= 2000)
            {
                dR = 1.03285 + (1.03747 - 1.03285) * (dH - 1000) / (2000 - 1000);
            }
            else if (dH <= 4000)
            {
                dR = 1.03747 + (1.04640 - 1.03747) * (dH - 2000) / (4000 - 2000);
            }
            else if (dH <= 6000)
            {
                dR = 1.04640 + (1.05495 - 1.04640) * (dH - 4000) / (6000 - 4000);
            }
            else if (dH <= 8000)
            {
                dR = 1.05495 + (1.06315 - 1.05495) * (dH - 6000) / (8000 - 6000);
            }
            else if (dH <= 10000)
            {
                dR = 1.06315 + (1.07104 - 1.06315) * (dH - 8000) / (10000 - 8000);
            }
            else
            {
                dR = 1.07104;
            }
            return dR;
        }

        /// <summary>
        /// 粘性係数 g/cm/s
        /// </summary>
        /// <param name="dH"></param>
        /// <returns></returns>
        public static double Co_Viscosity(double dH)
        {
            double dV = 0.0185 - (0.0185 - 0.0106) * Temperature(dH) / 20.0;
            return dV * (1 - (1 - 0.969) * (dH / 6000));
        }

        /// <summary>
        /// Steeleの式：植物プランクトン　光、温度、制限式
        /// </summary>
        /// <param name="X">入力値</param>
        /// <param name="optX">最適値</param>
        /// <returns></returns>
        public static double Steele(double X, double optX)
        {
            return (X / optX * Math.Exp(1 - X / optX));
        }
        /// <summary>
        /// Monod の指揮：植物プランクトンの栄養成長限界
        /// </summary>
        /// <param name="X">栄養量</param>
        /// <param name="Cp">成長飽和量</param>
        /// <returns></returns>
        public static double Monod(double X, double Cp)
        {
            return X/(Cp + X);
        }
        /// <summary>
        /// Droop の式：植物プランクトン栄養制限式
        /// </summary>
        /// <param name="X">変数</param>
        /// <param name="Xmin">Xの最小値</param>
        /// <param name="Kmax">Xが無限大の時の理論値</param>
        /// <returns></returns>
        public static double Droop(double X, double Xmin, double Kmax)
        {
            //if( X <  Xmin) { X = Xmin*(1.001); }
            //double dRtn = (Kmax * (1.0 - Xmin / X));
            //return dRtn;
            // ＊＊＊＊＊＊＊＊  修正　＊＊＊＊＊＊＊＊＊＊
            if ( X < Xmin * 1.5 )
            {
                //return Kmax * (0.5 /1.5) * (X / Xmin);
                return Kmax * (1.0 / 1.5) * X / (Xmin + X);
            }
            else
            {
                return (Kmax * (1.0 - Xmin / X));
            }
        }

        /// <summary>
        /// １気圧での単位体積（ｍ３）当たりの酸素溶解度 g/m3
        /// </summary>
        /// <param name="T">温度℃</param>
        /// <returns>g/m3</returns>
        public static double GetDisolveO2( double T)
        {
            // ここでは温度依存性を考えていない
            // 20℃で 0.031cm3 溶解する、1mol は22.4L 分子量は32
            // 酸素は、大気の 20%
            return (0.031 / 22.4E3) * 1E6 * 32 * 0.2;
        }

        /// <summary>
        /// １気圧での単位体積（ｍ３）当たりの二酸化炭素溶解度 g/m3
        /// </summary>
        /// <param name="T">温度℃</param>
        /// <returns>g/m3</returns>
        public static double GetDisolveCO2(double T)
        {
            // ここでは温度依存性を考えていない
            // 20℃で 0.88cm3 溶解する、1mol は22.4L 分子量は44
            // 二酸化炭素は、大気の　400ppm = 400E-6とする
            return (0.88 / 22.4E3) * 1E6 * 44 * 400E-6;
        }

        /// <summary>
        /// 光強度減衰（１～０）
        /// この関数は正確ではない
        /// </summary>
        /// <param name="dMass">不溶物質：g/m3</param>
        /// <param name="iLayerNo"></param>
        /// <returns></returns>
        public static double Light( double dMass, int iLayerNo, double dMass0 = 5500.0 )
        {
            double dRtn = 1.0;
            if (iLayerNo > 1) { return 0.0; }

            dRtn = dMass0 / (dMass0 + dMass);
            if (iLayerNo == 1) { dRtn = dRtn * 0.05; }
            return dRtn;
        }

    }   // end of class
}
