lx
2025-07-17 62aecf38e35a8a7fe14a4c8167441ae785cd6681
ErrorAnalysis.Service/ErrorRatioCalc.cs
@@ -10,22 +10,130 @@
{
    public class ErrorRatioCalc
    {
        public static ErrorRatioResult GetErrorRatioResult() { return new ErrorRatioResult(); }
        private static ErrorRatio GetFirstErrorRatio(string connectionString, string modelID, double porosity, double sw, double speed)
        public static ErrorRatioResult GetErrorRatioResult(string modelID, double porosity, double sw, double depth, bool lockSpeed, double speed, double targetErrorRatio, int pass = 0)
        {
            var coWOLRepository = new COWOLRepository(connectionString);
            var cWolRes = coWOLRepository.GetWOL(modelID, 0);
            var oWolRes = coWOLRepository.GetWOL(modelID, 100);
            var result = new ErrorRatioResult
            {
                CWOL = new List<double[]>(),
                OWOL = new List<double[]>(),
                ErrorRatios = new List<ErrorRatio>()
            };
            var mergePDEV = PDEVCalcService.GetMergePDEV(connectionString, modelID, porosity, speed);
            result.COModel = RepositoryInstance.Instance.COModelRepository?.GetCOModel(modelID);
            if (lockSpeed)
            {
                List<double[]> cWOL;
                List<double[]> 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<double[]> cWOL;
                List<double[]> 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;
                }
            }
            var poroFiledName = $"WLPu" + porosity;
            var property = cWolRes.GetType().GetProperty(poroFiledName);
            return result;
            var errorRatio = mergePDEV / ((double)property.GetValue(cWolRes) - (double)property.GetValue(cWolRes));
        }
            return new ErrorRatio { Pass = 1, ErrorRatioValue = errorRatio, Porosity = porosity };
        private static ErrorRatio GetFirstErrorRatio(string modelID, double porosity, double sw, double speed, double depth, out List<double[]> cWOL, out List<double[]> oWOL)
        {
            if (porosity > 40)
                throw new InvalidDataException("Porosity value out of range!");
            cWOL = new List<double[]>();
            oWOL = new List<double[]>();
            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 };
            }
        }
    }
}
}