Sic.Framework-Nanjing-Baishi/MECF.Framework.UI.Client/RecipeEditorLib/RecipeModel/RecipeStep.cs

896 lines
40 KiB
C#
Raw Normal View History

2023-04-13 11:51:03 +08:00
using System;
using System.Collections.Generic;
2023-04-13 11:51:03 +08:00
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using MECF.Framework.Common.DataCenter;
using MECF.Framework.UI.Client.RecipeEditorLib.RecipeModel.Params;
2023-04-13 11:51:03 +08:00
namespace MECF.Framework.UI.Client.RecipeEditorLib.RecipeModel
2023-04-13 11:51:03 +08:00
{
public class RecipeStep : ObservableCollection<Param>
{
/// <summary>
/// 步骤起始编号。
/// </summary>
public const int START_INDEX = 1;
#region Variables
private bool _isHideValue;
private bool _isProcessed;
2023-04-13 11:51:03 +08:00
/// <summary>
/// 当配方步骤的IsSaved属性发生变化时触发此事件。
/// </summary>
public event EventHandler<bool> SavedStateChanged;
2023-04-13 11:51:03 +08:00
#endregion
#region Constructors
public RecipeStep(RecipeStep previous)
{
Previous = previous;
IsSaved = true;
}
#endregion
#region Properties
2023-04-13 11:51:03 +08:00
/// <summary>
/// 父级配方集合。
/// </summary>
public RecipeData Parent { get; internal set; }
2023-04-13 11:51:03 +08:00
/// <summary>
/// 返回配方步骤序号参数。
/// </summary>
public StepParam StepNoParam => this.FirstOrDefault(x => x is StepParam) as StepParam;
public StringParam UidParam => this.FirstOrDefault(param => param.DisplayName == "Uid") as StringParam;
/// <summary>
/// 当前配方步骤的唯一识别码。
/// </summary>
public string StepUid
{
get => UidParam?.Value ?? null;
set
{
var paramUid = UidParam;
if (paramUid != null)
{
paramUid.Value = value;
}
}
}
2023-04-13 11:51:03 +08:00
/// <summary>
/// 返回步骤序号。
/// </summary>
public int? StepNo
{
get
{
var param = StepNoParam;
return param?.Value ?? null;
}
}
/// <summary>
/// 返回步骤执行时长。
/// </summary>
public double? StepTime
{
get
{
var param = this.FirstOrDefault(x => x is DoubleParam && string.Equals(x.Name,
RecipColNo.StepTime.ToString(), StringComparison.CurrentCultureIgnoreCase)) as DoubleParam;
2023-04-13 11:51:03 +08:00
return param?.Value;
}
}
/// <summary>
/// 返回当前配方步骤是否已保存。
/// </summary>
public bool IsSaved { get; private set; }
/// <summary>
/// 返回当前步骤是否已经跑完工艺。
/// </summary>
public bool IsProcessed
{
get => _isProcessed;
set
{
if (_isProcessed != value)
{
_isProcessed = value;
OnPropertyChanged(new PropertyChangedEventArgs(nameof(IsProcessed)));
}
}
}
2023-04-13 11:51:03 +08:00
/// <summary>
/// 返回前序配方。
/// </summary>
public RecipeStep Previous { get; private set; }
/// <summary>
/// 返回后序配方。
/// </summary>
public RecipeStep Next { get; private set; }
2023-04-13 11:51:03 +08:00
/// <summary>
/// 返回是否隐藏当前步骤的参数值。
/// </summary>
public bool IsHideValue
{
get => _isHideValue;
set
{
_isHideValue = value;
this.ToList().ForEach(x => x.IsHideValue = value);
}
}
#endregion
#region Methods
/// <summary>
/// 当配方中的参数的属性发生变化时,触发此事件。
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void ParamOnPropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (!(sender is IParam param))
2023-04-13 11:51:03 +08:00
return;
if (e.PropertyName == nameof(Param.IsSaved))
{
if (param.IsSaved == false)
{
IsSaved = false;
}
else
{
IsSaved = this.ToList().FirstOrDefault(x => x.IsSaved == false) == null;
}
2023-04-13 11:51:03 +08:00
SavedStateChanged?.Invoke(this, IsSaved);
}
}
2023-04-13 11:51:03 +08:00
/// <summary>
/// 将指定的Param链接到前序Param。
/// </summary>
/// <param name="param">当前Step中的参数。</param>
private void LinkWithPreviousParam(IParam param)
{
var preParam = Previous?.FirstOrDefault(x => x.Name == param.Name);
param.Previous = preParam;
if (preParam != null)
preParam.Next = param;
}
2023-04-13 11:51:03 +08:00
/// <summary>
/// 将指定的Param链接到后序Param。
/// </summary>
/// <param name="param">当前Step中的参数。</param>
private void LinkWithNextParam(IParam param)
{
var nextParam = Next?.FirstOrDefault(x => x.Name == param.Name);
param.Next = nextParam;
if (nextParam != null)
nextParam.Previous = param;
}
/// <summary>
/// 在当前步骤中查找指定控制名的参数。
/// </summary>
/// <param name="controlName">
/// 参数控制的名称。
/// </param>
/// <param name="isIgnoreCase">
/// 是否区分大小写。
/// </param>
/// <returns></returns>
public IParam FindParamByControlName(string controlName, bool isIgnoreCase = true)
{
return this.FirstOrDefault(x =>
string.Equals(x.Name, controlName,
isIgnoreCase ? StringComparison.CurrentCultureIgnoreCase : StringComparison.CurrentCulture));
}
2023-04-13 11:51:03 +08:00
/// <summary>
/// 校验步骤中的所有参数。
/// </summary>
public void Validate()
{
this.ToList().ForEach(x => x.Validate());
2023-04-13 11:51:03 +08:00
}
/// <summary>
/// 取消所有参数的Highlight状态。
/// </summary>
public void ResetHighlight()
{
this.ToList().ForEach(x => x.ResetHighlight());
}
/// <summary>
/// 获取高亮显示的参数。
/// </summary>
/// <returns></returns>
public List<Param> GetHighlightedParams()
{
return this.ToList().Where(p => p.IsHighlighted).ToList();
}
2023-04-13 11:51:03 +08:00
/// <summary>
/// 保存当前配方步骤。
/// </summary>
public void Save()
{
this.ToList().ForEach(x => x.Save());
2023-04-13 11:51:03 +08:00
}
/// <summary>
/// 設置前序步驟。
/// </summary>
/// <param name="step"></param>
public void SetPreviousStep(RecipeStep step)
{
Previous = step;
2023-04-13 11:51:03 +08:00
// 调整Step中Param的链接关系
this.ToList().ForEach(LinkWithPreviousParam);
if (Previous == null)
return;
// 将前序步骤的后序步骤链接到我自己。
Previous.Next = this;
}
public void SetNextStep(RecipeStep step)
{
Next = step;
this.ToList().ForEach(LinkWithNextParam);
}
/// <summary>
/// 检查StepNo是否为有效值。
/// </summary>
/// <param name="stepNo"></param>
/// <param name="validatedStepNo"></param>
/// <returns></returns>
public static bool ValidateStepNo(int? stepNo, out int validatedStepNo)
{
validatedStepNo = int.MinValue;
var isValid = stepNo >= START_INDEX;
2023-04-13 11:51:03 +08:00
if (isValid)
validatedStepNo = stepNo.Value;
return isValid;
}
#endregion
#region Gas Flow Calculation
private static double GetTcsFlow(RecipeStep currentStep, string selectedChamber)
{
var currentTcsBubbleLowFlow = ((DoubleParam)currentStep[(int)RecipColNo.TCSBubbLowFlow]).Value;
var currentTcsBubbleHighFlow = ((DoubleParam)currentStep[(int)RecipColNo.TCSBubbHighFlow]).Value;
var currentTcsPushFlow = ((DoubleParam)currentStep[(int)RecipColNo.TCSPushFlow]).Value;
var currentTcsFlowMode = (currentStep[(int)RecipColNo.TCSFlowMode] as ComboxParam)?.Value;
var tcsFlow = 0d;
var tcsEff =
(double)QueryDataClient.Instance.Service.GetConfig($"PM.{selectedChamber}.Efficiency.TCS-Eff");
if (string.Equals(currentTcsFlowMode, FlowModeParam.FlowModeEnum.Run.ToString(),
StringComparison.OrdinalIgnoreCase)
|| string.Equals(currentTcsFlowMode, FlowModeParam.FlowModeEnum.Vent.ToString(),
StringComparison.OrdinalIgnoreCase))
{
tcsFlow = (currentTcsBubbleHighFlow + currentTcsBubbleLowFlow) * tcsEff + currentTcsPushFlow;
}
else if (string.Equals(currentTcsFlowMode, FlowModeParam.FlowModeEnum.Purge.ToString(),
StringComparison.OrdinalIgnoreCase))
{
tcsFlow = currentTcsBubbleHighFlow + currentTcsBubbleLowFlow + currentTcsPushFlow;
}
return tcsFlow;
}
private static double GetTmaFlow(RecipeStep currentStep, string selectedChamber)
{
var currentTmaBubbleFlow = ((DoubleParam)currentStep[(int)RecipColNo.TMABubbFlow]).Value;
var currentTmaPushFlow = ((DoubleParam)currentStep[(int)RecipColNo.TMAPushFlow]).Value;
var currentTmaFlowMode = ((ComboxParam)currentStep[(int)RecipColNo.TMAFlowMode]).Value;
var tmaFlow = 0d;
var tmaEff =
(double)QueryDataClient.Instance.Service.GetConfig($"PM.{selectedChamber}.Efficiency.TMA-Eff");
if (string.Equals(currentTmaFlowMode, FlowModeParam.FlowModeEnum.Run.ToString(),
StringComparison.OrdinalIgnoreCase)
|| string.Equals(currentTmaFlowMode, FlowModeParam.FlowModeEnum.Vent.ToString(),
StringComparison.OrdinalIgnoreCase))
tmaFlow = currentTmaBubbleFlow * tmaEff + currentTmaPushFlow;
else if (string.Equals(currentTmaFlowMode, FlowModeParam.FlowModeEnum.Purge.ToString(),
StringComparison.OrdinalIgnoreCase))
tmaFlow = currentTmaBubbleFlow + currentTmaPushFlow;
return tmaFlow;
}
private static void CalSiSourceFlow(RecipeStep currentStep)
{
var currentSiSourSplitRatio = new double[3];
if (currentStep[(int)RecipColNo.SiSourceSplitRatio] is Sets3RatioParam siSourceRatio)
currentSiSourSplitRatio = siSourceRatio.Ratio;
var currentSiSourTotalFlow = ((DoubleParam)currentStep[(int)RecipColNo.SiSourceTotalFlow]).Value;
//double currentSiSourPushFlow = currentSiSourTotalFlow - (currentSiH4FlowMode == FlowMode.Run.ToString() ? currentSiH4Flow : 0)
// - (currentTCSFlowMode == FlowMode.Run.ToString() ? TCSFlow : 0) - (currentHClFlowMode == FlowMode.Run.ToString() ? currentHClFlow : 0);
//(currentStep[(int)RecipColNo.SiSourceOuterFlow] as DoubleParam).Value = currentSiSourPushFlow.ToString("F1");
double currentSiSourInnerFlow = 0;
double currentSiSourMidFlow = 0;
double currentSiSourOutFlow = 0;
if (currentSiSourSplitRatio.Length == 3)
{
var rationSum = currentSiSourSplitRatio[0] + currentSiSourSplitRatio[1] + currentSiSourSplitRatio[2];
currentSiSourInnerFlow = currentSiSourTotalFlow / rationSum * currentSiSourSplitRatio[0];
currentSiSourMidFlow = currentSiSourTotalFlow / rationSum * currentSiSourSplitRatio[1];
currentSiSourOutFlow = currentSiSourTotalFlow / rationSum * currentSiSourSplitRatio[2];
}
((DoubleParam)currentStep[(int)RecipColNo.SiSourceInnerFlow]).Value = Math.Round(currentSiSourInnerFlow, 1);
((DoubleParam)currentStep[(int)RecipColNo.SiSourceMiddleFlow]).Value = Math.Round(currentSiSourMidFlow, 1);
((DoubleParam)currentStep[(int)RecipColNo.SiSourceOuterFlow]).Value = Math.Round(currentSiSourOutFlow, 1);
}
private static void CalCSourceFlow(RecipeStep currentStep)
{
var currentC2H4Flow = ((DoubleParam)currentStep[(int)RecipColNo.C2H4Flow]).Value;
var currentCSourSplitRatio = new double[3];
if (currentStep[(int)RecipColNo.CSourceSplitRatio] is Sets3RatioParam cSourceRatio)
currentCSourSplitRatio = cSourceRatio.Ratio;
var currentCSourTotalFlow = ((DoubleParam)currentStep[(int)RecipColNo.CSourceTotalFlow]).Value;
var currentC2H4FlowMode = (currentStep[(int)RecipColNo.C2H4FlowMode] as ComboxParam)?.Value;
var currentCSourPushFlow = currentCSourTotalFlow -
(string.Equals(currentC2H4FlowMode, FlowModeParam.FlowModeEnum.Run.ToString(),
StringComparison.OrdinalIgnoreCase)
? currentC2H4Flow
: 0d);
((DoubleParam)currentStep[(int)RecipColNo.CSourceOuterFlow]).Value = Math.Round(currentCSourPushFlow, 1);
double currentCSourInnerFlow = 0;
double currentCSourMidFlow = 0;
double currentCSourOuterFlow = 0;
if (currentCSourSplitRatio.Length == 3)
{
var ratioSum = currentCSourSplitRatio[0] + currentCSourSplitRatio[1] + currentCSourSplitRatio[2];
currentCSourInnerFlow = currentCSourTotalFlow / ratioSum * currentCSourSplitRatio[0];
currentCSourMidFlow = currentCSourTotalFlow / ratioSum * currentCSourSplitRatio[1];
currentCSourOuterFlow = currentCSourTotalFlow / ratioSum * currentCSourSplitRatio[2];
}
((DoubleParam)currentStep[(int)RecipColNo.CSourceInnerFlow]).Value = Math.Round(currentCSourInnerFlow, 1);
((DoubleParam)currentStep[(int)RecipColNo.CSourceMiddleFlow]).Value = Math.Round(currentCSourMidFlow, 1);
((DoubleParam)currentStep[(int)RecipColNo.CSourceOuterFlow]).Value = Math.Round(currentCSourOuterFlow, 1);
}
private static void CalDopeFlow(RecipeStep currentStep)
{
var currentDopeTotalFlow = ((DoubleParam)currentStep[(int)RecipColNo.DopeTotalFlow]).Value;
var currentN2ActualFlow = ((DoubleParam)currentStep[(int)RecipColNo.N2ActualFlow]).Value;
var currentN2LowFlow = ((DoubleParam)currentStep[(int)RecipColNo.N2LowFlow]).Value;
var currentDiluFlowForN2 = ((DoubleParam)currentStep[(int)RecipColNo.DilutFlowForN2]).Value;
var currentDilutedN2Flow =
(currentN2LowFlow + currentDiluFlowForN2) * currentN2ActualFlow / currentN2LowFlow;
((DoubleParam)currentStep[(int)RecipColNo.DilutedN2Flow]).Value = Math.Round(currentDilutedN2Flow, 1);
var currentDopeSplitRatio = new double[3];
if (currentStep[(int)RecipColNo.DopeSplitRatio] is Sets3RatioParam dopRatio)
currentDopeSplitRatio = dopRatio.Ratio;
//double currentDopePushFlow = currentDopeTotalFlow
// - (currentN2FlowMode == FlowMode.Run.ToString() ? currentDilutedN2Flow : 0)
// - (currentN2HighFlowMode == FlowMode.Run.ToString() ? currentN2HighFlow : 0)
// - (currentTMAFlowMode == FlowMode.Run.ToString() ? TMAFlow : 0);
//(currentStep[(int)RecipColNo.DopeOuterFlow] as DoubleParam).Value = currentDopePushFlow.ToString("F1");
double currentDopeInnerFlow = 0;
double currentDopeMidFlow = 0;
double currentDopeOuterFlow = 0;
if (currentDopeSplitRatio.Length == 3)
{
var ratioSum = currentDopeSplitRatio[0] + currentDopeSplitRatio[1] + currentDopeSplitRatio[2];
currentDopeInnerFlow = currentDopeTotalFlow / ratioSum * currentDopeSplitRatio[0];
currentDopeMidFlow = currentDopeTotalFlow / ratioSum * currentDopeSplitRatio[1];
currentDopeOuterFlow = currentDopeTotalFlow / ratioSum * currentDopeSplitRatio[2];
}
((DoubleParam)currentStep[(int)RecipColNo.DopeInnerFlow]).Value = Math.Round(currentDopeInnerFlow, 1);
((DoubleParam)currentStep[(int)RecipColNo.DopeMiddleFlow]).Value = Math.Round(currentDopeMidFlow, 1);
((DoubleParam)currentStep[(int)RecipColNo.DopeOuterFlow]).Value = Math.Round(currentDopeOuterFlow, 1);
}
private static void CalShSupplementFlow(RecipeStep currentStep)
{
var currentSiSourTotalFlow = ((DoubleParam)currentStep[(int)RecipColNo.SiSourceTotalFlow]).Value;
var currentCSourTotalFlow = ((DoubleParam)currentStep[(int)RecipColNo.CSourceTotalFlow]).Value;
var currentDopeTotalFlow = ((DoubleParam)currentStep[(int)RecipColNo.DopeTotalFlow]).Value;
var currentShTotalFlow = ((DoubleParam)currentStep[(int)RecipColNo.SHTotalFlow]).Value;
var currentSurroundingFlow = ((DoubleParam)currentStep[(int)RecipColNo.CarrayGasFlow]).Value;
var currentSiSourInnerFlow = ((DoubleParam)currentStep[(int)RecipColNo.SiSourceInnerFlow]).Value;
var currentSiSourMidFlow = ((DoubleParam)currentStep[(int)RecipColNo.SiSourceMiddleFlow]).Value;
var currentCSourInnerFlow = ((DoubleParam)currentStep[(int)RecipColNo.CSourceInnerFlow]).Value;
var currentCSourMidFlow = ((DoubleParam)currentStep[(int)RecipColNo.CSourceMiddleFlow]).Value;
var currentDopeInnerFlow = ((DoubleParam)currentStep[(int)RecipColNo.DopeInnerFlow]).Value;
var currentDopeMidFlow = ((DoubleParam)currentStep[(int)RecipColNo.DopeMiddleFlow]).Value;
var currentShTotalFlowSplitRatio = new double[3];
if (currentStep[(int)RecipColNo.SHTotalFlowSplitRatio] is Sets3RatioParam shTotalRatio)
currentShTotalFlowSplitRatio = shTotalRatio.Ratio;
var currentShSuppTotalFlow = currentShTotalFlow - currentSurroundingFlow - currentSiSourTotalFlow -
currentCSourTotalFlow - currentDopeTotalFlow;
var sumShTotalFlowSplitRatio = currentShTotalFlowSplitRatio[0] + currentShTotalFlowSplitRatio[1] +
currentShTotalFlowSplitRatio[2];
var currentShInnerFlow = (currentShTotalFlow - currentSurroundingFlow) / sumShTotalFlowSplitRatio *
currentShTotalFlowSplitRatio[0];
var currentShMidFlow = (currentShTotalFlow - currentSurroundingFlow) / sumShTotalFlowSplitRatio *
currentShTotalFlowSplitRatio[1];
var currentShOutterFlow = (currentShTotalFlow - currentSurroundingFlow) / sumShTotalFlowSplitRatio *
currentShTotalFlowSplitRatio[2];
var currentInnerSuppFlow = currentShInnerFlow - currentSiSourInnerFlow - currentCSourInnerFlow -
currentDopeInnerFlow;
var currentMidSuppFlow = currentShMidFlow - currentSiSourMidFlow - currentCSourMidFlow - currentDopeMidFlow;
var currentOutterSuppFlow = currentShSuppTotalFlow - currentInnerSuppFlow - currentMidSuppFlow;
((DoubleParam)currentStep[(int)RecipColNo.SHPushTotalFlow]).Value = Math.Round(currentShSuppTotalFlow, 1);
((DoubleParam)currentStep[(int)RecipColNo.SHInnerFlow]).Value = Math.Round(currentShInnerFlow, 1);
((DoubleParam)currentStep[(int)RecipColNo.SHMiddleFlow]).Value = Math.Round(currentShMidFlow, 1);
((DoubleParam)currentStep[(int)RecipColNo.SHOuterFlow]).Value = Math.Round(currentShOutterFlow, 1);
((DoubleParam)currentStep[(int)RecipColNo.InnerPushFlow]).Value = Math.Round(currentInnerSuppFlow, 1);
((DoubleParam)currentStep[(int)RecipColNo.MiddlePushFlow]).Value = Math.Round(currentMidSuppFlow, 1);
((DoubleParam)currentStep[(int)RecipColNo.OuterPushFlow]).Value = Math.Round(currentOutterSuppFlow, 1);
}
private static void CalVentFlow(RecipeStep currentStep, string selectedChamber)
{
var currentSiH4Flow = ((DoubleParam)currentStep[(int)RecipColNo.SiH4Flow]).Value;
var currentTotalVentFlow = ((DoubleParam)currentStep[(int)RecipColNo.TotalVentFlow]).Value;
var currentHClFlow = ((DoubleParam)currentStep[(int)RecipColNo.HCLFlow]).Value;
var currentN2HighFlow = ((DoubleParam)currentStep[(int)RecipColNo.N2HighFlow]).Value;
var currentC2H4Flow = ((DoubleParam)currentStep[(int)RecipColNo.C2H4Flow]).Value;
var currentDilutedN2Flow = ((DoubleParam)currentStep[(int)RecipColNo.DilutedN2Flow]).Value;
var currentN2FlowMode = ((ComboxParam)currentStep[(int)RecipColNo.N2FlowMode]).Value;
var currentN2HighFlowMode = ((ComboxParam)currentStep[(int)RecipColNo.N2HighFlowMode]).Value;
var currentSiH4FlowMode = (currentStep[(int)RecipColNo.SiH4FlowMode] as ComboxParam)?.Value;
var currentTcsFlowMode = (currentStep[(int)RecipColNo.TCSFlowMode] as ComboxParam)?.Value;
var currentHClFlowMode = (currentStep[(int)RecipColNo.HCLFlowMode] as ComboxParam)?.Value;
var currentC2H4FlowMode = (currentStep[(int)RecipColNo.C2H4FlowMode] as ComboxParam)?.Value;
var currentTmaFlowMode = ((ComboxParam)currentStep[(int)RecipColNo.TMAFlowMode]).Value;
var tcsFlow = GetTcsFlow(currentStep, selectedChamber);
var tmaFlow = GetTmaFlow(currentStep, selectedChamber);
var currentSiSourTotalFlowForPurge =
(string.Equals(currentSiH4FlowMode, FlowModeParam.FlowModeEnum.Run.ToString(),
StringComparison.OrdinalIgnoreCase) == false
? currentSiH4Flow
: 0d)
+ (string.Equals(currentTcsFlowMode, FlowModeParam.FlowModeEnum.Run.ToString(),
StringComparison.OrdinalIgnoreCase) == false
? tcsFlow
: 0d) +
(string.Equals(currentHClFlowMode, FlowModeParam.FlowModeEnum.Run.ToString(),
StringComparison.OrdinalIgnoreCase) == false
? currentHClFlow
: 0d);
var currentCSourTotalFlowForPurge =
string.Equals(currentC2H4FlowMode, FlowModeParam.FlowModeEnum.Run.ToString(),
StringComparison.OrdinalIgnoreCase) == false
? currentC2H4Flow
: 0d;
var n2Flow = (string.Equals(currentN2FlowMode, FlowModeParam.FlowModeEnum.Run.ToString(),
StringComparison.OrdinalIgnoreCase) == false
? currentDilutedN2Flow
: 0d) +
(string.Equals(currentN2HighFlowMode, FlowModeParam.FlowModeEnum.Run.ToString(),
StringComparison.OrdinalIgnoreCase) == false
? currentN2HighFlow
: 0d);
var currentDopeTotalFlowForPurge = n2Flow + (string.Equals(currentTmaFlowMode,
FlowModeParam.FlowModeEnum.Run.ToString(), StringComparison.OrdinalIgnoreCase) == false
? tmaFlow
: 0d);
var currentVentPushFlow = currentTotalVentFlow - currentSiSourTotalFlowForPurge -
currentCSourTotalFlowForPurge - currentDopeTotalFlowForPurge;
((DoubleParam)currentStep[(int)RecipColNo.VentPushFlow]).Value = Math.Round(currentVentPushFlow, 1);
}
public void CalRecipeParameterForRunVent()
{
/*if (!(currentStep.StepTime > 0))
return;*/
CalSiSourceFlow(this);
CalCSourceFlow(this);
CalDopeFlow(this);
CalShSupplementFlow(this);
CalVentFlow(this, Parent.Module);
}
[Obsolete("该函数已废除,请使用分步计算函数。")]
private void CalRecipeParameterForRunVent(RecipeStep previousStep,
IReadOnlyList<Param> currentStep, double stepTime)
{
/*#region SH Total flow
var currentShTotalFlow = ((DoubleParam)currentStep[(int)RecipColNo.SHTotalFlow]).Value;
var currentSurroundingFlow = ((DoubleParam)currentStep[(int)RecipColNo.CarrayGasFlow]).Value;
var currentShTotalFlowSplitRatio = new double[3];
if (currentStep[(int)RecipColNo.SHTotalFlowSplitRatio] is Sets3RatioParam shTotalRatio)
currentShTotalFlowSplitRatio = shTotalRatio.Ratio;
#endregion
#region Si Source
var currentSiH4Flow = ((DoubleParam)currentStep[(int)RecipColNo.SiH4Flow]).Value;
var currentTcsBubbleLowFlow = ((DoubleParam)currentStep[(int)RecipColNo.TCSBubbLowFlow]).Value;
var currentTcsBubbleHighFlow = ((DoubleParam)currentStep[(int)RecipColNo.TCSBubbHighFlow]).Value;
var currentTcsPushFlow = ((DoubleParam)currentStep[(int)RecipColNo.TCSPushFlow]).Value;
var currentHClFlow = ((DoubleParam)currentStep[(int)RecipColNo.HCLFlow]).Value;
var currentSiSourSplitRatio = new double[3];
if (currentStep[(int)RecipColNo.SiSourceSplitRatio] is Sets3RatioParam siSourceRatio)
currentSiSourSplitRatio = siSourceRatio.Ratio;
var currentSiSourTotalFlow = ((DoubleParam)currentStep[(int)RecipColNo.SiSourceTotalFlow]).Value;
var currentSiH4FlowMode = (currentStep[(int)RecipColNo.SiH4FlowMode] as ComboxParam)?.Value;
var currentTcsFlowMode = (currentStep[(int)RecipColNo.TCSFlowMode] as ComboxParam)?.Value;
var currentHClFlowMode = (currentStep[(int)RecipColNo.HCLFlowMode] as ComboxParam)?.Value;
double tcsFlow = 0d;
var tcsEff =
(double)QueryDataClient.Instance.Service.GetConfig($"PM.{Parent.ChamberBelongTo}.Efficiency.TCS-Eff");
if (string.Equals(currentTcsFlowMode, FlowModeParam.FlowModeEnum.Run.ToString(),
StringComparison.OrdinalIgnoreCase)
|| string.Equals(currentTcsFlowMode, FlowModeParam.FlowModeEnum.Vent.ToString(),
StringComparison.OrdinalIgnoreCase))
{
tcsFlow = (currentTcsBubbleHighFlow + currentTcsBubbleLowFlow) * tcsEff + currentTcsPushFlow;
}
else if (string.Equals(currentTcsFlowMode, FlowModeParam.FlowModeEnum.Purge.ToString(),
StringComparison.OrdinalIgnoreCase))
{
tcsFlow = currentTcsBubbleHighFlow + currentTcsBubbleLowFlow + currentTcsPushFlow;
}
//double currentSiSourPushFlow = currentSiSourTotalFlow - (currentSiH4FlowMode == FlowMode.Run.ToString() ? currentSiH4Flow : 0)
// - (currentTCSFlowMode == FlowMode.Run.ToString() ? TCSFlow : 0) - (currentHClFlowMode == FlowMode.Run.ToString() ? currentHClFlow : 0);
//(currentStep[(int)RecipColNo.SiSourceOuterFlow] as DoubleParam).Value = currentSiSourPushFlow.ToString("F1");
double currentSiSourInnerFlow = 0;
double currentSiSourMidFlow = 0;
double currentSiSourOutFlow = 0;
if (currentSiSourSplitRatio.Length == 3)
{
var rationSum = currentSiSourSplitRatio[0] + currentSiSourSplitRatio[1] + currentSiSourSplitRatio[2];
currentSiSourInnerFlow = currentSiSourTotalFlow / rationSum * currentSiSourSplitRatio[0];
currentSiSourMidFlow = currentSiSourTotalFlow / rationSum * currentSiSourSplitRatio[1];
currentSiSourOutFlow = currentSiSourTotalFlow / rationSum * currentSiSourSplitRatio[2];
}
((DoubleParam)currentStep[(int)RecipColNo.SiSourceInnerFlow]).Value = Math.Round(currentSiSourInnerFlow, 1);
((DoubleParam)currentStep[(int)RecipColNo.SiSourceMiddleFlow]).Value = Math.Round(currentSiSourMidFlow, 1);
((DoubleParam)currentStep[(int)RecipColNo.SiSourceOuterFlow]).Value = Math.Round(currentSiSourOutFlow, 1);
#endregion
#region C Source
var currentC2H4Flow = ((DoubleParam)currentStep[(int)RecipColNo.C2H4Flow]).Value;
var currentCSourSplitRatio = new double[3];
if (currentStep[(int)RecipColNo.CSourceSplitRatio] is Sets3RatioParam cSourceRatio)
currentCSourSplitRatio = cSourceRatio.Ratio;
var currentCSourTotalFlow = ((DoubleParam)currentStep[(int)RecipColNo.CSourceTotalFlow]).Value;
var currentC2H4FlowMode = (currentStep[(int)RecipColNo.C2H4FlowMode] as ComboxParam)?.Value;
var currentCSourPushFlow = currentCSourTotalFlow -
(string.Equals(currentC2H4FlowMode, FlowModeParam.FlowModeEnum.Run.ToString(),
StringComparison.OrdinalIgnoreCase)
? currentC2H4Flow
: 0d);
((DoubleParam)currentStep[(int)RecipColNo.CSourceOuterFlow]).Value = Math.Round(currentCSourPushFlow, 1);
double currentCSourInnerFlow = 0;
double currentCSourMidFlow = 0;
double currentCSourOuterFlow = 0;
if (currentCSourSplitRatio.Length == 3)
{
var ratioSum = currentCSourSplitRatio[0] + currentCSourSplitRatio[1] + currentCSourSplitRatio[2];
currentCSourInnerFlow = currentCSourTotalFlow / ratioSum * currentCSourSplitRatio[0];
currentCSourMidFlow = currentCSourTotalFlow / ratioSum * currentCSourSplitRatio[1];
currentCSourOuterFlow = currentCSourTotalFlow / ratioSum * currentCSourSplitRatio[2];
}
((DoubleParam)currentStep[(int)RecipColNo.CSourceInnerFlow]).Value = Math.Round(currentCSourInnerFlow, 1);
((DoubleParam)currentStep[(int)RecipColNo.CSourceMiddleFlow]).Value = Math.Round(currentCSourMidFlow, 1);
((DoubleParam)currentStep[(int)RecipColNo.CSourceOuterFlow]).Value = Math.Round(currentCSourOuterFlow, 1);
#endregion
#region Dope
var currentDopeTotalFlow = ((DoubleParam)currentStep[(int)RecipColNo.DopeTotalFlow]).Value;
var currentN2ActualFlow = ((DoubleParam)currentStep[(int)RecipColNo.N2ActualFlow]).Value;
var currentN2LowFlow = ((DoubleParam)currentStep[(int)RecipColNo.N2LowFlow]).Value;
var currentDiluFlowForN2 = ((DoubleParam)currentStep[(int)RecipColNo.DilutFlowForN2]).Value;
var currentN2HighFlow = ((DoubleParam)currentStep[(int)RecipColNo.N2HighFlow]).Value;
var currentTmaBubbFlow = ((DoubleParam)currentStep[(int)RecipColNo.TMABubbFlow]).Value;
var currentTmaPushFlow = ((DoubleParam)currentStep[(int)RecipColNo.TMAPushFlow]).Value;
var currentDilutedN2Flow =
(currentN2LowFlow + currentDiluFlowForN2) * currentN2ActualFlow / currentN2LowFlow;
((DoubleParam)currentStep[(int)RecipColNo.DilutedN2Flow]).Value = Math.Round(currentDilutedN2Flow, 1);
var currentDopeSplitRatio = new double[3];
if (currentStep[(int)RecipColNo.DopeSplitRatio] is Sets3RatioParam dopRatio)
currentDopeSplitRatio = dopRatio.Ratio;
var currentN2FlowMode = ((ComboxParam)currentStep[(int)RecipColNo.N2FlowMode]).Value;
var currentN2HighFlowMode = ((ComboxParam)currentStep[(int)RecipColNo.N2HighFlowMode]).Value;
var currentTmaFlowMode = ((ComboxParam)currentStep[(int)RecipColNo.TMAFlowMode]).Value;
double tmaFlow = 0;
var tmaEff =
(double)QueryDataClient.Instance.Service.GetConfig($"PM.{Parent.ChamberBelongTo}.Efficiency.TMA-Eff");
if (string.Equals(currentTmaFlowMode, FlowModeParam.FlowModeEnum.Run.ToString(),
StringComparison.OrdinalIgnoreCase)
|| string.Equals(currentTmaFlowMode, FlowModeParam.FlowModeEnum.Vent.ToString(),
StringComparison.OrdinalIgnoreCase))
tmaFlow = currentTmaBubbFlow * tmaEff + currentTmaPushFlow;
else if (string.Equals(currentTmaFlowMode, FlowModeParam.FlowModeEnum.Purge.ToString(),
StringComparison.OrdinalIgnoreCase))
tmaFlow = currentTmaBubbFlow + currentTmaPushFlow;
//double currentDopePushFlow = currentDopeTotalFlow
// - (currentN2FlowMode == FlowMode.Run.ToString() ? currentDilutedN2Flow : 0)
// - (currentN2HighFlowMode == FlowMode.Run.ToString() ? currentN2HighFlow : 0)
// - (currentTMAFlowMode == FlowMode.Run.ToString() ? TMAFlow : 0);
//(currentStep[(int)RecipColNo.DopeOuterFlow] as DoubleParam).Value = currentDopePushFlow.ToString("F1");
double currentDopeInnerFlow = 0;
double currentDopeMidFlow = 0;
double currentDopeOuterFlow = 0;
if (currentDopeSplitRatio.Length == 3)
{
var ratioSum = currentDopeSplitRatio[0] + currentDopeSplitRatio[1] + currentDopeSplitRatio[2];
currentDopeInnerFlow = currentDopeTotalFlow / ratioSum * currentDopeSplitRatio[0];
currentDopeMidFlow = currentDopeTotalFlow / ratioSum * currentDopeSplitRatio[1];
currentDopeOuterFlow = currentDopeTotalFlow / ratioSum * currentDopeSplitRatio[2];
}
(currentStep[(int)RecipColNo.DopeInnerFlow] as DoubleParam).Value = Math.Round(currentDopeInnerFlow, 1);
(currentStep[(int)RecipColNo.DopeMiddleFlow] as DoubleParam).Value = Math.Round(currentDopeMidFlow, 1);
(currentStep[(int)RecipColNo.DopeOuterFlow] as DoubleParam).Value = Math.Round(currentDopeOuterFlow, 1);
#endregion
#region SH Supp. Flow
var currentShSuppTotalFlow = currentShTotalFlow - currentSurroundingFlow - currentSiSourTotalFlow -
currentCSourTotalFlow - currentDopeTotalFlow;
var sumShTotalFlowSplitRatio = currentShTotalFlowSplitRatio[0] + currentShTotalFlowSplitRatio[1] +
currentShTotalFlowSplitRatio[2];
var currentShInnerFlow = (currentShTotalFlow - currentSurroundingFlow) / sumShTotalFlowSplitRatio *
currentShTotalFlowSplitRatio[0];
var currentShMidFlow = (currentShTotalFlow - currentSurroundingFlow) / sumShTotalFlowSplitRatio *
currentShTotalFlowSplitRatio[1];
var currentShOutterFlow = (currentShTotalFlow - currentSurroundingFlow) / sumShTotalFlowSplitRatio *
currentShTotalFlowSplitRatio[2];
var currentInnerSuppFlow = currentShInnerFlow - currentSiSourInnerFlow - currentCSourInnerFlow -
currentDopeInnerFlow;
var currentMidSuppFlow = currentShMidFlow - currentSiSourMidFlow - currentCSourMidFlow - currentDopeMidFlow;
var currentOutterSuppFlow = currentShSuppTotalFlow - currentInnerSuppFlow - currentMidSuppFlow;
(currentStep[(int)RecipColNo.SHPushTotalFlow] as DoubleParam).Value = Math.Round(currentShSuppTotalFlow, 1);
(currentStep[(int)RecipColNo.SHInnerFlow] as DoubleParam).Value = Math.Round(currentShInnerFlow, 1);
(currentStep[(int)RecipColNo.SHMiddleFlow] as DoubleParam).Value = Math.Round(currentShMidFlow, 1);
(currentStep[(int)RecipColNo.SHOuterFlow] as DoubleParam).Value = Math.Round(currentShOutterFlow, 1);
(currentStep[(int)RecipColNo.InnerPushFlow] as DoubleParam).Value = Math.Round(currentInnerSuppFlow, 1);
(currentStep[(int)RecipColNo.MiddlePushFlow] as DoubleParam).Value = Math.Round(currentMidSuppFlow, 1);
(currentStep[(int)RecipColNo.OuterPushFlow] as DoubleParam).Value = Math.Round(currentOutterSuppFlow, 1);
#endregion
#region Vent Flow
var currentTotalVentFlow = (currentStep[(int)RecipColNo.TotalVentFlow] as DoubleParam).Value;
var currentSiSourTotalFlowForPurge =
(string.Equals(currentSiH4FlowMode, FlowModeParam.FlowModeEnum.Run.ToString(),
StringComparison.OrdinalIgnoreCase) == false
? currentSiH4Flow
: 0d)
+ (string.Equals(currentTcsFlowMode, FlowModeParam.FlowModeEnum.Run.ToString(),
StringComparison.OrdinalIgnoreCase) == false
? tcsFlow
: 0d) +
(string.Equals(currentHClFlowMode, FlowModeParam.FlowModeEnum.Run.ToString(),
StringComparison.OrdinalIgnoreCase) == false
? currentHClFlow
: 0d);
var currentCSourTotalFlowForPurge =
string.Equals(currentC2H4FlowMode, FlowModeParam.FlowModeEnum.Run.ToString(),
StringComparison.OrdinalIgnoreCase) == false
? currentC2H4Flow
: 0d;
var n2Flow = (string.Equals(currentN2FlowMode, FlowModeParam.FlowModeEnum.Run.ToString(),
StringComparison.OrdinalIgnoreCase) == false
? currentDilutedN2Flow
: 0d) +
(string.Equals(currentN2HighFlowMode, FlowModeParam.FlowModeEnum.Run.ToString(),
StringComparison.OrdinalIgnoreCase) == false
? currentN2HighFlow
: 0d);
var currentDopeTotalFlowForPurge = n2Flow + (string.Equals(currentTmaFlowMode,
FlowModeParam.FlowModeEnum.Run.ToString(), StringComparison.OrdinalIgnoreCase) == false
? tmaFlow
: 0d);
var currentVentPushFlow = currentTotalVentFlow - currentSiSourTotalFlowForPurge -
currentCSourTotalFlowForPurge - currentDopeTotalFlowForPurge;
(currentStep[(int)RecipColNo.VentPushFlow] as DoubleParam).Value = Math.Round(currentVentPushFlow, 1);
#endregion*/
}
2023-04-13 11:51:03 +08:00
#endregion
#region Override Methods
2023-04-13 11:51:03 +08:00
protected override void InsertItem(int index, Param item)
{
if (item != null)
{
item.Parent = this;
LinkWithPreviousParam(item);
LinkWithNextParam(item);
2023-04-13 11:51:03 +08:00
item.PropertyChanged += ParamOnPropertyChanged;
}
base.InsertItem(index, item);
}
protected override void SetItem(int index, Param item)
{
throw new NotSupportedException();
}
protected override void RemoveItem(int index)
{
if (Count > 0)
{
if (index >= 0 && index < Count)
{
this[index].PropertyChanged -= ParamOnPropertyChanged;
}
}
// 将前后两个Param链接起来
var preParam = this[index].Previous;
var nextParam = this[index].Next;
if (preParam != null && nextParam != null)
{
preParam.Next = nextParam;
nextParam.Previous = preParam;
}
else if (preParam == null && nextParam != null)
{
nextParam.Previous = null;
}
else if (preParam != null)
{
preParam.Next = null;
}
IsSaved = false;
SavedStateChanged?.Invoke(this, true);
base.RemoveItem(index);
}
protected override void ClearItems()
{
this.ToList().ForEach(x => x.PropertyChanged -= ParamOnPropertyChanged);
IsSaved = Count <= 0;
SavedStateChanged?.Invoke(this, true);
base.ClearItems();
}
public override string ToString()
{
return Count > 0 ? (StepNoParam == null ? "Recipe Step, Item={Count}" : StepNoParam.ToString()) : "Empty Recipe Step";
2023-04-13 11:51:03 +08:00
}
#endregion
}
}