public void UnwrapsChannelFlowMethodFrame() { var message = new ChannelFlow( active: Random.Bool() ); _context.Send(_subject, (Inbound, RawFrame.Wrap(_channelNumber, message))); if (_messageReceivedSignal.Wait(timeout: TimeSpan.FromMilliseconds(100))) { var unwrappedMessage = _unwrappedMessage as ChannelFlow; Assert.Equal(expected: message.Active, actual: unwrappedMessage.Active); } else { // No `ChannelFlow` command was received within 100 millis... throw new TimeoutException("Timeout occurred before command was received"); } }
/// <summary> /// 计算稳态子通道流量场,使用节点压力迭代,即用压力平衡思想考虑横向流动 /// </summary> /// <param name="coolent">冷却剂</param> /// <param name="channels">通道集合</param> /// <param name="rods">燃料棒集合</param> /// <param name="massFlow">质量流速对象</param> /// <param name="Ni">通道数</param> /// <param name="Nj">轴向分段数</param> /// <param name="totalArea">总流通面积</param> /// <param name="options">计算选项</param> /// <returns></returns> public List <ChannelFlow> Caculate_Channels_Steady_NodeIteration( Fluid coolent, List <Channel> channels, List <Rod> rods, MassFlow massFlow, int Ni, int Nj, double totalArea, Options options) { ///使用压力迭代方法确定不同子通道之间的流量,此计算方法使用压力迭代确定 /// Main.MsgCenter.ShowMessage("计算子通道数据,流量计算方式压力迭代:节点迭代..."); //初始化输出结果 List <ChannelFlow> channelsFlow = new List <ChannelFlow>(); for (int i = 0; i < Ni; i++) { ChannelFlow channelFlow = new ChannelFlow { //流动计算结果 编号与输入的子通道编号相对应 ChannelIndex = channels[i].Index, FluidDatas = new List <FluidData>() }; for (int j = 0; j < Nj + 1; j++) { channelFlow.FluidDatas.Add(new FluidData()); } channelsFlow.Add(channelFlow); } //迭代的限制参数 Iteration iteration = options.Iteration; //功率的乘子 PowerFactor powerFactor = options.PowerFactor; //计算的准确度 Precision acc = options.Precision; //CHF公式选取 CHF_Formula_Types chf_formula = options.DNBR_Formula; //流动方向(-1~1) double flow_direction = massFlow.Flow_Direction; //质量流量迭代 var MassFlowRate = Matrix <double> .Build.Dense(Nj + 1, Ni, 0); //每个子通道的分段压降,Ni行xNj列初值为0 var P_Local = Matrix <double> .Build.Dense(Nj + 1, Ni, 0); //压降迭代因子 double Sigma = 0; //质量流速迭代中间变量 double[] m = new double[Ni]; //质量流速迭代中间变量 double[] velocity = new double[Ni]; //质量流速迭代中间变量 double[] DeltaP = new double[Nj]; //遍历所有子通道 for (int i = 0; i < Ni; i++) { //初始化j=0入口节点 FluidData InitNode = SetInitNode(coolent, totalArea, channels[i], massFlow, acc); //初始化子通道数据节点加入 channelsFlow[i].FluidDatas[0] = InitNode; //局部压力场矩阵(Mpa) P_Local[0, i] = InitNode.Pressure; //质量流速kg/s 迭代用) m[i] = InitNode.MassFlowRate; //流速m/s(迭代用) velocity[i] = InitNode.Velocity; //质量流速矩阵(输出用) MassFlowRate[0, i] = m[i]; } //轴向迭代 for (int j = 1; j < Nj + 1; j++) { //迭代次数 int iteration_times = 0; do { //计算所有燃料棒j段(J=1~Nj-1) for (int i = 0; i < Ni; i++) { //计算当前段的长度j>=1 double Lj = rods[0].SubPowerCollection[j - 1].To - rods[0].SubPowerCollection[j - 1].From; //前一个节点 FluidData pre = channelsFlow[i].FluidDatas[j - 1]; //当前子通道燃料棒功率输出 double SubPowerJ = 0; //遍历所有燃料棒 foreach (Rod rod in rods) { //燃料棒所有接触的通道 foreach (var ContactedChannel in rod.ContactedChannel) { //如果与燃料棒接触的通道,如果是当前正在计算的通道 if (ContactedChannel.Index == channels[i].Index) { SubPowerJ += rod.SubPowerCollection[j - 1].Value * ContactedChannel.Angle / 360; } } } //乘以功率因子 SubPowerJ = SubPowerJ * powerFactor.Multiplier; //计算新节点,NodeToNext计算子通道节点 FluidData next = NodeToNext( coolent, pre, channels[i], Lj, SubPowerJ, m[i], acc, out double DeltaPij, chf_formula, flow_direction); //迭代中间变量赋值 DeltaP[i] = DeltaPij; //存储计算结果 channelsFlow[i].FluidDatas[j] = next; //i棒j段压降 P_Local[j, i] = next.Pressure; //质量流速 MassFlowRate[j, i] = m[i]; } //初始化迭代收敛因子 Sigma = 0; //平均压降 double AvgPressure = 0; for (int i = 0; i < Ni; i++) { AvgPressure += DeltaP[i]; } //平均压降 AvgPressure = AvgPressure / Ni; // 所有偏差之和 for (int i = 0; i < Ni; i++) { Sigma += Math.Abs(DeltaP[i] - AvgPressure); } //总质量流速 double TotalM = 0; for (int i = 0; i < Ni; i++) { //子通道i压降和平均压降的比值 double Factor = (1 - DeltaP[i] / AvgPressure) * 0.1; //重新分配压降 m[i] = m[i] + m[i] * Factor; TotalM += m[i]; Debug.WriteLine(String.Format("因子{0}:", Factor)); } //计算平衡后与平衡前的比值 double k = massFlow.MassVelocity / TotalM; //保持总质量流速不变 for (int i = 0; i < Ni; i++) { //对质量流量进行修正 m[i] = k * m[i]; Debug.WriteLine(String.Format("通道{0}压降{1}Pa", i, DeltaP[i])); } Debug.WriteLine("========================================="); //迭代压降 iteration_times += 1; Main.MsgCenter.ShowMessage(String.Format("压力迭代次数:{0}", iteration_times)); if (iteration_times > iteration.MaxIteration) { Main.MsgCenter.ShowMessage(String.Format("超过最大迭代次数限制,最大迭代次数限制{0}", iteration.MaxIteration)); break; } }while (Sigma > iteration.Sigma); //循环每个通道 Main.MsgCenter.ShowMessage(String.Format("Sigma->{0}", Sigma)); } //信息输出 Main.MsgCenter.ShowMessage("--------压力场预览--------"); Main.MsgCenter.ShowMessage(P_Local.ToMatrixString(Nj + 1, Ni)); Main.MsgCenter.ShowMessage("--------流量场预览--------"); Main.MsgCenter.ShowMessage(MassFlowRate.ToMatrixString(Nj + 1, Ni)); return(channelsFlow); }
/// <summary> /// 计算燃料棒稳态温度场 /// </summary> /// <param name="Nj">轴向分段数</param> /// <param name="Nk">燃料棒数</param> /// <param name="coolent">冷却剂</param> /// <param name="channels">通道结合</param> /// <param name="rods">燃料棒集合</param> /// <param name="rodTypes">燃料棒类型集合</param> /// <param name="materials">材料集合</param> /// <param name="channelsFlow">已经得到的子通道稳态流体计算结果</param> /// <param name="gasGap">气体间隙模型对象</param> /// <param name="options">计算选项集合</param> /// <returns></returns> public List <RodTemperature> Caculate_Rods_Temperature_Steady( int Nj, int Nk, Fluid coolent, List <Channel> channels, List <Rod> rods, List <RodType> rodTypes, List <Material> materials, List <ChannelFlow> channelsFlow, GasGap gasGap, Options options) { Main.MsgCenter.ShowMessage("--------计算燃料棒温度场--------"); //燃料棒温度集合 返回数据 List <RodTemperature> RodsTemperature = new List <RodTemperature>(); //包壳分段数 var CladSegment = options.CladSegment; //芯块分段数 var PelletSegment = options.PelletSegment; //功率因子 var powerFactor = options.PowerFactor.Multiplier; //包壳功率份额 var cladShare = options.PowerFactor.CladShare; //芯块功率份额 var pelletShare = options.PowerFactor.PelletShare; //冷却剂中功率份额 var fluidShare = options.PowerFactor.FluidShare; //计算结果准确度设置 var acc = options.Precision; //燃料棒周围主流流体温度 Matrix <double> Tf = Matrix <double> .Build.Dense(Nj, Nk, 0); //燃料棒周围主流流体对流换热系数 Matrix <double> h = Matrix <double> .Build.Dense(Nj, Nk, 0); Matrix <double> massFlowDensity = Matrix <double> .Build.Dense(Nj, Nk, 0); //遍历所有燃料棒 for (int k = 0; k < Nk; k++) { //新建一个用于存储一个燃料棒输出的对象 RodTemperature RodkTemperature = new RodTemperature { Index = rods[k].Index, SubRods = new List <SubRodTemperature>(), }; //径向温度节点数 int size = CladSegment + PelletSegment + 2; //燃料棒k的温度场 矩阵 Matrix <double> RodTField = Matrix <double> .Build.Dense(Nj, size, 0); //是否找到燃料类型 bool isTypeFound = false; RodType rodType = new RodType(); //找到燃料棒k的燃料棒类型 foreach (RodType type in rodTypes) { if (type.Index == rods[k].Type) { rodType = type; //找到了燃料棒类型 isTypeFound = true; break; } } //如果未找到燃料棒类型 if (!isTypeFound) { Main.MsgCenter.ShowMessage(String.Format("燃料棒{0}未找到匹配的{1}燃料棒类型", k, rods[k].Type)); } //寻找燃料棒固体材料数据 Material Clad = new Material(); Material Pellet = new Material(); foreach (var material in materials) { if (material.Index == rodType.CladMaterialIndex) { Clad = material; } else if (material.Index == rodType.PelletMaterialIndex) { Pellet = material; } } //燃料棒直径 double d_rod = rodType.Diameter; //燃料芯块直径 double d_pellet = rodType.PelletDiameter; //燃料包壳厚度 double clad_thickness = rodType.CladThickness; //气体间隙通过计算得出 double gap_thickness = (d_rod - d_pellet) * 0.5 - clad_thickness; //分段计算燃料棒温度场 for (int j = 0; j < Nj; j++) { //分段长度 double Lj = rods[0].SubPowerCollection[j].To - rods[0].SubPowerCollection[j].From; //接触的全部角度 double TotalAngle = 0; double Xe = 0; FluidData FluidJ; //遍历与[燃料棒k] 接触的 子通道,找到流体外部边界条件 foreach (ContactedChannel EachContactedChannel in rods[k].ContactedChannel) { //与燃料棒k接触的所有子通道流体物性参数计算结果 ChannelFlow ChannelFlowOfContactChannel = new ChannelFlow(); //找到与燃料棒接触的子通道计算结果 foreach (ChannelFlow channelFlow in channelsFlow) { //通道数据 index和连接的通道 index相同 if (channelFlow.ChannelIndex == EachContactedChannel.Index) { ChannelFlowOfContactChannel = channelFlow; } } FluidJ = ChannelFlowOfContactChannel.FluidDatas[j]; h[j, k] += FluidJ.h * EachContactedChannel.Angle; Tf[j, k] += FluidJ.Temperature * EachContactedChannel.Angle; Xe = FluidJ.Xe * EachContactedChannel.Angle; //质量流密度 massFlowDensity[j, k] += FluidJ.Velocity * FluidJ.Density * EachContactedChannel.Angle; //累加接触的角度份额 TotalAngle += EachContactedChannel.Angle; } //加权平均对流换热系数 h[j, k] = h[j, k] / TotalAngle; //加权平均流体温度 Tf[j, k] = Tf[j, k] / TotalAngle; //加权平均热平衡含气率 Xe = Xe / TotalAngle; //加权平均质量流密度 massFlowDensity[j, k] = massFlowDensity[j, k] / TotalAngle; //线性功率,单位W/M double Linearpower = rods[k].SubPowerCollection[j].Value * powerFactor; //体热源W/m3 double fi_pellet = Linearpower * pelletShare / (0.25 * PI * d_pellet * d_pellet); //clad面积 double cladArea = 0.25 * PI * (d_rod * d_rod - (d_rod - 2 * clad_thickness) * (d_rod - 2 * clad_thickness)); //包壳 体热流密度 double fi_clad = Linearpower * cladShare / cladArea; //包壳分段长度 double deltaR_clad = clad_thickness / CladSegment; //芯块分段长度 double deltaR_pellet = d_pellet * 0.5 / PelletSegment; //包壳外表面 - 热流密度 double q = Linearpower * (1 - fluidShare) / (PI * d_rod); //包壳外表面 - 温度 double Tw = q / h[j, k] + Tf[j, k]; //内推温度场 RodTField[j, 0] = Tw; //稳态,温度场由外向内内推 for (int layer = 0; layer < CladSegment; layer++) { //外径 double r_outside = 0.5 * d_rod - deltaR_clad * layer; //内径 double r_inside = 0.5 * d_rod - deltaR_clad * (layer + 1); //层平均半径 double r_av = (r_inside + r_outside) * 0.5; //已经内推过的层面积 double layerArea = PI * (d_rod * d_rod * 0.25 - r_inside * r_inside); //内推过的层发热线功率 double layerHeat = layerArea * fi_clad; //层导热热阻ln(d2/d1)/2π lamd l Clad.K.Get(vectorT[layer]) double R_layer = Math.Log(r_outside / r_inside) / (2 * PI * Clad.GetK(RodTField[j, layer]) * Lj); //内推节点 RodTField[j, layer + 1] = (Linearpower - layerHeat) * Lj * R_layer + RodTField[j, layer]; } //稳态下气体间隙传递的热流密度(导出热量等于芯块Pellet产热) double q_gap = Linearpower * pelletShare / (PI * d_pellet); //芯块外表面温度 RodTField[j, CladSegment + 1] = RodTField[j, CladSegment] + q_gap / gasGap.Get_h(); //计算燃料棒 for (int layer = 0; layer < PelletSegment; layer++) { //外径 double r_outside = 0.5 * d_pellet - deltaR_pellet * layer; //内径 double r_inside = 0.5 * d_pellet - deltaR_pellet * (layer + 1); //层平均半径 double r_av = (r_inside + r_outside) * 0.5; //已经内推过的层面积 double layerArea = PI * (0.25 * d_pellet * d_pellet - r_inside * r_inside); //层发热线功率 double layerHeat = layerArea * fi_pellet; //层导热热阻ln(d2/d1)/2π*lamd*l Clad.K.Get(vectorT[layer]) double R_layer = Math.Log(r_outside / r_inside) / (2 * PI * Clad.GetK(RodTField[j, layer]) * Lj); RodTField[j, layer + CladSegment + 2] = (Linearpower * pelletShare - layerHeat) * Lj * R_layer + RodTField[j, layer + CladSegment + 1]; } //芯块中心温度(根据有内热源传热方程) RodTField[j, PelletSegment + CladSegment + 1] = RodTField[j, PelletSegment + CladSegment] + 0.25 * fi_pellet / Pellet.GetK(RodTField[j, PelletSegment + CladSegment]) * deltaR_pellet * deltaR_pellet; //计算临界热流密度 double q_critical = Q_Critical(Xe, d_rod, massFlowDensity[j, k], coolent.GetHf(Tf[j, k]), coolent.GetH(Tf[j, k]), options.DNBR_Formula); //设置输出对象(燃料棒k第j段) SubRodTemperature subRodTemperature = new SubRodTemperature { Index = j, //一些重要观测点温度 CladOutsideT = Math.Round(RodTField[j, 0], acc.T), CladInsideT = Math.Round(RodTField[j, CladSegment], acc.T), PelletOutsideT = Math.Round(RodTField[j, CladSegment + 1], acc.T), PelletCenterT = Math.Round(RodTField[j, PelletSegment + CladSegment + 1], acc.T), //对流换热系数 h = Math.Round(h[j, k], acc.h), //热流密度 Q = Math.Round(q, 1), //临界热流密度 Qc = Math.Round(q_critical, 1), //DNBR DNBR = Math.Round(q_critical / q, 3), //温度向量 TemperatureVector = RodTField.Row(j), }; //加入计算结果集合 RodkTemperature.SubRods.Add(subRodTemperature); }//---结束轴向J循环 RodsTemperature.Add(RodkTemperature); //输出消息提示 Main.MsgCenter.ShowMessage(String.Format("燃料棒{0}:", rods[k].Index)); Main.MsgCenter.ShowMessage(RodTField.ToMatrixString(Nj, PelletSegment + CladSegment + 2)); }//结束燃料棒k循环 return(RodsTemperature); }
/// <summary> /// 计算稳态子通道流量场,使用进出口压力迭代,即不考虑横向流动 /// </summary> /// <param name="coolent">冷却剂</param> /// <param name="channels">通道集合</param> /// <param name="rods">燃料棒集合</param> /// <param name="massFlow">质量流速对象</param> /// <param name="Ni">通道数</param> /// <param name="Nj">轴向分段数</param> /// <param name="totalArea">总流通面积</param> /// <param name="options">计算选项</param> /// <returns></returns> public List <ChannelFlow> Caculate_Channels_Steady_IOIteration( Fluid coolent, List <Channel> channels, List <Rod> rods, MassFlow massFlow, int Ni, int Nj, double totalArea, Options options) { ///使用压力迭代方法确定稳态不同子通道之间的流量,此计算方法使用压力迭代确定 ///一些局部变量 /// //初始化输出结果 List <ChannelFlow> channelsFlow = new List <ChannelFlow>(); for (int i = 0; i < Ni; i++) { ChannelFlow channelFlow = new ChannelFlow { //流动计算结果 编号与输入的子通道编号相对应 ChannelIndex = channels[i].Index, FluidDatas = new List <FluidData>() }; for (int j = 0; j < Nj + 1; j++) { channelFlow.FluidDatas.Add(new FluidData()); } channelsFlow.Add(channelFlow); } //迭代的限制参数 Iteration iteration = options.Iteration; //功率的乘子 PowerFactor powerFactor = options.PowerFactor; //计算的准确度 Precision acc = options.Precision; //CHF公式选取 CHF_Formula_Types chf_formula = options.DNBR_Formula; //流动方向(-1~1) double flow_direction = massFlow.Flow_Direction; //压降迭代,每个子通道的压降 double[] DeltaP = new double[Ni]; //压降迭代,每个子通道的压降 double[] m = new double[Ni]; //每个子通道的分段压降,Ni行xNj列初值为0 Matrix <double> P_Local = Matrix <double> .Build.Dense(Nj + 1, Ni, 0); //压降迭代收敛因子 double Sigma = 0; //迭代次数统计 int iteration_times = 0; //迭代压降 do { //遍历子通道 for (int i = 0; i < Ni; i++) { //初始化压降 DeltaP[i] = 0; //初始化子通道入口数据节点 FluidData InitNode = SetInitNode(coolent, totalArea, channels[i], massFlow, acc); //初始化子通道数据节点加入 channelsFlow[i].FluidDatas[0] = InitNode; //局部压力场矩阵 P_Local[0, i] = InitNode.Pressure; if (iteration_times <= 1) { //质量流速 m[i] = InitNode.MassFlowRate; } //每个通道数据节点(共Nj+1个,初始节点1个,循环Nj个) for (int j = 1; j < Nj + 1; j++) { //计算当前段的长度j>=1 double Lj = rods[0].SubPowerCollection[j - 1].To - rods[0].SubPowerCollection[j - 1].From; //前一个节点 FluidData pre = channelsFlow[i].FluidDatas[j - 1]; //当前子通道燃料棒功率输出 double SubPowerJ = 0; //遍历所有燃料棒 foreach (Rod rod in rods) { //燃料棒所有接触的通道 foreach (var ContactedChannel in rod.ContactedChannel) { //如果与燃料棒接触的通道,如果是当前正在计算的通道 if (ContactedChannel.Index == channels[i].Index) { SubPowerJ += rod.SubPowerCollection[j - 1].Value * ContactedChannel.Angle / 360; } } } //乘以功率因子 SubPowerJ = SubPowerJ * powerFactor.Multiplier; //计算新节点,NodeToNext计算子通道节点 FluidData next = NodeToNext( coolent, pre, channels[i], Lj, SubPowerJ, m[i], acc, out double DeltaPij, chf_formula, flow_direction); //存储计算结果 channelsFlow[i].FluidDatas[j] = next; //i棒j段压降 P_Local[j, i] = next.Pressure; //压降用于迭代 DeltaP[i] += DeltaPij; } } //初始化迭代收敛因子Sigma Sigma = 0; //平均压降 double AvgPressure = 0; for (int i = 0; i < Ni; i++) { #if DEBUG Main.MsgCenter.ShowMessage(String.Format("通道{0}压降:{1}", i, DeltaP[i])); #endif AvgPressure += DeltaP[i]; } //平均压降 AvgPressure = AvgPressure / Ni; //所有偏差之和 for (int i = 0; i < Ni; i++) { Sigma += Math.Abs(DeltaP[i] - AvgPressure); } double TotalM = 0; for (int i = 0; i < Ni; i++) { //子通道i压降和平均压降的比值 double Factor = Math.Sqrt(AvgPressure / DeltaP[i]); //重新分配压降 m[i] = Factor * m[i]; // 所有偏差之和 //计算平衡后的总质量流速 TotalM += m[i]; } //计算平衡后与平衡前的比值 double k = massFlow.MassVelocity / TotalM; //对质量流量进行修正,保持总质量流速不变 for (int i = 0; i < Ni; i++) { m[i] = k * m[i]; #if DEBUG Main.MsgCenter.ShowMessage(String.Format("通道{0}质量流速:{1}", i, m[i])); #endif } //输出迭代收敛因子 Main.MsgCenter.ShowMessage(String.Format("Sigma->{0}", Sigma)); //迭代次数+1 iteration_times += 1; Main.MsgCenter.ShowMessage(String.Format("压力迭代次数:{0}", iteration_times)); if (iteration_times > iteration.MaxIteration) { Main.MsgCenter.ShowMessage(String.Format("超过最大迭代次数限制,最大迭代次数限制{0}", iteration.MaxIteration)); break; } }while (Sigma > iteration.Sigma); // MyIOManager.OutputData.SteadyResult.ChannelsFlow = ChannelsFlow; //信息输出 Main.MsgCenter.ShowMessage("--------压力场预览--------"); Main.MsgCenter.ShowMessage(P_Local.ToMatrixString(Nj + 1, Ni)); Main.MsgCenter.ShowMessage("--------流量场预览--------"); var MassFlowRate = Matrix <double> .Build.Dense(Nj + 1, Ni, (Mi, Mj) => m[Mj]); Main.MsgCenter.ShowMessage(MassFlowRate.ToMatrixString(Nj + 1, Ni)); return(channelsFlow); }