/// <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)); } } }
/// <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)); } }
/// <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]); } } }
/// <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); } }