Beispiel #1
0
 /// <summary>Make vector object from other vector object</summary>
 /// <param name="size">size of vector</param>
 /// <param name="startNumber"></param>
 /// <param name="originalVector"></param>
 internal Vector(uint size, uint startNumber, Vector originalVector)
 {
     this.isVectorView = true;
     this.viewSize = size;
     this.viewStartNumber = startNumber;
     this.originalVector = originalVector;
 }
Beispiel #2
0
 /// <summary>Constructor</summary>
 /// <param name="variableNumber">number of variables and functions</param>
 public MultiRoot(uint variableNumber)
 {
     this.VariableNumber = variableNumber;
     outputs1 = new double[variableNumber];
     outputs2 = new double[variableNumber];
     jacobian = new Matrix(variableNumber, variableNumber);
     fnc = new Vector(variableNumber);
 }
Beispiel #3
0
 /// <summary>行列とベクトルの積と和を計算する(y = α op(A) x + βy)</summary>
 /// <param name="vectorX">ベクトルX</param>
 /// <param name="vectorY">ベクトルY(解が上書きされる)</param>
 /// <param name="alpha">第一項の係数</param>
 /// <param name="beta">第二項の係数</param>
 internal void VectorProduct(Vector vectorX, ref Vector vectorY, double alpha, double beta)
 {
     for (uint i = 0; i < this.Columns; i++)
     {
         vectorY.SetValue(i, vectorY.GetValue(i) * beta);
         for (uint j = 0; j < this.Rows; j++)
         {
             vectorY.AddValue(i, alpha * this.GetValue(i, j) * vectorX.GetValue(j));
         }
     }
 }
Beispiel #4
0
 /// <summary></summary>
 /// <param name="vector"></param>
 internal void LUSolve(ref Vector vector)
 {
     if (isMatrixView)
     {
         uint ii = 0;
         for (uint i = 0; i < Rows; i++)
         {
             uint ip = perm[i];
             double sum = vector.GetValue(ip);
             vector.SetValue(ip, vector.GetValue(i));
             if (ii != 0)
             {
                 for (uint j = ii - 1; j < i; j++) sum -= GetValue(i, j) * vector.GetValue(j);
             }
             else if (sum != 0) ii = i + 1;
             vector.SetValue(i, sum);
         }
         for (int i = (int)Rows - 1; i >= 0; i--)
         {
             uint iii = (uint)i;
             double sum = vector.GetValue(iii);
             for (uint j = iii + 1; j < Columns; j++) sum -= GetValue(iii, j) * vector.GetValue(j);
             vector.SetValue(iii, sum / GetValue(iii, iii));
         }
     }
     else
     {
         uint ii = 0;
         for (uint i = 0; i < Rows; i++)
         {
             uint ip = perm[i];
             double sum = vector.GetValue(ip);
             vector.SetValue(ip, vector.GetValue(i));
             if (ii != 0)
             {
                 for (uint j = ii - 1; j < i; j++) sum -= mat[i, j] * vector.GetValue(j);
             }
             else if (sum != 0) ii = i + 1;
             vector.SetValue(i, sum);
         }
         for (int i = (int)Rows - 1; i >= 0; i--)
         {
             uint iii = (uint)i;
             double sum = vector.GetValue(iii);
             for (uint j = iii + 1; j < Columns; j++) sum -= mat[iii, j] * vector.GetValue(j);
             vector.SetValue(iii, sum / mat[iii, iii]);
         }
     }
 }
Beispiel #5
0
 /// <summary>matrix1の逆行列を計算してmatrix2に設定する</summary>
 /// <param name="matrix"></param>
 internal void GetInverse(ref Matrix matrix)
 {
     LUDecomposition();
     Vector col = new Vector(Columns);
     for (uint j = 0; j < Columns; j++)
     {
         col.SetValue(0);
         col.SetValue(j, 1);
         LUSolve(ref col);
         for (uint i = 0; i < Columns; i++) matrix.SetValue(i, j, col.GetValue(i));
     }
 }
Beispiel #6
0
        /// <summary>行列要素を設定する(JOSモデル)</summary>
        /// <param name="zm">ZMベクトル(要素の単位は全てW)</param>
        /// <param name="bm">BM行列(要素の単位は全てW/K)</param>
        private void makeJOSMatrix(ref Vector zm, ref Matrix bm)
        {
            const double RCS = HumanBody.RHO_C / 3.6d;  //流量単位がL/hなので、ここで単位を調整
            double dt = Body.timeStep;
            bool hasAVA = (heatCapacity_SuperficialVein != 0);
            double sum;

            //JOS計算用にコア・脂肪・筋肉層を統合
            double hcapCore = heatCapacity_Core + heatCapacity_Fat + heatCapacity_Muscle;
            double bfCore = bloodFlow_Core + bloodFlow_Fat + bloodFlow_Muscle;
            double mrCore = metabolicRate_Core + metabolicRate_Fat + metabolicRate_Muscle;

            //皮膚・空気間の熱コンダクタンスを更新
            updateHeatConductance_Skin_Air();

            //蒸発熱損失を計算
            //不感蒸泄分
            double eMax = LatentHeatConductance_Skin_Air * (HumanBody.getSaturatedVaporPressure(SkinTemperature_NonContact)
                - HumanBody.getVaporPressure(DrybulbTemperature, RelativeHumidity, Body.AtmosphericPressure));
            EvaporativeHeatLoss = 0.06 * eMax + EvaporativeHeatLoss_Sweat * 0.94;

            //ZMベクトルを設定*************************************************************************
            zm.SetValue(0, hcapCore * 3600 * coreTemperature / dt + mrCore + WorkLoad + ShiveringLoad);
            zm.SetValue(1, heatCapacity_Skin * 3600 * SkinTemperature_Contact / dt + MaterialTemperature * HeatConductance_Skin_Material * SurfaceArea + metabolicRate_Skin);
            zm.SetValue(2, heatCapacity_Skin * 3600 * SkinTemperature_NonContact / dt + OperativeTemperature * HeatConductance_Skin_Air + metabolicRate_Skin - EvaporativeHeatLoss);
            zm.SetValue(3, heatCapacity_Artery * 3600 * arteryTemperature / dt);
            zm.SetValue(4, heatCapacity_DeepVein * 3600 * deepVeinTemperature / dt);
            if (hasAVA) zm.SetValue(5, heatCapacity_SuperficialVein * 3600 * superficialVeinTemperature / dt);

            //BM行列を設定*****************************************************************************
            //コア層
            bm.SetValue(0, 0, hcapCore * 3600d / dt + RCS * bfCore
                + 2 * heatConductance_Vein_Core + heatConductance_Core_Skin);
            bm.SetValue(0, 1, -ContactPortionRate * heatConductance_Core_Skin);
            bm.SetValue(0, 2, -NonContactPortionRate * heatConductance_Core_Skin);
            bm.SetValue(0, 3, -(RCS * bfCore + heatConductance_Vein_Core));
            bm.SetValue(0, 4, -heatConductance_Vein_Core);
            if (hasAVA) bm.SetValue(0, 5, 0);

            //皮膚層接触部
            bm.SetValue(1, 0, -heatConductance_Core_Skin);
            bm.SetValue(1, 1, heatCapacity_Skin * 3600d / dt + RCS * bloodFlow_Skin + heatConductance_Core_Skin
                + heatConductance_SuperficialVein_Skin + HeatConductance_Skin_Material * SurfaceArea);
            bm.SetValue(1, 2, 0);
            bm.SetValue(1, 3, -RCS * bloodFlow_Skin);
            bm.SetValue(1, 4, 0);
            if (hasAVA) bm.SetValue(1, 5, -heatConductance_SuperficialVein_Skin);

            //皮膚層非接触部
            bm.SetValue(2, 0, -heatConductance_Core_Skin);
            bm.SetValue(2, 1, 0);
            bm.SetValue(2, 2, heatCapacity_Skin * 3600d / dt + RCS * bloodFlow_Skin + heatConductance_Core_Skin
                + heatConductance_SuperficialVein_Skin + HeatConductance_Skin_Air);
            bm.SetValue(2, 3, -RCS * bloodFlow_Skin);
            bm.SetValue(2, 4, 0);
            if (hasAVA) bm.SetValue(2, 5, -heatConductance_SuperficialVein_Skin);

            //動脈
            bm.SetValue(3, 0, -heatConductance_Vein_Core);
            bm.SetValue(3, 1, 0);
            bm.SetValue(3, 2, 0);
            bm.SetValue(3, 3, heatCapacity_Artery * 3600d / dt + RCS * bloodFlow_Artery + heatConductance_Vein_Core + heatConductance_Artery_DeepVein);
            bm.SetValue(3, 4, -heatConductance_Artery_DeepVein);
            if (hasAVA) bm.SetValue(3, 5, 0);

            //深部静脈
            bm.SetValue(4, 0, -(RCS * bfCore + heatConductance_Vein_Core));
            bm.SetValue(4, 1, -ContactPortionRate * RCS * bloodFlow_Skin);
            bm.SetValue(4, 2, -NonContactPortionRate * RCS * bloodFlow_Skin);
            bm.SetValue(4, 3, -heatConductance_Artery_DeepVein);
            sum = heatCapacity_DeepVein * 3600d / dt + RCS * bfCore + RCS * bloodFlow_Skin
                + heatConductance_Vein_Core + heatConductance_Artery_DeepVein;
            foreach (BodyPart bp in bpConnectTo)
            {
                if (Position == HumanBody.Nodes.Pelvis) sum += RCS * (bp.GetBloodFlow(Segments.DeepVein) + bp.GetBloodFlow(Segments.SuperficialVein));
                else sum += RCS * bp.GetBloodFlow(Segments.DeepVein);
            }
            bm.SetValue(4, 4, sum);
            if (hasAVA) bm.SetValue(4, 5, 0);

            //表在静脈
            if (hasAVA)
            {
                bm.SetValue(5, 0, 0);
                bm.SetValue(5, 1, -ContactPortionRate * heatConductance_SuperficialVein_Skin);
                bm.SetValue(5, 2, -NonContactPortionRate * heatConductance_SuperficialVein_Skin);
                //四肢末端部の場合
                if ((Position & HumanBody.Nodes.TerminalPart) != HumanBody.Nodes.None) bm.SetValue(5, 3, -RCS * GetBloodFlow(Segments.SuperficialVein));
                //その他
                else bm.SetValue(5, 3, 0);
                bm.SetValue(5, 4, 0);
                sum = heatCapacity_SuperficialVein * 3600d / dt + heatConductance_SuperficialVein_Skin;
                if ((Position & HumanBody.Nodes.TerminalPart) != HumanBody.Nodes.None) sum += RCS * GetBloodFlow(Segments.SuperficialVein);
                if (Position != HumanBody.Nodes.Pelvis)
                {
                    foreach (BodyPart bp in bpConnectTo) sum += RCS * bp.GetBloodFlow(Segments.SuperficialVein);
                }
                bm.SetValue(5, 5, sum);
            }
        }
Beispiel #7
0
        /// <summary>温度[C]を設定する</summary>
        /// <param name="temperatures">温度[C]</param>
        internal void setTemperature(Vector temperatures)
        {
            coreTemperature = temperatures.GetValue(0);
            SkinTemperature_Contact = temperatures.GetValue(1);
            SkinTemperature_NonContact = temperatures.GetValue(2);
            arteryTemperature = temperatures.GetValue(3);
            deepVeinTemperature = temperatures.GetValue(4);
            if (heatCapacity_SuperficialVein != 0) superficialVeinTemperature = temperatures.GetValue(5);

            if (! isJOSModel)
            {
                if (heatCapacity_SuperficialVein != 0)
                {
                    muscleTemperature = temperatures.GetValue(6);
                    fatTemperature = temperatures.GetValue(7);
                }
                else
                {
                    muscleTemperature = temperatures.GetValue(5);
                    fatTemperature = temperatures.GetValue(6);
                }
            }
        }
Beispiel #8
0
 /// <summary>行列要素を設定する</summary>
 /// <param name="zm">ZMベクトル(要素の単位は全てW)</param>
 /// <param name="bm">BM行列(要素の単位は全てW/K)</param>
 internal void makeMatrix(ref Vector zm, ref Matrix bm)
 {
     if (isJOSModel) makeJOSMatrix(ref zm, ref bm);
     else make132MNMatrix(ref zm, ref bm);
 }
Beispiel #9
0
        /// <summary>UX行列を更新する</summary>
        private void makeUMatrix()
        {
            uint mNumber = (uint)res.Length - 1;

            //逆行列計算領域を確保
            if (uMatrix.Columns != mNumber)
            {
                uMatrix = new Matrix(mNumber, mNumber);
                uMatrix2 = new Matrix(mNumber, mNumber);
                //perm = new Permutation(mNumber);
                perm = new uint[mNumber];
                uxMatrix = new Matrix(mNumber, mNumber);
                cfVector = new Vector(mNumber);
                uL = new double[mNumber];
                uR = new double[mNumber];
                ux0mMatrix = new Matrix(mNumber, 2);
                temperatures = new Vector(mNumber);
                temperaturesLMAT = new Vector(mNumber);
                temperaturesFRZ = new Vector(mNumber);
                fpt1 = new Vector(mNumber);
                fpt2 = new Vector(mNumber);
            }
            uMatrix.Initialize(0);
            //perm.Initialize();

            for (int i = 0; i < mNumber; i++)
            {
                double c = 0.5 * (cap[i] + cap[i + 1]);
                uL[i] = timeStep / (c * res[i]);
                uR[i] = timeStep / (c * res[i + 1]);
            }

            uMatrix.SetValue(0, 0, 1d + uL[0] + uR[0]);
            for (uint i = 1; i < mNumber; i++)
            {
                uMatrix.SetValue(i, i, 1d + uL[i] + uR[i]);
                uMatrix.SetValue(i, i - 1, -uL[i]);
                uMatrix.SetValue(i - 1, i, -uR[i - 1]);
            }
        }
Beispiel #10
0
 /// <summary>ベクトルをベクトルにコピーする</summary>
 /// <param name="vector">コピー先のベクトル</param>
 internal void CopyTo(ref Vector vector)
 {
     if (isVectorView)
     {
         for (uint i = 0; i < viewSize; i++) vector.vect[i] = originalVector.GetValue(i + viewStartNumber);
     }
     else
     {
         for (int i = 0; i < this.vect.Length; i++) vector.vect[i] = this.vect[i];
     }
 }
Beispiel #11
0
 /// <summary>ベクトルの内容をピーする</summary>
 /// <param name="vector">コピーもとのベクトル</param>
 internal void CopyFrom(Vector vector)
 {
     if (isVectorView)
     {
         for (uint i = 0; i < viewSize; i++) originalVector.SetValue(i + viewStartNumber, vector.vect[i]);
     }
     else
     {
         for (int i = 0; i < this.vect.Length; i++) this.vect[i] = vector.vect[i];
     }
 }
Beispiel #12
0
        /// <summary>体温を更新する</summary>
        private void updateBodyTemperature()
        {
            const double RCS = RHO_C / 3.6d;  //流量単位がL/hなので、ここで単位を調整

            //対流熱伝達率の補正係数を計算
            double sumHc = 0;
            double sumVl = 0;
            double sumArea = 0;
            foreach (Nodes bp in parts.Keys)
            {
                BodyPart part = parts[bp];
                sumVl += part.Velocity * part.SurfaceArea;
                sumHc += part.ConvectiveHeatTransferCoefficient * part.SurfaceArea;
                sumArea += part.SurfaceArea;
            }
            sumHc /= sumArea;
            sumVl /= sumArea;
            convectiveHeatTransferCoefficientMod = Math.Max(8.600001 * Math.Pow(sumVl, 0.53) / sumHc, 3d / sumHc);

            //行列初期化
            bmMatrix.Initialize(0);
            zmVector.SetValue(0);

            //部位温度に関する行列を用意
            Matrix bmView;
            Vector zmView;
            double coreSum = HeatCapacity_CentralBloodPool * 3600 / timeStep;
            foreach (Nodes bp in parts.Keys)
            {
                BodyPart part = parts[bp];
                uint startPoint = bpDict[bp];
                bool hasAVA = (part.GetHeatCapacity(BodyPart.Segments.SuperficialVein) != 0);

                //部位別の行列要素を設定******************
                uint size = 5;
                if (!part.IsJOSModel) size += 2;
                if (part.GetHeatCapacity(BodyPart.Segments.SuperficialVein) != 0) size += 1;
                bmView = new Matrix(size, size, startPoint, startPoint, bmMatrix);
                zmView = new Vector(size, startPoint, zmVector);
                part.makeMatrix(ref zmView, ref bmView);

                //部位間血流に関する行列要素を設定********
                BodyPart ptf = part.bpConnectFrom;
                //上流に部位が存在する場合
                if (ptf != null) bmMatrix.SetValue(startPoint + 3, bpDict[ptf.Position] + 3, - RCS * part.GetBloodFlow(BodyPart.Segments.Artery));
                //上流が中央血液だまりの場合
                else
                {
                    //動脈血流による熱移動
                    bmMatrix.SetValue(startPoint + 3, bmMatrix.Columns - 1, -RCS * part.GetBloodFlow(BodyPart.Segments.Artery));

                    //中央血液だまりへ向かう静脈血流による熱移動を計算
                    bmMatrix.SetValue(bmMatrix.Columns - 1, startPoint + 4, -RCS * part.GetBloodFlow(BodyPart.Segments.DeepVein));
                    if (hasAVA) bmMatrix.SetValue(bmMatrix.Columns - 1, startPoint + 5, -RCS * part.GetBloodFlow(BodyPart.Segments.SuperficialVein));
                    coreSum += RCS * part.GetBloodFlow(BodyPart.Segments.DeepVein) + RCS * part.GetBloodFlow(BodyPart.Segments.SuperficialVein);
                }

                //静脈血流による熱移動
                List<BodyPart> ptts = part.bpConnectTo;
                foreach (BodyPart ptt in ptts)
                {
                    uint stp2 = bpDict[ptt.Position];

                    //深部静脈血流による熱移動
                    bmMatrix.SetValue(startPoint + 4, stp2 + 4, -RCS * ptt.GetBloodFlow(BodyPart.Segments.DeepVein));

                    //表在静脈血流による熱移動
                    if (part.Position == Nodes.Pelvis)
                    {
                        //腰部の場合は深部静脈に流れ込む
                        bmMatrix.SetValue(startPoint + 4, stp2 + 5, -RCS * ptt.GetBloodFlow(BodyPart.Segments.SuperficialVein));
                    }
                    else
                    {
                        //腰部以外の場合は表在静脈に流れ込む
                        if(ptt.GetHeatCapacity(BodyPart.Segments.SuperficialVein) != 0) bmMatrix.SetValue(startPoint + 5, stp2 + 5, -RCS * ptt.GetBloodFlow(BodyPart.Segments.SuperficialVein));
                    }
                }
            }

            //中央血液だまりに関する行列要素を設定
            bmMatrix.SetValue(bmMatrix.Columns - 1, bmMatrix.Columns - 1, coreSum);
            zmVector.SetValue(zmVector.Size - 1, HeatCapacity_CentralBloodPool * 3600 * CentralBloodPoolTemperature / timeStep);

            //胸部に関して呼吸による項を設定
            double wlSum = 0;
            foreach(Nodes bp in parts.Keys) wlSum += parts[bp].WorkLoad + parts[bp].ShiveringLoad;
            BodyPart head = parts[Nodes.Head];
            HeatLossByBreathing = (0.0014 * (34 - head.DrybulbTemperature)
                + 0.0173 * (5.867 - getVaporPressure(head.DrybulbTemperature, head.RelativeHumidity, 101.325)))
                * (wlSum + BasicMetabolicRate);
            zmVector.AddValue(bpDict[Nodes.Chest], -HeatLossByBreathing);

            //逆行列を計算
            for (uint i = 0; i < perm.Length; i++) perm[i] = i;
            bmMatrix.LUDecomposition();
            bmMatrix.LUSolve(ref zmVector);
            //LinearAlgebra.LUDecomposition(ref bmMatrix, ref perm);
            //LinearAlgebra.LUSolve(bmMatrix, perm, ref zmVector);

            //温度を更新・設定
            foreach (Nodes bp in parts.Keys)
            {
                BodyPart part = parts[bp];

                uint size = 5;
                if (!part.IsJOSModel) size += 2;
                if (part.GetHeatCapacity(BodyPart.Segments.SuperficialVein) != 0) size += 1;
                zmView = new Vector(size, bpDict[bp], zmVector);
                part.setTemperature(zmView);
            }
            CentralBloodPoolTemperature = zmVector.GetValue(zmVector.Size - 1);
        }
Beispiel #13
0
        /// <summary>初期化処理</summary>
        /// <param name="weight">体重[kg]</param>
        /// <param name="height">身長[m]</param>
        /// <param name="age">年齢</param>
        /// <param name="isMale">男性か否か</param>
        /// <param name="cardiacIndexAtRest">安静時の心係数[L/(min m^2)]</param>
        /// <param name="fatPercentage">体脂肪率[%]</param>
        private void initialize(double weight, double height, double age, bool isMale, double cardiacIndexAtRest, double fatPercentage)
        {
            Weight = weight;
            Height = height;
            Age = age;
            IsMale = isMale;
            CardiacIndexAtRest = cardiacIndexAtRest;
            FatPercentage = fatPercentage;

            //体表面積を初期化する
            SurfaceArea = 0.202 * Math.Pow(Weight, 0.425) * Math.Pow(Height, 0.725);
            //代謝量[W]を初期化する
            initMetabolicRate();
            //血流量[L/h]を初期化する
            BaseBloodFlowRate = cardiacIndexAtRest * 60 * SurfaceArea;
            //中央血液だまりの熱容量[Wh/K]を初期化する
            HeatCapacity_CentralBloodPool = 1.999 * CardiacIndexAtRest * 60 * SurfaceArea / STANDARD_BLOOD_FLOW;

            //部位を作成
            Nodes[] pos = (Nodes[])Enum.GetValues(typeof(Nodes));
            foreach (Nodes bp in pos)
            {
                if (bp != Nodes.TerminalPart && bp != Nodes.None)
                {
                    parts.Add(bp, new BodyPart(this, bp));
                }
            }

            //部位を接続
            parts[Nodes.Neck].connect(parts[Nodes.Head]);
            parts[Nodes.Pelvis].connect(parts[Nodes.LeftThigh]);
            parts[Nodes.Pelvis].connect(parts[Nodes.RightThigh]);
            parts[Nodes.LeftThigh].connect(parts[Nodes.LeftLeg]);
            parts[Nodes.RightThigh].connect(parts[Nodes.RightLeg]);
            parts[Nodes.LeftLeg].connect(parts[Nodes.LeftFoot]);
            parts[Nodes.RightLeg].connect(parts[Nodes.RightFoot]);
            parts[Nodes.LeftShoulder].connect(parts[Nodes.LeftArm]);
            parts[Nodes.RightShoulder].connect(parts[Nodes.RightArm]);
            parts[Nodes.LeftArm].connect(parts[Nodes.LeftHand]);
            parts[Nodes.RightArm].connect(parts[Nodes.RightHand]);

            //姿勢を設定
            SetPosture(BodyPosture.Standing);

            //仕事量を設定
            SetWorkLoad(58);

            //気流速度[m/s]を設定
            SetVelocity(0);

            //着衣量[clo]を設定
            SetClothingIndex(Nodes.Chest, 0.62);
            SetClothingIndex(Nodes.Back, 0.74);
            SetClothingIndex(Nodes.Pelvis, 1.18);
            SetClothingIndex(Nodes.LeftShoulder, 0.45);
            SetClothingIndex(Nodes.RightShoulder, 0.45);
            SetClothingIndex(Nodes.LeftThigh, 0.38);
            SetClothingIndex(Nodes.LeftLeg, 0.69);
            SetClothingIndex(Nodes.LeftFoot, 1.23);
            SetClothingIndex(Nodes.RightThigh, 0.38);
            SetClothingIndex(Nodes.RightLeg, 0.69);
            SetClothingIndex(Nodes.RightFoot, 1.23);

            //体温を初期化
            InitializeTemperature(36);

            //行列初期化
            uint varSum = 0;
            foreach (Nodes bp in parts.Keys)
            {
                bpDict.Add(bp, varSum);

                varSum += 5;
                BodyPart part = parts[bp];
                //筋肉・脂肪・コアを統合するJOSモデルではない場合
                if (!part.IsJOSModel) varSum += 2;
                //AVAによる表在静脈がある場合
                if (part.GetHeatCapacity(BodyPart.Segments.SuperficialVein) != 0) varSum += 1;
            }

            //計算領域初期化
            varSum++;
            bmMatrix = new Matrix(varSum, varSum);
            zmVector = new Vector(varSum);
            perm = new uint[varSum];

            //セットポイント初期化
            initializeSetPoint();
        }
Beispiel #14
0
        /// <summary>室の乾球温度を更新する</summary>
        public void UpdateRoomTemperatures()
        {
            //タイムステップ確認
            if (!isTimeStepCorrect()) throw new Exception("計算時間間隔が不正です");

            //壁および窓の構成が変化した場合には逆行列を初期化
            if (hasFIOChanged) makeXAMatrix();

            //各Roomの放射を壁面に設定
            setRadiationToSurface();

            //壁表面計算用行列を作成
            makeARMatrixAndCAVector();

            //行列入れ替え配列を作成
            uint ffZones = makePermVectorDB();

            //Bマトリクス・Bベクトル・Tマトリクスを作成
            for (uint i = 0; i < zones.Length; i++)
            {
                //Bマトリクスを作成
                //ゾーンの熱容量/時間間隔[W/K]を計算
                double airSV = MoistAir.GetAirStateFromDBHR(zones[i].CurrentDrybulbTemperature,
                            zones[i].CurrentHumidityRatio, MoistAir.Property.SpecificVolume);
                double cpAir = MoistAir.GetSpecificHeat(zones[i].CurrentHumidityRatio) * 1000;
                double zSH = (zones[i].Volume / airSV * cpAir + zones[i].SensibleHeatCapacity) / TimeStep;
                double cgo = zones[i].VentilationVolume / airSV / 3600d * cpAir;
                Dictionary<ImmutableZone, double> aFlow = airFlowToZone[zones[i]];

                for (uint j = 0; j < zones.Length; j++)
                {
                    double cgr = 0;
                    //対角成分
                    if (i == j)
                    {
                        foreach (Zone key in aFlow.Keys) cgr += aFlow[key];
                        cgr = cgr / airSV / 3600d * cpAir;
                        bMatrix.SetValue(arbPerm[i], arbPerm[j], zSH + arMatrix[i, j] + cgo + cgr);
                    }
                    //その他成分
                    else
                    {
                        if (aFlow.ContainsKey(zones[j])) cgr = aFlow[zones[j]] / airSV / 3600d * cpAir;
                        else cgr = 0;
                        bMatrix.SetValue(arbPerm[i], arbPerm[j], -(arMatrix[i, j] + cgr));
                    }
                }

                //Bベクトル・Tマトリクス
                bVector.SetValue(arbPerm[i], zSH * zones[i].CurrentDrybulbTemperature
                    + caVector[i] + cgo * zones[i].VentilationAirState.DryBulbTemperature
                    + zones[i].integrateConvectiveHeatGain());
                if (zones[i].ControlDrybulbTemperature)
                {
                    tzVector.SetValue(arbPerm[i], zones[i].DrybulbTemperatureSetPoint);
                }
                else
                {
                    bVector.AddValue(arbPerm[i], zones[i].SensibleHeatSupply);
                    //-供給熱量[W]が即ち熱負荷[W]
                    zones[i].CurrentSensibleHeatLoad = -zones[i].SensibleHeatSupply;
                }
            }

            //定数部分を差し引く
            uint ccZones = (uint)(zones.Length - ffZones);
            for (uint i = 0; i < ffZones; i++)
            {
                double br = bVector.GetValue(i);
                for (uint j = 0; j < ccZones; j++)
                {
                    br -= bMatrix.GetValue(i, j + ffZones) * tzVector.GetValue(j + ffZones);
                }
                bVector.SetValue(i, br);
            }

            //MatrixView mView = new MatrixView(bMatrix, 0, 0, ffZones, ffZones);
            //VectorView bView = new VectorView(bVector, 0, ffZones);
            //VectorView tView = new VectorView(tzVector, 0, ffZones);

            Matrix mView = new Matrix(ffZones, ffZones, 0, 0, bMatrix);
            Vector bView = new Vector(ffZones, 0, bVector);
            Vector tView = new Vector(ffZones, 0, tzVector);
            //空気温度が変動するゾーンを逆行列で解く
            if (0 < ffZones)
            {
                Matrix xmView = new Matrix(ffZones, ffZones, 0, 0, xbMatrix);
                mView.GetInverse(ref xmView);
                xmView.VectorProduct(bView, ref tView, 1, 0);
            }

            //温度をゾーンに設定
            for (uint i = 0; i < zones.Length; i++) zones[i].setDrybulbTemperature(tzVector.GetValue(arbPerm[i]));

            if (0 < ccZones)
            {
                //空気温度指定ゾーンの熱負荷を計算
                //ゾーン空気温度に依存する成分
                mView = new Matrix(ccZones, (uint)zones.Length, ffZones, 0, bMatrix);
                tView = new Vector(tzVector.Size, 0, tzVector);
                bView = new Vector(ccZones, ffZones, bbVector);
                mView.VectorProduct(tView, ref bView, 1, 0);
                //
                for (uint i = 0; i < zones.Length; i++)
                {
                    if (zones[i].ControlDrybulbTemperature)
                    {
                        zones[i].CurrentSensibleHeatLoad = -(bbVector.GetValue(arbPerm[i]) - bVector.GetValue(arbPerm[i]));
                    }
                }
            }

            //表面温度を計算する
            surfaceTemperatures.SetValue(0);
            foreach (Zone spc in rxVector.Keys)
            {
                Vector vec = raVector[spc];
                for (uint i = 0; i < vec.Size; i++) surfaceTemperatures.AddValue(i, vec.GetValue(i) * spc.CurrentDrybulbTemperature);
            }
            for (uint i = 0; i < craVector.Size; i++) surfaceTemperatures.AddValue(i, craVector.GetValue(i));

            //室温を表面に設定
            for (int i = 0; i < zones.Length; i++)
            {
                ISurface[] sfs = zones[i].getSurfaces();
                for (int j = 0; j < sfs.Length; j++)
                {
                    //表面近傍の空気温度を設定
                    sfs[j].AirTemperature = zones[i].CurrentDrybulbTemperature * sfs[j].ConvectiveRate;
                }
            }

            //放射を表面に設定
            phi.VectorProduct(surfaceTemperatures, ref surfaceMRTs, 1, 0);
            for (uint i = 0; i < surfaces.Length; i++)
            {
                surfaces[i].Radiation += surfaceMRTs.GetValue(i) * surfaces[i].FilmCoefficient;
            }

            //平均放射温度[C]を計算して設定
            foreach (Room room in rooms)
            {
                ImmutableSurface[] sfs = room.GetSurface();
                double mrt = 0;
                double aSum = 0;
                for (int i = 0; i < sfs.Length; i++)
                {
                    mrt += sfs[i].Temperature * sfs[i].Area;
                    aSum += sfs[i].Area;
                }
                mrt /= aSum;
                Zone[] zns = room.getZone();
                for (int i = 0; i < zns.Length; i++) zns[i].setMeanRadiantTemperature(mrt);
            }
        }
Beispiel #15
0
        /// <summary>室の絶対湿度を更新する</summary>
        public void UpdateRoomHumidities()
        {
            //行列入れ替え配列を作成
            uint ffZones = makePermVectorAH();

            //Bマトリクス・Bベクトル・Tマトリクスを作成
            for (uint i = 0; i < zones.Length; i++)
            {
                //Bマトリクスを作成
                //ゾーンの水蒸気容量/時間間隔[W/K]を計算
                double airSV = MoistAir.GetAirStateFromDBHR(zones[i].CurrentDrybulbTemperature,
                            zones[i].CurrentHumidityRatio, MoistAir.Property.SpecificVolume);
                double zSH = (zones[i].Volume / airSV + zones[i].LatentHeatCapacity) / TimeStep;
                double cgo = zones[i].VentilationVolume / airSV / 3600d;
                Dictionary<ImmutableZone, double> aFlow = airFlowToZone[zones[i]];

                for (uint j = 0; j < zones.Length; j++)
                {
                    double cgr = 0;
                    //対角成分
                    if (i == j)
                    {
                        foreach (Zone key in aFlow.Keys) cgr += aFlow[key];
                        cgr = cgr / airSV / 3600d;
                        bMatrix.SetValue(arbPerm[i], arbPerm[j], zSH + cgo + cgr);
                    }
                    //その他成分
                    else
                    {
                        if (aFlow.ContainsKey(zones[j])) cgr = aFlow[zones[j]] / airSV / 3600d;
                        else cgr = 0;
                        bMatrix.SetValue(arbPerm[i], arbPerm[j], -cgr);
                    }
                }

                //Bベクトル・Tマトリクス
                bVector.SetValue(arbPerm[i], zSH * zones[i].CurrentHumidityRatio
                    + cgo * zones[i].VentilationAirState.HumidityRatio
                    + zones[i].integrateLatentHeatGain() / MoistAir.LatentHeatOfVaporization / 1000);
                if (zones[i].ControlHumidityRatio)
                {
                    tzVector.SetValue(arbPerm[i], zones[i].HumidityRatioSetPoint);
                }
                else
                {
                    bVector.AddValue(arbPerm[i], zones[i].LatentHeatSupply / MoistAir.LatentHeatOfVaporization / 1000);
                    //-供給熱量[W]が即ち熱負荷[W]
                    zones[i].CurrentLatentHeatLoad = -zones[i].LatentHeatSupply;
                }
            }

            //定数部分を差し引く
            uint ccZones = (uint)(zones.Length - ffZones);
            for (uint i = 0; i < ffZones; i++)
            {
                double br = bVector.GetValue(i);
                for (uint j = 0; j < ccZones; j++)
                {
                    br -= bMatrix.GetValue(i, j + ffZones) * tzVector.GetValue(j + ffZones);
                }
                bVector.SetValue(i, br);
            }

            //MatrixView mView = new MatrixView(bMatrix, 0, 0, ffZones, ffZones);
            //VectorView bView = new VectorView(bVector, 0, ffZones);
            //VectorView tView = new VectorView(tzVector, 0, ffZones);
            Matrix mView = new Matrix(ffZones, ffZones, 0, 0, bMatrix);
            Vector bView = new Vector(ffZones, 0, bVector);
            Vector tView = new Vector(ffZones, 0, tzVector);
            //空気湿度が変動するゾーンを逆行列で解く
            if (0 < ffZones)
            {
                //int sig;
                Matrix xmView = new Matrix(ffZones, ffZones, 0, 0, xbMatrix);
                mView.GetInverse(ref xmView);
                xmView.VectorProduct(bView, ref tView, 1, 0);
            }

            //絶対湿度をゾーンに設定
            for (uint i = 0; i < zones.Length; i++) zones[i].setHumidityRatio(tzVector.GetValue(arbPerm[i]));

            if (0 < ccZones)
            {
                //絶対湿度指定ゾーンの熱負荷を計算
                //ゾーン絶対湿度に依存する成分
                //mView.Initialize(bMatrix, ffZones, 0, ccZones, (uint)zones.Length);
                //tView.Initialize(tzVector, 0, tzVector.Size);
                //bView.Initialize(bbVector, ffZones, ccZones);

                mView = new Matrix(ccZones, (uint)zones.Length, ffZones, 0, bMatrix);
                tView = new Vector(tzVector.Size, 0, tzVector);
                bView = new Vector(ccZones, ffZones, bbVector);

                //Blas.DGemv(Blas.TransposeType.NoTranspose, 1, mView, tView, 0, ref bView);
                mView.VectorProduct(tView, ref bView, 1, 0);

                //
                for (uint i = 0; i < zones.Length; i++)
                {
                    if (zones[i].ControlHumidityRatio)
                    {
                        zones[i].CurrentLatentHeatLoad = - MoistAir.LatentHeatOfVaporization * 1000
                            * (bbVector.GetValue(arbPerm[i]) - bVector.GetValue(arbPerm[i]));
                    }
                }
            }
        }
Beispiel #16
0
        /// <summary>初期化処理</summary>
        public void Initialize()
        {
            sfNumber = new uint[rooms.Length];
            znNumber = new uint[rooms.Length];

            //壁表面とゾーンの数を積算
            uint sfSum = 0;
            uint sfZnSum = 0;
            uint znSum = 0;
            List<ISurface> sfs = new List<ISurface>();
            List<Zone> zns = new List<Zone>();
            for (int i = 0; i < rooms.Length; i++)
            {
                //AX行列におけるRoom要素の開始列数
                if(axRmIndices.ContainsKey(rooms[i])) axRmIndices[rooms[i]] = sfSum;
                else axRmIndices.Add(rooms[i], sfSum);

                //壁表面数
                sfNumber[i] = rooms[i].SurfaceNumber;
                sfSum += rooms[i].SurfaceNumber;

                //ゾーン数
                znNumber[i] = rooms[i].ZoneNumber;
                znSum += rooms[i].ZoneNumber;
                zns.AddRange(rooms[i].getZone());
                for (uint j = 0; j < rooms[i].ZoneNumber; j++)
                {
                    Zone zn = rooms[i].getZone(j);

                    if (znToRm.ContainsKey(zn)) znToRm[zn] = rooms[i];
                    else znToRm.Add(zn, rooms[i]);

                    //AX行列におけるZone要素の開始列数
                    if (axZnIndices.ContainsKey(zn)) axZnIndices[zn] = sfZnSum;
                    else axZnIndices.Add(zn, sfZnSum);
                    sfZnSum += (uint)zn.Surfaces.Length;
                }

                //壁表面リスト
                sfs.AddRange(rooms[i].getSurface());
                for (uint j = 0; j < rooms[i].SurfaceNumber; j++)
                {
                    if (sfToRm.ContainsKey(rooms[i].getSurface(j))) sfToRm[rooms[i].getSurface(j)] = rooms[i];
                    else sfToRm.Add(rooms[i].getSurface(j), rooms[i]);
                }
            }
            surfaces = sfs.ToArray();
            zones = zns.ToArray();

            //行列・ベクトルのメモリ領域を用意
            tzVector = new Vector(znSum);
            arbPerm = new uint[znSum];
            arMatrix = new double[znSum, znSum];
            bMatrix = new Matrix(znSum, znSum);
            xa = new Matrix(sfSum, sfSum);
            phi = new Matrix(sfSum, sfSum);
            surfaceTemperatures = new Vector(sfSum);
            surfaceMRTs = new Vector(sfSum);
            crxVector = new Vector(sfSum);
            craVector = new Vector(sfSum);
            caVector = new double[znSum];
            bMatrix = new Matrix(znSum, znSum);
            xbMatrix = new Matrix(znSum, znSum);
            bVector = new Vector(znSum);
            bbVector = new Vector(znSum);
            for (int i = 0; i < rooms.Length; i++)
            {
                for (uint j = 0; j < rooms[i].ZoneNumber; j++)
                {
                    if(! rxVector.ContainsKey(rooms[i].getZone(j))) rxVector.Add(rooms[i].getZone(j), new Vector(sfSum));
                    if (!raVector.ContainsKey(rooms[i].getZone(j))) raVector.Add(rooms[i].getZone(j), new Vector(sfSum));
                }
            }
            for (int i = 0; i < zones.Length; i++)
            {
                if (!airFlowToZone.ContainsKey(zones[i])) airFlowToZone.Add(zones[i], new Dictionary<ImmutableZone, double>());
            }

            //表面温度計算式の逆行列を計算する
            makeXAMatrix();

            //壁および窓構成変更イベントへの対応
            foreach (ISurface sf in surfaces)
            {
                sf.FIOChangeEvent += new EventHandler(sf_FIOChangeEvent);
            }
        }