lx
2025-07-22 cb764c0d0bbd76a3fd14c440e7dc0db612bb8244
ErrorAnalysis.Service/ErrorRatioCalc.cs
@@ -10,22 +10,137 @@
{
    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, out double testSpeed, 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 firstErrorPassM = GetFirstErrorRatio(modelID, porosity, sw, speed, depth, out cWOL, out oWOL);
                result.CWOL = cWOL;
                result.OWOL = oWOL;
                result.ErrorRatios.Add(firstErrorPassM);
                if (firstErrorPassM.ErrorRatioValue > targetErrorRatio)
                {
                    var targetPass = Convert.ToInt32(Math.Ceiling(Math.Pow(firstErrorPassM.ErrorRatioValue / targetErrorRatio, 2)));
                    for (int i = 2; i <= targetPass; i++)
                    {
                        result.ErrorRatios.Add(new ErrorRatio { Pass = i, ErrorRatioValue = firstErrorPassM.ErrorRatioValue / Math.Sqrt(i) });
                    }
                }
            }
            else
            {
                var firstTargetErrorRatio = targetErrorRatio * Math.Sqrt(pass);
                List<double[]> cWOL;
                List<double[]> oWOL;
                var firstErrorPass = new ErrorRatio();
                speed = 0.6;
                do
                {
                    firstErrorPass = GetFirstErrorRatio(modelID, porosity, sw, speed, depth, out cWOL, out oWOL);
                    result.CWOL = cWOL;
                    result.OWOL = oWOL;
                    speed -= 0.01;
                } while (firstErrorPass.ErrorRatioValue != 0 && firstErrorPass.ErrorRatioValue > firstTargetErrorRatio);
                result.ErrorRatios.Clear();
                result.ErrorRatios.Add(firstErrorPass);
                for (int i = 2; i <= pass; i++)
                {
                    result.ErrorRatios.Add(new ErrorRatio { Pass = i, ErrorRatioValue = firstErrorPass.ErrorRatioValue / Math.Sqrt(i) });
                }
            }
            testSpeed = speed;
            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 };
            }
        }
    }
}
}