using ErrorAnalysis.Repository; using ErrorAnalysis.Service.Model; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace ErrorAnalysis.Service { public class ErrorRatioCalc { public static ErrorRatioResult GetErrorRatioResult(string modelID, double porosity, double sw, double depth, bool lockSpeed, double speed, double targetErrorRatio, int pass = 0) { var result = new ErrorRatioResult { CWOL = new List(), OWOL = new List(), ErrorRatios = new List() }; result.COModel = RepositoryInstance.Instance.COModelRepository?.GetCOModel(modelID); if (lockSpeed) { List cWOL; List oWOL; var firsErrorPass = GetFirstErrorRatio(modelID, porosity, sw, speed, depth, out cWOL, out oWOL); result.CWOL = cWOL; result.OWOL = oWOL; result.ErrorRatios.Add(firsErrorPass); if (firsErrorPass.ErrorRatioValue > targetErrorRatio) { var targetPass = Convert.ToInt32(Math.Ceiling(Math.Pow(firsErrorPass.ErrorRatioValue / targetErrorRatio, 2))); for (int i = 2; i <= targetPass; i++) { result.ErrorRatios.Add(new ErrorRatio { Pass = i, ErrorRatioValue = firsErrorPass.ErrorRatioValue / Math.Sqrt(i) }); } } } else { var firstTargetErrorRatio = targetErrorRatio * Math.Sqrt(pass); List cWOL; List oWOL; var firstErrorPass = new ErrorRatio(); speed = 0.6; while (firstErrorPass.ErrorRatioValue != 0 && firstErrorPass.ErrorRatioValue > firstTargetErrorRatio) { firstErrorPass = GetFirstErrorRatio(modelID, porosity, sw, speed, depth, out cWOL, out oWOL); result.CWOL = cWOL; result.OWOL = oWOL; speed -= 0.01; } } return result; } private static ErrorRatio GetFirstErrorRatio(string modelID, double porosity, double sw, double speed, double depth, out List cWOL, out List oWOL) { if (porosity > 40) throw new InvalidDataException("Porosity value out of range!"); cWOL = new List(); oWOL = new List(); var cWolRes = RepositoryInstance.Instance.COWOLRepository?.GetWOL(modelID, 0); var oWolRes = RepositoryInstance.Instance.COWOLRepository?.GetWOL(modelID, 100); var mergePDEV = PDEVCalcService.GetMergePDEV(modelID, porosity, sw, speed, depth); var wolResType = cWolRes?.GetType(); try { if (sw > 0 && sw < 100) { foreach (var wolProperty in wolResType.GetProperties()) { if (wolProperty.Name.Contains("WLPu")) { var interC = Utility.Interpolate(sw, 100, 0, 0, (double)wolProperty.GetValue(cWolRes)); var interO = Utility.Interpolate(sw, 0, 0, 100, (double)wolProperty.GetValue(oWolRes)); wolProperty.SetValue(cWolRes, interC); wolProperty.SetValue(oWolRes, interO); } } } foreach (var wolProperty in wolResType.GetProperties()) { if (wolProperty.Name.Contains("WLPu")) { cWOL.Add([Convert.ToDouble(wolProperty.Name.Replace("WLPu", "")), Convert.ToDouble(wolProperty.GetValue(cWolRes))]); oWOL.Add([Convert.ToDouble(wolProperty.Name.Replace("WLPu", "")), Convert.ToDouble(wolProperty.GetValue(oWolRes))]); } } double cRes = 0; double oRes = 0; if (porosity % 5 == 0) { var poroFiledName = $"WLPu" + porosity; var property = wolResType.GetProperty(poroFiledName); cRes = Convert.ToDouble(property.GetValue(cWolRes)); oRes = Convert.ToDouble(property.GetValue(oWolRes)); } else { var ceilingPorosity = Math.Ceiling(porosity / 5) * 5; var ceilingProperty = wolResType.GetProperty($"WLPu" + ceilingPorosity); var ceilingC = Convert.ToDouble(ceilingProperty.GetValue(cWolRes)); var ceilingO = Convert.ToDouble(ceilingProperty.GetValue(oWolRes)); var floorPorosity = Math.Floor(porosity / 5) * 5; var floorProperty = wolResType.GetProperty($"WLPu" + floorPorosity); var floorC = Convert.ToDouble(floorProperty.GetValue(cWolRes)); var floorO = Convert.ToDouble(floorProperty.GetValue(oWolRes)); cRes = Utility.Interpolate(porosity, floorPorosity, floorC, ceilingPorosity, ceilingC); oRes = Utility.Interpolate(porosity, floorPorosity, floorO, ceilingPorosity, ceilingO); } var errorRatio = mergePDEV / (cRes - oRes); return new ErrorRatio { Pass = 1, ErrorRatioValue = errorRatio }; } catch { cWOL = null; oWOL = null; return new ErrorRatio { Pass = 0, ErrorRatioValue = 0 }; } } } }