lx
2025-08-04 e0279fe6db39d1071ef04ad0080b887cb6a0d335
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
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, out double testSpeed, int pass = 0)
        {
            var result = new ErrorRatioResult
            {
                CWOL = new List<double[]>(),
                OWOL = new List<double[]>(),
                ErrorRatios = new List<ErrorRatio>()
            };
 
            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 = 2;
                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;
 
            return result;
 
        }
 
        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"))
                //        {
                //            //if (wolProperty.Name != "WLPu0")
                //            //{
                //            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);
                //            //}
                //            //else
                //            //{
                //            //    var interC = Utility.Interpolate(sw, 100, 0, 0, (double)wolProperty.GetValue(cWolRes));
                //            //    var interO = Utility.Interpolate(sw, 0, 0, 100, (double)wolProperty.GetValue(oWolRes));
                //            //    var interVal = Utility.Interpolate(sw, 0, interC, 100, interO);
                //            //    wolProperty.SetValue(cWolRes, interVal);
                //            //    wolProperty.SetValue(oWolRes, interVal);
                //            //}
 
                //        }
                //    }
                //}
 
                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 ? (cRes - oRes) : (oRes - cRes));
 
                return new ErrorRatio { Pass = 1, ErrorRatioValue = errorRatio };
            }
            catch
            {
                cWOL = null;
                oWOL = null;
                return new ErrorRatio { Pass = 0, ErrorRatioValue = 0 };
            }
        }
    }
}