/// <summary> /// Iteration methord host /// </summary> /// <param name="impellerInput">Input impeller</param> /// <returns>Impeller with calculated data</returns> public Impeller Iteration(Impeller impellerInput) { var impeller = new Impeller(impellerInput); var impellerNew = new Impeller(); //initial the Y(x) array //get Y(x) array impeller.Y = new List<double>(impeller.PSections.Count); for (int i = 0; i < impeller.PSections.Count; i++) { //Type 1 : Y(x) = (x / height)^2 impeller.Y.Add( Math.Pow(impeller.PSections[i].Position / impeller.Height, 2)); } int iterationCount = 0; while (true) { iterationCount++; //get new impeller Y impellerNew = IterationCalculater(impeller); impellerNew.IterationCount = iterationCount; //if impeller Y is precise enough or if cycled too many times, quit iteration if (ImpellerDifference(impeller, impellerNew) < impeller.MinTolerance || iterationCount > impeller.MaxIterationCount) { impeller = impellerNew; break; } impeller = impellerNew; } return impeller; }
/// <summary> /// Iteration methord host /// </summary> /// <param name="impellerInput">Input impeller</param> /// <returns>Impeller with calculated data</returns> public Impeller Iteration(Impeller impellerInput, AssumeDeflectionFunction deflectionFunc) { var impeller = new Impeller(impellerInput); var impellerNew = new Impeller(); //initial the Y(x) array //get Y(x) array try { impeller.Y = deflectionFunc(impeller.PSections, impeller.Height); } catch { throw; } int iterationCount = 0; while (true) { iterationCount++; //get new impeller Y impellerNew = IterationCalculater(impeller); impellerNew.IterationCount = iterationCount; //if impeller Y is precise enough or if cycled too many times, quit iteration if (ImpellerDifference(impeller, impellerNew) < impeller.MinTolerance || iterationCount > impeller.MaxIterationCount) { impeller = impellerNew; break; } impeller = impellerNew; } return impeller; }
/// <summary> /// Rayleigh methord host /// </summary> /// <param name="impellerInput">Input impeller</param> /// <param name="g">Gravitational acceleration, m/s^2</param> /// <returns>Impeller with calculated data</returns> public Impeller Rayleigh(Impeller impellerInput, double g) { var impeller = RayleighCalculater(impellerInput, g); double uTemp = 0; double dTemp = 0; for (var i = 0; i < impeller.MSections.Count; i++) { uTemp += impeller.MSections[i].Mass * impeller.Y[i]; dTemp += impeller.MSections[i].Mass * Math.Pow(impeller.Y[i], 2); } //ω = sqrt( g * ∑(mi*Yi) / ∑(mi*Yi^2) ) impeller.LegacyVibrationFrequency = Math.Sqrt(g * uTemp / dTemp) / (2 * Math.PI); return impeller; }
/// <summary> /// Make a copy from existed impeller /// </summary> /// <param name="impeller">Impeller copy</param> public Impeller(Impeller impeller) { this.Comment = impeller.Comment; if (impeller.Density >= 0) this.Density = impeller.Density; if (impeller.E >= 0) this.E = impeller.E; if (impeller.Height >= 0) this.Height = impeller.Height; if (impeller.IterationCount >= 0) this.IterationCount = impeller.IterationCount; if (impeller.LegacyVibrationFrequency >= 0) this.LegacyVibrationFrequency = impeller.LegacyVibrationFrequency; if (impeller.MaxIterationCount >= 0) this.MaxIterationCount = impeller.MaxIterationCount; if (impeller.MaxProhlOmegaSearchCount >= 0) this.MaxProhlOmegaSearchCount = impeller.MaxProhlOmegaSearchCount; if (impeller.MaxProhlSearchCount >= 0) this.MaxProhlSearchCount = impeller.MaxProhlSearchCount; if (impeller.MinStepDiff > 0) this.MinStepDiff = impeller.MinStepDiff; if (impeller.MinTolerance > 0) this.MinTolerance = impeller.MinTolerance; if (impeller.MSections != null) this.MSections = impeller.MSections; if (impeller.PSections != null) this.PSections = impeller.PSections; if (impeller.VibrationFrequency != null) this.VibrationFrequency = impeller.VibrationFrequency; if (impeller.Y != null) this.Y = impeller.Y; }
/// <summary> /// Impeller vibration frequency calculater with iteration method /// </summary> /// <param name="impeller">Input impeller</param> /// <returns>Calculated impeller</returns> private Impeller IterationCalculater(Impeller impeller) { //cache result array var resultCache = new List<double>(new double[impeller.PSections.Count]); var resultCache2 = new List<double>(new double[impeller.PSections.Count]); var resultImpeller = new Impeller(impeller); // (A*Y_ij)_k or q_k/pw^2 for (int i = 0; i < impeller.PSections.Count; i++) { resultCache[i] = impeller.Y[i] * impeller.PSections[i].Area; } //first and second integral for (int integralCount = 2; integralCount > 0; integralCount--) { for (int i = 0; i < impeller.PSections.Count; i++) { if (i == 0) { resultCache2[i] = 0; } else { // (2/pw^2)*q_mk then 4Q_mk/(pw^2*Δx) resultCache2[i] = resultCache[i] + resultCache[i - 1]; } } for (int i = impeller.PSections.Count - 1; i >= 0; i--) { if (i == impeller.PSections.Count - 1) { resultCache[i] = 0; } else { // 2Q_k/(pw^2*Δx) then (4/(pw^2*Δx^2))*M_k resultCache[i] = resultCache[i + 1] + resultCache2[i + 1]; } } } // (4E/(pw^2*Δx^2))*(ΔY')/Δx for (int i = 0; i < impeller.PSections.Count; i++) { resultCache[i] = resultCache[i] / impeller.PSections[i].InertiaMoment; } //third and fourth integral for (int integralCount = 2; integralCount > 0; integralCount--) { for (int i = 0; i < impeller.PSections.Count; i++) { if (i == 0) { resultCache2[i] = 0; } else { // (8E/(pw^2*Δx^2))*(ΔY')_m/Δx^2 then (16E/(pw^2*Δx^3))*(ΔY')_m/Δx resultCache2[i] = resultCache[i] + resultCache[i - 1]; } } for (int i = 0; i < impeller.PSections.Count; i++) { if (i == 0) { resultCache[i] = 0; } else { // (8E/(pw^2*Δx^3))*(ΔY')/Δx^2 then (16E/(pw^2*Δx^4))*ΔY' resultCache[i] = resultCache[i - 1] + resultCache2[i]; } } } // ΔY', i.e. impeller Y New = (cache1[i] / max(cache1) ) double maxResult = resultCache.Max(); for (int i = 0; i < resultCache.Count; i++) { resultCache[i] = resultCache[i] / maxResult; } resultImpeller.Y = resultCache; //ω = (4 / Δx^2) * (sqrt(E/(ρZ))) resultImpeller.LegacyVibrationFrequency = 4 / Math.Pow(impeller.PAvePieceLength, 2) * Math.Sqrt(impeller.E / (impeller.Density * maxResult)); //f = ω / 2π resultImpeller.LegacyVibrationFrequency /= (2 * Math.PI); return resultImpeller; }
/// <summary> /// Check the difference between two impeller Y /// </summary> /// <param name="impellerYA">The first impeller Y array</param> /// <param name="impellerYB">The second impeller Y array</param> /// <returns>Total difference</returns> private double ImpellerDifference(Impeller impellerA, Impeller impellerB) { double totalMess = 0; if (impellerA.Y.Count != impellerB.Y.Count) { return -1; } for (int i = 0; i < impellerA.Y.Count; i++) { totalMess += Math.Abs(impellerA.Y[i] - impellerB.Y[i]); } return totalMess; }
/// <summary> /// Impeller vibration frequency calculater with Rayleigh method /// </summary> /// <param name="impeller">Input impeller</param> /// <returns>Calculated impeller</returns> private Impeller RayleighCalculater(Impeller impeller, double g) { //cache result array var resultCache = new List<double>(new double[impeller.MSections.Count]); var resultCache2 = new List<double>(new double[impeller.MSections.Count]); for (int i = 0; i < impeller.MSections.Count; i++) { if (i == 0) { resultCache[i] = impeller.MSections[i+1].Mass / impeller.MSections[i+1].Position; } else { resultCache[i] = impeller.MSections[i].Mass / (impeller.MSections[i].Position - impeller.MSections[i-1].Position); } } //first and second integral for (int integralCount = 2; integralCount > 0; integralCount--) { for (int i = 0; i < impeller.MSections.Count; i++) { if (i == 0) { resultCache2[i] = 0; } else { resultCache2[i] = (resultCache[i] + resultCache[i - 1]) / 2; } } for (int i = impeller.MSections.Count - 1; i >= 0; i--) { if (i == impeller.MSections.Count - 1) { resultCache[i] = 0; } else { resultCache[i] = resultCache[i + 1] + resultCache2[i + 1] * (impeller.MSections[i + 1].Position - impeller.MSections[i].Position); } } } for (int i = 0; i < impeller.MSections.Count; i++) { resultCache[i] = resultCache[i] / impeller.MSections[i].InertiaMoment; } //third and fourth integral for (int integralCount = 2; integralCount > 0; integralCount--) { for (int i = 0; i < impeller.MSections.Count; i++) { if (i == 0) { resultCache2[i] = 0; } else { resultCache2[i] = (resultCache[i] + resultCache[i - 1]) / 2; } } for (int i = 0; i < impeller.MSections.Count; i++) { if (i == 0) { resultCache[i] = 0; } else { resultCache[i] = resultCache[i - 1] + resultCache2[i] * (impeller.MSections[i].Position - impeller.MSections[i-1].Position); } } } for (var i = 0; i < resultCache.Count; i++) { resultCache[i] = resultCache[i] * g / impeller.E; } impeller.Y = resultCache; return impeller; }
/// <summary> /// Iteration frequency founder /// </summary> /// <param name="impeller">Input impeller</param> /// <param name="state">State object</param> private double ProhlFound(Impeller impeller, ProhlState state) { int searchCount = 0; double step = state.ProhlStep; int jumpSign = Math.Sign(state.residualMoment); int landSign = jumpSign; int direction = -1; // -1 = backwards , 1 = forwards while (step > impeller.MinStepDiff && searchCount < impeller.MaxProhlOmegaSearchCount) { step /= 2; state.Omega += direction * step; //caculate transfer matrix and residual moment ProhlCalculator(impeller, state); landSign = Math.Sign(state.residualMoment); if (jumpSign != landSign) { direction *= -1; jumpSign = landSign; } searchCount++; } impeller.IterationCount = searchCount; state.TempOmegaPoint = state.Omega; return state.Omega; }
/// <summary> /// Prohl matrix methord host /// </summary> /// <param name="impellerInput">Input impeller</param> /// <param name="state">Some settings and states</param> /// <returns>Impeller with calculated data</returns> public Impeller Prohl(Impeller impellerInput, ProhlState state) { var impeller = new Impeller(impellerInput); var freqPoints = new Dictionary<double,int>(); int mainLoopCount = 0; state.Omega = state.CheckFromOmega; state.residualMoment = 0; if (state.Omega > state.CheckToOmega) { ProhlCalculator(impeller, state); } else { int anchorSign; //store the residualMoment sign double anchor; //store the freq double determinantAnchor; //store the residualMoment double freqPoint; while (state.Omega <= state.CheckToOmega && mainLoopCount++ < impeller.MaxProhlSearchCount) { //search the frequency point anchorSign = Math.Sign(state.residualMoment); ProhlCalculator(impeller, state); if (Math.Sign(state.residualMoment) * anchorSign < 0) { anchor = state.Omega; determinantAnchor = state.residualMoment; //find freq point freqPoint = ProhlFound(impeller, state); if (impeller.VibrationFrequency.IndexOf(freqPoint) < 0) { impeller.VibrationFrequency.Add(freqPoint); freqPoints.Add(freqPoint, impeller.IterationCount); } state.Omega = anchor + state.ProhlStep; state.residualMoment = determinantAnchor; if (ProhlOmega_Changed != null) { ProhlOmega_Changed(impeller, state); //System.Windows.MessageBox.Show(""); } } else { state.Omega += state.ProhlStep; if (ProhlOmega_Changed != null) { ProhlOmega_Changed(impeller, state); //System.Windows.MessageBox.Show(""); } } } } impeller.VibrationFrequency = new List<double>(); foreach( var freqPoint in freqPoints){ impeller.VibrationFrequency.Add(freqPoint.Key / (2 * Math.PI)); } impeller.IterationCount = mainLoopCount; return impeller; }
/// <summary> /// Impeller vibration frequency calculater with Prohl method /// </summary> /// <param name="impeller">Input impeller</param> /// <param name="state">State object</param> private void ProhlCalculator(Impeller impeller, ProhlState state) { #if TRACER watch.Start(); #endif // the non-zero numbers of root state vector const int ROOT_STATE_VECTOR_SIZE = 2; var transferMatrix = new Matrix(4, 4); var residualMatrix = new Matrix(2, 2); //vibration frequency order var rootStateVector = new Matrix[2]{ new Matrix( new double[][]{ new double[] {0}, new double[] {0}, new double[] {1}, new double[] {0} } ), new Matrix( new double[][]{ new double[] {0}, new double[] {0}, new double[] {0}, new double[] {1} } ) }; //section transfer matrix and hole transfer matrix(from root to end) var sectionTransferMatrix = new Matrix( new double[][]{ new double[] {1,1,1,1}, new double[] {0,1,1,1}, new double[] {0,0,1,1}, new double[] {1,1,1,1} } ); #if TRACER long step1 = watch.ElapsedTicks; #endif double freq2 = state.Omega * state.Omega; for (var j = 0; j < ROOT_STATE_VECTOR_SIZE; j++) { for (var i = 0; i < impeller.MSections.Count; i++) { double L = (i == 0 ? impeller.MSections[0].Position : impeller.MSections[i].Position - impeller.MSections[i - 1].Position); //L_EJ = L / EJ double L_EJ = L / (impeller.E * impeller.MSections[i].InertiaMoment); double m = impeller.MSections[i].Mass; //freq2xm = freq2 double freq2xm = freq2 * m; sectionTransferMatrix[3, 0] = freq2xm; sectionTransferMatrix[0, 1] = L; sectionTransferMatrix[3, 1] = freq2xm * L; sectionTransferMatrix[0, 2] = L * L_EJ / 2; sectionTransferMatrix[1, 2] = L_EJ; sectionTransferMatrix[3, 2] = freq2xm * L * L_EJ / 2; sectionTransferMatrix[0, 3] = L * L * L_EJ / 6; sectionTransferMatrix[1, 3] = L * L_EJ / 2; sectionTransferMatrix[2, 3] = L; sectionTransferMatrix[3, 3] = 1 + freq2xm * L * L * L_EJ / 6; transferMatrix = (i == 0 ? sectionTransferMatrix.Clone() : sectionTransferMatrix.Multiply(transferMatrix)); } state.TransferMatrix = transferMatrix; state.StateVector = transferMatrix.Multiply(rootStateVector[j]); for (var i = 0; i < state.EndStateVector.RowCount; i++) { if (state.EndStateVector[i, 0] == 0 ) { if (residualMatrix[0, j] == 0) { residualMatrix[0, j] = state.StateVector[i, 0]; continue; } residualMatrix[1, j] = state.StateVector[i, 0]; break; } } } #if TRACER long step2 = watch.ElapsedTicks; watch.Reset(); System.Windows.MessageBox.Show( "Run time" + "\nstep1: " + step1 + "\nstep2: " + (step2 - step1) ); #endif state.residualMoment = residualMatrix.Determinant(); }
private PointCollection GetPointsFromY(Impeller impeller, double canvasHeight, double canvasWidth) { var points = new List<Point>(impeller.Y.Count); double heightScale = canvasHeight / impeller.Y.Max(); double widthScale = canvasWidth / impeller.MSections.Max(sec => sec.Position); points.Add(new Point(0, canvasHeight)); for (int i = 0; i < impeller.Y.Count; i++) { points.Add(new Point(impeller.MSections[i].Position * widthScale, canvasHeight - impeller.Y[i] * heightScale)); } return new PointCollection(points); }
private Impeller FullSectionsDepartor(List<FullSection> fullSections, Impeller target) { fullSections = fullSections.OrderBy(sec => sec.Position).ToList(); target.MSections = new List<MechanicalSection>(fullSections.Count); target.PSections = new List<PhysicalSection>(fullSections.Count); foreach (var section in fullSections) { target.MSections.Add(new MechanicalSection(section.Position, section.InertiaMoment, section.Mass)); target.PSections.Add(new PhysicalSection(section.Position, section.InertiaMoment, section.Area)); } return target; }
private void ShowProgressBar(Impeller impeller, ProhlState state) { progressBar.Dispatcher.Invoke(new Action(() => { progressBar.Value = state.Omega; }), System.Windows.Threading.DispatcherPriority.ContextIdle); }
private string ShowResult(Impeller impeller, CalculateMethod method) { string resultString = ""; StringBuilder yString = new StringBuilder(); switch (method) { case CalculateMethod.Rayleigh: for (int i = 0; i < Impeller.InnerImpeller.Y.Count; i++) { yString .Append(Impeller.InnerImpeller.MSections[i].Position.ToString()) .Append(" : ") .Append(Impeller.InnerImpeller.Y[i].ToString()) .Append("\n"); } resultString = "计算方法:Rayleigh法" + "\n一阶固有频率:" + Impeller.InnerImpeller.LegacyVibrationFrequency.ToString() + " Hz" + "\n\n振型(位置,单位m : 振幅,单位m)\n" + yString.ToString(); break; case CalculateMethod.Iteration: for (int i = 0; i < Impeller.InnerImpeller.Y.Count; i++) { yString .Append(Impeller.InnerImpeller.PSections[i].Position.ToString()) .Append(" : ") .Append(Impeller.InnerImpeller.Y[i].ToString()) .Append("\n"); } resultString = "计算方法:振型迭代法" + "\n迭代次数:" + Impeller.InnerImpeller.IterationCount + "\n一阶固有频率: " + Impeller.InnerImpeller.LegacyVibrationFrequency.ToString() + " Hz" + "\n\n振型(位置,单位m : 振幅,相对值)\n" + yString.ToString(); break; case CalculateMethod.Prohl: int power = 1; resultString = "计算方法:Prohl传递矩阵法" + "\n检测次数:" + (Impeller.InnerImpeller.IterationCount + 1).ToString(); foreach (var freq in Impeller.InnerImpeller.VibrationFrequency) { resultString += "\n" + (power++) + "阶固有频率: " + freq + " Hz"; } break; default: break; } return resultString; }