| | |
| | | private static (double slope, double intercept) _lineCoef; |
| | | private static (double a, double b, double c) _parabolaCoef; |
| | | |
| | | public static ErrorRatioResult GetErrorRatioResult(string modelID, double porosity, double sw, double depth, bool lockSpeed, double speed, double yieldCounting, double targetErrorRatio, out double testSpeed, int pass = 0, double nearCofe = 0.65, double farCofe = 0.35) |
| | | public static ErrorRatioResult GetErrorRatioResult(string modelID, double porosity, double sw, double depth, bool lockSpeed, double speed, double yieldCounting, double targetErrorRatio, out double testSpeed, out ProcessingDataModel processingData, int pass = 0, double nearCofe = 0.65, double farCofe = 0.35) |
| | | { |
| | | processingData = new ProcessingDataModel { Depth = depth, NearPDEVCoef = nearCofe, FarPDEVCoef = farCofe, NearTO = yieldCounting }; |
| | | var result = new ErrorRatioResult |
| | | { |
| | | CWOL = new List<double[]>(), |
| | | OWOL = new List<double[]>(), |
| | | ErrorRatios = new List<ErrorRatio>() |
| | | }; |
| | | |
| | | result.COModel = RepositoryInstance.Instance.COModelRepository?.GetCOModel(modelID); |
| | | (result.CWOL, result.OWOL) = GetOilWaterLine(modelID); |
| | | processingData.OilLine = result.CWOL; |
| | | processingData.WaterLine = result.OWOL; |
| | | (processingData.OilLineOrigin, processingData.WaterLineOrgin) = GetOilWaterLine(modelID, true); |
| | | processingData.FarSpecData = COMergeCalcService.GetFarSpectrum(modelID, porosity, sw); |
| | | processingData.NearSpecData = COMergeCalcService.GetNearSpectrum(modelID, porosity, sw); |
| | | |
| | | var nearCROR = COMergeCalcService.GetNearCOORResult(modelID, porosity, sw); |
| | | var farCROR = COMergeCalcService.GetFarCOORResult(modelID, porosity, sw); |
| | | processingData.NearCR = nearCROR.Item1; |
| | | processingData.NearOR = nearCROR.Item2; |
| | | processingData.FarCR = farCROR.Item1; |
| | | processingData.FarOR = farCROR.Item2; |
| | | |
| | | var mDelta = GetMDelta(porosity, out double oilPoint, out double waterPoint); |
| | | processingData.OilPoint = oilPoint; |
| | | processingData.WaterPoint = waterPoint; |
| | | |
| | | if (lockSpeed) |
| | | { |
| | | List<double[]> cWOL; |
| | | List<double[]> oWOL; |
| | | (cWOL, oWOL) = GetOilWaterLine(modelID); |
| | | result.CWOL = cWOL; |
| | | result.OWOL = oWOL; |
| | | var firstErrorPassM = GetFirstErrorRatio(modelID, porosity, sw, speed, depth, yieldCounting, nearCofe, farCofe); |
| | | |
| | | var mergePDEV = Math.Sqrt(160 * speed / (0.0762 * 36 * depth)) * Math.Sqrt((Math.Pow(nearCofe, 2) / yieldCounting * (Math.Pow(nearCROR.Item1 / nearCROR.Item2, 2)) * (1 / nearCROR.Item1 + 1 / nearCROR.Item2)) + (Math.Pow(farCofe, 2) / yieldCounting / 2.2 * (Math.Pow(farCROR.Item1 / farCROR.Item2, 2)) * (1 / farCROR.Item1 + 1 / farCROR.Item2))); |
| | | var firstErrorPassM = new ErrorRatio { Pass = 1, ErrorRatioValue = mergePDEV / mDelta }; |
| | | result.ErrorRatios.Clear(); |
| | | result.ErrorRatios.Add(firstErrorPassM); |
| | | |
| | | if (firstErrorPassM.ErrorRatioValue > targetErrorRatio) |
| | | { |
| | | var targetPass = Convert.ToInt32(Math.Ceiling(Math.Pow(firstErrorPassM.ErrorRatioValue / targetErrorRatio, 2))); |
| | |
| | | result.ErrorRatios.Add(new ErrorRatio { Pass = i, ErrorRatioValue = firstErrorPassM.ErrorRatioValue / Math.Sqrt(i) }); |
| | | } |
| | | } |
| | | processingData.Speed = speed; |
| | | } |
| | | else |
| | | { |
| | | var firstTargetErrorRatio = targetErrorRatio * Math.Sqrt(pass); |
| | | List<double[]> cWOL; |
| | | List<double[]> oWOL; |
| | | (cWOL, oWOL) = GetOilWaterLine(modelID); |
| | | result.CWOL = cWOL; |
| | | result.OWOL = oWOL; |
| | | |
| | | var nearCROR = COMergeCalcService.GetNearCOORResult(modelID, porosity, sw); |
| | | var farCROR = COMergeCalcService.GetFarCOORResult(modelID, porosity, sw); |
| | | var mDelta = GetMDelta(porosity); |
| | | |
| | | speed = Math.Pow(firstTargetErrorRatio / |
| | | (Math.Sqrt(160 / (0.0762 * depth * 36d * yieldCounting)) * |
| | | processingData.Speed = speed = Math.Pow(firstTargetErrorRatio / |
| | | (Math.Sqrt(160 / (0.0762 * depth * 36d)) * |
| | | 1d / mDelta) / |
| | | Math.Sqrt((Math.Pow(nearCofe, 2) * (Math.Pow(nearCROR.Item1 / nearCROR.Item2, 2)) * (1 / nearCROR.Item1 + 1 / nearCROR.Item2)) + (Math.Pow(farCofe, 2) * (Math.Pow(farCROR.Item1 / farCROR.Item2, 2)) * (1 / farCROR.Item1 + 1 / farCROR.Item2))) |
| | | Math.Sqrt((Math.Pow(nearCofe, 2) / yieldCounting * (Math.Pow(nearCROR.Item1 / nearCROR.Item2, 2)) * (1 / nearCROR.Item1 + 1 / nearCROR.Item2)) + (Math.Pow(farCofe, 2) / yieldCounting / 2.2 * (Math.Pow(farCROR.Item1 / farCROR.Item2, 2)) * (1 / farCROR.Item1 + 1 / farCROR.Item2))) |
| | | , 2); |
| | | |
| | | var firstErrorPass = new ErrorRatio { Pass = 1, ErrorRatioValue = firstTargetErrorRatio }; |
| | |
| | | |
| | | } |
| | | |
| | | private static ErrorRatio GetFirstErrorRatio(string modelID, double porosity, double sw, double speed, double depth, double yieldCounting, double nearCofe, double farCofe) |
| | | private static ErrorRatio GetFirstErrorRatio(string modelID, double porosity, double sw, double speed, double depth, double yieldCounting, double nearCofe, double farCofe, out double oilPoint, out double waterPoint) |
| | | { |
| | | if (porosity > 40) |
| | | throw new InvalidDataException("Porosity value out of range!"); |
| | | |
| | | try |
| | | { |
| | | var mDelta = GetMDelta(porosity); |
| | | var mDelta = GetMDelta(porosity, out oilPoint, out waterPoint); |
| | | |
| | | //var mergePDEVOld = PDEVCalcService.GetMergePDEV(modelID, porosity, sw, speed, depth, yieldCounting, nearCofe, farCofe); |
| | | var mergePDEVOld = PDEVCalcService.GetMergePDEV(modelID, porosity, sw, speed, depth, yieldCounting, nearCofe, farCofe); |
| | | |
| | | var nearCROR = COMergeCalcService.GetNearCOORResult(modelID, porosity, sw); |
| | | var farCROR = COMergeCalcService.GetFarCOORResult(modelID, porosity, sw); |
| | | //var nearCROR = COMergeCalcService.GetNearCOORResult(modelID, porosity, sw); |
| | | //var farCROR = COMergeCalcService.GetFarCOORResult(modelID, porosity, sw); |
| | | |
| | | var mergePDEV = Math.Sqrt(160 * speed / (0.0762 * 36 * depth * yieldCounting)) * Math.Sqrt((Math.Pow(nearCofe, 2) * (Math.Pow(nearCROR.Item1 / nearCROR.Item2, 2)) * (1 / nearCROR.Item1 + 1 / nearCROR.Item2)) + (Math.Pow(farCofe, 2) * (Math.Pow(farCROR.Item1 / farCROR.Item2, 2)) * (1 / farCROR.Item1 + 1 / farCROR.Item2))); |
| | | //var mergePDEV = Math.Sqrt(160 * speed / (0.0762 * 36 * depth)) * Math.Sqrt((Math.Pow(nearCofe, 2) / yieldCounting * (Math.Pow(nearCROR.Item1 / nearCROR.Item2, 2)) * (1 / nearCROR.Item1 + 1 / nearCROR.Item2)) + (Math.Pow(farCofe, 2) / yieldCounting / 2.2 * (Math.Pow(farCROR.Item1 / farCROR.Item2, 2)) * (1 / farCROR.Item1 + 1 / farCROR.Item2))); |
| | | |
| | | var errorRatio = mergePDEV / mDelta; |
| | | var errorRatio = mergePDEVOld / mDelta; |
| | | |
| | | return new ErrorRatio { Pass = 1, ErrorRatioValue = errorRatio }; |
| | | } |
| | | catch |
| | | { |
| | | oilPoint = 0; |
| | | waterPoint = 0; |
| | | return new ErrorRatio { Pass = 0, ErrorRatioValue = 0 }; |
| | | } |
| | | } |
| | | |
| | | private static double GetMDelta(double porosity) |
| | | private static double GetMDelta(double porosity, out double oilPoint, out double waterPoint) |
| | | { |
| | | var oilRes = Utility.GetParabolaValue(porosity, _parabolaCoef.a, _parabolaCoef.b, _parabolaCoef.c); |
| | | var waterRes = Utility.GetLineValue(porosity, _lineCoef.slope, _lineCoef.intercept); |
| | | oilPoint = Utility.GetParabolaValue(porosity, _parabolaCoef.a, _parabolaCoef.b, _parabolaCoef.c); |
| | | waterPoint = Utility.GetLineValue(porosity, _lineCoef.slope, _lineCoef.intercept); |
| | | |
| | | //var cWolRes = RepositoryInstance.Instance.COWOLRepository?.GetWOL(modelID, 0); |
| | | //var oWolRes = RepositoryInstance.Instance.COWOLRepository?.GetWOL(modelID, 100); |
| | |
| | | // cRes = Utility.Interpolate(porosity, floorPorosity, floorC, ceilingPorosity, ceilingC); |
| | | // oRes = Utility.Interpolate(porosity, floorPorosity, floorO, ceilingPorosity, ceilingO); |
| | | //} |
| | | return oilRes - waterRes; |
| | | return oilPoint - waterPoint; |
| | | } |
| | | |
| | | private static (List<double[]>, List<double[]>) GetOilWaterLine(string modelID) |
| | | private static (List<double[]>, List<double[]>) GetOilWaterLine(string modelID, bool original = false) |
| | | { |
| | | var cWOL = new List<double[]>(); |
| | | var oWOL = new List<double[]>(); |
| | | |
| | | var fitModel = GetFitModel(modelID); |
| | | var fitModel = original ? GetModel(modelID) : GetFitModel(modelID); |
| | | |
| | | var cWolRes = fitModel.Item1; |
| | | var oWolRes = fitModel.Item2; |
| | |
| | | } |
| | | } |
| | | return (cWOL, oWOL); |
| | | } |
| | | |
| | | private static (COWOLTable, COWOLTable) GetModel(string modelID) |
| | | { |
| | | var oilWol = RepositoryInstance.Instance.COWOLRepository?.GetWOL(modelID, 0); |
| | | var waterWol = RepositoryInstance.Instance.COWOLRepository?.GetWOL(modelID, 100); |
| | | return (oilWol, waterWol); |
| | | } |
| | | |
| | | private static (COWOLTable, COWOLTable) GetFitModel(string modelID) |
| | |
| | | |
| | | _lineCoef = Utility.FitLine(waterPoints.ToArray()); |
| | | _parabolaCoef = Utility.FitParabola(oilPoints.ToArray()); |
| | | //var texCoef = Utility.quadraticLine(oilPoints.Select(o => Convert.ToDouble(o.X)).ToArray(), oilPoints.Select(o => Convert.ToDouble(o.Y)).ToArray()); |
| | | |
| | | double initDiff = 0; |
| | | |
| | |
| | | var porosity = double.Parse(wolProperty.Name.Replace("WLPu", "")); |
| | | var waterVal = Utility.GetLineValue(porosity, _lineCoef.slope, _lineCoef.intercept); |
| | | var oilVal = Utility.GetParabolaValue(porosity, _parabolaCoef.a, _parabolaCoef.b, _parabolaCoef.c); |
| | | //var testoilVal = Utility.GetParabolaValue(porosity, texCoef.a, texCoef.b, texCoef.c); |
| | | if (porosity == 0) |
| | | { |
| | | initDiff = oilVal - waterVal; |