lx
2025-11-24 e5a570db2036a6b155c2ddc289b42bd050b9ad3c
ErrorAnalysis.Service/COMergeCalcService.cs
@@ -1,4 +1,6 @@
using ErrorAnalysis.Repository;
using ErrorAnalysis.Repository.Entity;
using Microsoft.VisualBasic;
using System;
using System.Collections.Generic;
using System.Linq;
@@ -22,121 +24,400 @@
        const int _oWinStartIndex = (int)(4.88 / _gg + _offset); // org
        const int _oWinEndIndex = (int)(6.36 / _gg + _offset); // width = 6.36-4.88=1.48
        private static double GetFarInterplolateResult(COFarResultRepository repos, string modelId, double porosity, double sw, double speed, double depth)
        {
        //const double _coef = 1e8 * 2.54 * 2.54 * 4 * 6 * 2 * 11 * 77 * 0.2 / 0.6;
        private static (double, double) GetFarInterplolateResult(string modelId, double porosity, double sw, double speed, double depth, double yieldCounting, int countStart, int countEnd)
        {
            var countLen = countEnd - countStart + 1;
            var cWinLength = _cWinEndIndex - _cWinStartIndex + 1;
            var oWinLength = _oWinEndIndex - _oWinStartIndex + 1;
            var oilLine = RepositoryInstance.Instance.COFarResultRepository?.GetCOFarResult(modelId, (int)porosity, 0);
            var waterLine = RepositoryInstance.Instance.COFarResultRepository?.GetCOFarResult(modelId, (int)porosity, 100);
            if (oilLine == null || waterLine == null)
                throw new InvalidDataException("COFarResult Line is null");
            var oilLineValArr = oilLine.CInelasticSpec.Split(',').Select(v => Convert.ToDouble(v)).ToArray();
            var waterLineValArr = waterLine.CInelasticSpec.Split(',').Select(v => Convert.ToDouble(v)).ToArray();
            var oilLineCR = oilLineValArr.Skip(_cWinStartIndex - 1).Take(cWinLength).Sum() / oilLineValArr.Skip(countStart).Take(countLen).Sum();
            var oilLineOR = oilLineValArr.Skip(_oWinStartIndex - 1).Take(oWinLength).Sum() / oilLineValArr.Skip(countStart).Take(countLen).Sum();
            var oilLineC = 36d / 160d * oilLineCR * yieldCounting / speed * depth * 0.0762d;
            var oilLineO = 36d / 160d * oilLineOR * yieldCounting / speed * depth * 0.0762d;
            var waterLineCR = waterLineValArr.Skip(_cWinStartIndex - 1).Take(cWinLength).Sum() / waterLineValArr.Skip(countStart).Take(countLen).Sum();
            var waterLineOR = waterLineValArr.Skip(_oWinStartIndex - 1).Take(oWinLength).Sum() / waterLineValArr.Skip(countStart).Take(countLen).Sum();
            var waterLineC = 36d / 160d * waterLineCR * yieldCounting / speed * depth * 0.0762d;
            var waterLineO = 36d / 160d * waterLineOR * yieldCounting / speed * depth * 0.0762d;
            double cRes = 0, oRes = 0;
            if (sw == 0)
            {
                cRes = oilLineC;
                oRes = oilLineO;
            }
            else if (sw == 100)
            {
                cRes = waterLineC;
                oRes = waterLineO;
            }
            else if (sw > 0 && sw < 100)
            {
                cRes = Utility.Interpolate(sw, 100, waterLineC, 0, oilLineC);
                oRes = Utility.Interpolate(sw, 0, oilLineO, 100, waterLineO);
            }
            return (cRes, oRes);
        }
        private static double GetNearInterplolateResult(COFarResultRepository repos, string modelId, double porosity, double sw, double speed, double depth)
        private static (double, double) GetNearInterplolateResult(string modelId, double porosity, double sw, double speed, double depth, double yieldCounting, int countStart, int countEnd)
        {
            var countLen = countEnd - countStart + 1;
            var cWinLength = _cWinEndIndex - _cWinStartIndex + 1;
            var oWinLength = _oWinEndIndex - _oWinStartIndex + 1;
            var oilLine = RepositoryInstance.Instance.CONearResultRepository?.GetCONearResult(modelId, (int)porosity, 0);
            var waterLine = RepositoryInstance.Instance.CONearResultRepository?.GetCONearResult(modelId, (int)porosity, 100);
            if (oilLine == null || waterLine == null)
                throw new InvalidDataException("COFarResult Line is null");
            var oilLineValArr = oilLine.CInelasticSpec.Split(',').Select(v => Convert.ToDouble(v)).ToArray();
            var waterLineValArr = waterLine.CInelasticSpec.Split(',').Select(v => Convert.ToDouble(v)).ToArray();
            var oilLineCR = oilLineValArr.Skip(_cWinStartIndex - 1).Take(cWinLength).Sum() / oilLineValArr.Skip(countStart).Take(countLen).Sum();
            var oilLineOR = oilLineValArr.Skip(_oWinStartIndex - 1).Take(oWinLength).Sum() / oilLineValArr.Skip(countStart).Take(countLen).Sum();
            var oilLineC = (36d / 160d) * oilLineCR * yieldCounting / speed * depth * 0.0762d;
            var oilLineO = (36d / 160d) * oilLineOR * yieldCounting / speed * depth * 0.0762d;
            var waterLineCR = waterLineValArr.Skip(_cWinStartIndex - 1).Take(cWinLength).Sum() / waterLineValArr.Skip(countStart).Take(countLen).Sum();
            var waterLineOR = waterLineValArr.Skip(_oWinStartIndex - 1).Take(oWinLength).Sum() / waterLineValArr.Skip(countStart).Take(countLen).Sum();
            var waterLineC = (36d / 160d) * waterLineCR * yieldCounting / speed * depth * 0.0762d;
            var waterLineO = (36d / 160d) * waterLineOR * yieldCounting / speed * depth * 0.0762d;
            double cRes = 0, oRes = 0;
            if (sw == 0)
            {
                cRes = waterLineC;
                oRes = waterLineO;
            }
            else if (sw == 100)
            {
                cRes = waterLineC;
                oRes = waterLineO;
            }
            else if (sw > 0 && sw < 100)
            {
                cRes = Utility.Interpolate(sw, 100, waterLineC, 0, oilLineC);
                oRes = Utility.Interpolate(sw, 0, oilLineO, 100, waterLineO);
            }
            return (cRes, oRes);
        }
        public static double GetFarMergeCResult(string connectionString, string modelId, double porosity, double sw, double speed, double depth)
        /// <summary>
        /// 获取远探头C或O值(废弃)
        /// </summary>
        /// <param name="connectionString">数据库连接字符串</param>
        /// <param name="modelId">管柱ID</param>
        /// <param name="porosity">孔隙度</param>
        /// <param name="sw">含水饱和度</param>
        /// <param name="readSw">读取含水饱和度(0为碳,100为氧)</param>
        /// <param name="speed">测速</param>
        /// <param name="depth">深度</param>
        /// <returns>碳和氧值</returns>
        /// <exception cref="InvalidDataException">孔隙度超过范围</exception>
        public static (double, double) GetFarMergeCOResult(string modelId, double porosity, double sw, double speed, double depth, double yieldCounting, int countStart, int countEnd)
        {
            if (porosity > 40)
                throw new InvalidDataException("Porosity value out of range!");
            var repository = new COFarResultRepository(connectionString);
            double result = 0;
            (double, double) result = (0, 0);
            if (porosity % 5 == 0)
            {
                var cResult = repository.GetCOFarResult(modelId, (int)porosity, 0);
                if (cResult == null)
                    throw new InvalidDataException("COFarResult not found");
                var cArr = cResult.InelasticSpec?.Split(',').Select(v => Convert.ToDouble(v)).ToArray();
                if (cArr == null)
                    throw new InvalidDataException("COFarResult InelasticSpec is null");
                var length = _cWinEndIndex - _cWinStartIndex + 1;
                var originC = cArr.Skip(_cWinStartIndex).Take(length).Sum();
                var coef = originC * 1e8 * 2.54 * 2.54 * 4 * 6 * 2 * 11 * 77 * 0.2 / 0.6 * speed * depth * 0.07;
                if (sw > 0)
                    result = Utility.Interpolate(sw, 100, 0, 0, coef);
                result = GetFarInterplolateResult(modelId, porosity, sw, speed, depth, yieldCounting, countStart, countEnd);
            }
            else
            {
                double ceilingResult = 0;
                var ceilingPorosity = Math.Ceiling(porosity / 5) * 5;
                var ceilingCResult = repository.GetCOFarResult(modelId, (int)ceilingPorosity, 0);
                if (ceilingCResult == null)
                    throw new InvalidDataException("COFarResult not found");
                var ceilingCArr = ceilingCResult.InelasticSpec?.Split(',').Select(v => Convert.ToDouble(v)).ToArray();
                if (ceilingCArr == null)
                    throw new InvalidDataException("COFarResult InelasticSpec is null");
                var ceilingResult = GetFarInterplolateResult(modelId, ceilingPorosity, sw, speed, depth, yieldCounting, countStart, countEnd);
                var ceilingLength = _cWinEndIndex - _cWinStartIndex + 1;
                var ceilingOriginC = ceilingCArr.Skip(_cWinStartIndex).Take(ceilingLength).Sum();
                var ceilingCoef = ceilingOriginC * 1e8 * 2.54 * 2.54 * 4 * 6 * 2 * 11 * 77 * 0.2 / 0.6 * speed;
                if (sw > 0)
                    ceilingResult = Utility.Interpolate(sw, 100, 0, 0, ceilingCoef);
                double floorResult = 0;
                var floorPorosity = Math.Floor(porosity / 5) * 5;
                var floorCResult = repository.GetCOFarResult(modelId, (int)floorPorosity, 0);
                if (floorCResult == null)
                    throw new InvalidDataException("COFarResult not found");
                var floorCArr = floorCResult.InelasticSpec?.Split(',').Select(v => Convert.ToDouble(v)).ToArray();
                if (floorCArr == null)
                    throw new InvalidDataException("COFarResult InelasticSpec is null");
                var floorResult = GetFarInterplolateResult(modelId, floorPorosity, sw, speed, depth, yieldCounting, countStart, countEnd);
                var floorLength = _cWinEndIndex - _cWinStartIndex + 1;
                var floorOriginC = floorCArr.Skip(_cWinStartIndex).Take(floorLength).Sum();
                var floorCoef = floorOriginC * 1e8 * 2.54 * 2.54 * 4 * 6 * 2 * 11 * 77 * 0.2 / 0.6 * speed;
                if (sw > 0)
                    floorResult = Utility.Interpolate(sw, 100, 0, 0, floorCoef);
                result = Utility.Interpolate(porosity, floorPorosity, floorResult, ceilingPorosity, ceilingResult);
                result.Item1 = Utility.Interpolate(porosity, floorPorosity, floorResult.Item1, ceilingPorosity, ceilingResult.Item1);
                result.Item2 = Utility.Interpolate(porosity, floorPorosity, floorResult.Item2, ceilingPorosity, ceilingResult.Item2);
            }
            return result;
        }
        public static double GetFarMergeOResult(string connectionString, string modelId, double porosity, double sw, double speed)
        /// <summary>
        /// 获取近探头C或O值(废弃)
        /// </summary>
        /// <param name="connectionString">数据库连接字符串</param>
        /// <param name="modelId">管柱ID</param>
        /// <param name="porosity">孔隙度</param>
        /// <param name="sw">含水饱和度</param>
        /// <param name="readSw">读取含水饱和度(0为碳,100为氧)</param>
        /// <param name="speed">测速</param>
        /// <param name="depth">深度</param>
        /// <returns>碳或氧值</returns>
        /// <exception cref="InvalidDataException">孔隙度超过范围</exception>
        public static (double, double) GetNearMergeCOResult(string modelId, double porosity, double sw, double speed, double depth, double yieldCounting, int countStart, int countEnd)
        {
            var repository = new COFarResultRepository(connectionString);
            var cResult = repository.GetCOFarResult(modelId, porosity, 100);
            if (cResult == null)
                throw new InvalidDataException("COFarResult not found");
            var cArr = cResult.InelasticSpec?.Split(',').Select(v => Convert.ToDouble(v)).ToArray();
            if (cArr == null)
                throw new InvalidDataException("COFarResult InelasticSpec is null");
            if (porosity > 40)
                throw new InvalidDataException("Porosity value out of range!");
            var length = _oWinEndIndex - _oWinStartIndex + 1;
            var result = cArr.Skip(_oWinStartIndex).Take(length).Sum();
            (double, double) result = (0, 0);
            if (porosity % 5 == 0)
            {
                result = GetNearInterplolateResult(modelId, porosity, sw, speed, depth, yieldCounting, countStart, countEnd);
            }
            else
            {
                var ceilingPorosity = Math.Ceiling(porosity / 5) * 5;
                var ceilingResult = GetNearInterplolateResult(modelId, ceilingPorosity, sw, speed, depth, yieldCounting, countStart, countEnd);
                var floorPorosity = Math.Floor(porosity / 5) * 5;
                var floorResult = GetNearInterplolateResult(modelId, floorPorosity, sw, speed, depth, yieldCounting, countStart, countEnd);
                result.Item1 = Utility.Interpolate(porosity, floorPorosity, floorResult.Item1, ceilingPorosity, ceilingResult.Item1);
                result.Item2 = Utility.Interpolate(porosity, floorPorosity, floorResult.Item2, ceilingPorosity, ceilingResult.Item2);
            }
            return result;
        }
        public static List<double[]> GetFarSpectrum(string modelId, double porosity, double sw)
        {
            var result = new List<double[]>();
            if (porosity > 40)
                throw new InvalidDataException("Porosity value out of range!");
            double[] oilLineSpec;
            double[] waterLineSpec;
            if (porosity % 5 == 0)
            {
                oilLineSpec = RepositoryInstance.Instance.COFarResultRepository.GetCOFarResult(modelId, (int)porosity, 0).CInelasticSpec.Split(',').Select(v => Convert.ToDouble(v)).ToArray();
                waterLineSpec = RepositoryInstance.Instance.COFarResultRepository.GetCOFarResult(modelId, (int)porosity, 100).CInelasticSpec.Split(',').Select(v => Convert.ToDouble(v)).ToArray();
            }
            else
            {
                var ceilingPorosity = Math.Ceiling(porosity / 5) * 5;
                double[] ceilingOilLineSpec = RepositoryInstance.Instance.COFarResultRepository.GetCOFarResult(modelId, (int)ceilingPorosity, 0).CInelasticSpec.Split(',').Select(v => Convert.ToDouble(v)).ToArray();
                double[] ceilingWaterLineSpec = RepositoryInstance.Instance.COFarResultRepository.GetCOFarResult(modelId, (int)ceilingPorosity, 100).CInelasticSpec.Split(',').Select(v => Convert.ToDouble(v)).ToArray();
                var floorPorosity = Math.Floor(porosity / 5) * 5;
                double[] floorOilLineSpec = RepositoryInstance.Instance.COFarResultRepository.GetCOFarResult(modelId, (int)floorPorosity, 0).CInelasticSpec.Split(',').Select(v => Convert.ToDouble(v)).ToArray();
                double[] floorWaterLineSpec = RepositoryInstance.Instance.COFarResultRepository.GetCOFarResult(modelId, (int)floorPorosity, 100).CInelasticSpec.Split(',').Select(v => Convert.ToDouble(v)).ToArray();
                oilLineSpec = ceilingOilLineSpec;
                waterLineSpec = ceilingWaterLineSpec;
                for (int i = 0; i < ceilingOilLineSpec.Length; i++)
                {
                    oilLineSpec[i] = Utility.Interpolate(porosity, floorPorosity, floorOilLineSpec[i], ceilingPorosity, ceilingOilLineSpec[i]);
                    waterLineSpec[i] = Utility.Interpolate(porosity, floorPorosity, floorWaterLineSpec[i], ceilingPorosity, ceilingWaterLineSpec[i]);
                }
            }
            if (sw == 0)
            {
                for (int i = 0; i < oilLineSpec.Length; i++)
                {
                    result.Add([i, oilLineSpec[i]]);
                }
            }
            else if (sw == 100)
            {
                for (int i = 0; i < waterLineSpec.Length; i++)
                {
                    result.Add([i, waterLineSpec[i]]);
                }
            }
            else if (sw > 0 && sw < 100)
            {
                for (int i = 0; i < waterLineSpec.Length; i++)
                {
                    var val = Utility.Interpolate(sw, 0, oilLineSpec[i], 100, waterLineSpec[i]);
                    result.Add([i, val]);
                }
            }
            return result;
        }
        public static double GetNearMergeCResult(string connectionString, string modelId, double porosity, double sw, double speed)
        public static List<double[]> GetNearSpectrum(string modelId, double porosity, double sw)
        {
            var repository = new CONearResultRepository(connectionString);
            var cResult = repository.GetCONearResult(modelId, porosity, 0);
            if (cResult == null)
                throw new InvalidDataException("CONearResult not found");
            var cArr = cResult.InelasticSpec?.Split(',').Select(v => Convert.ToDouble(v)).ToArray();
            if (cArr == null)
                throw new InvalidDataException("CONearResult InelasticSpec is null");
            var result = new List<double[]>();
            if (porosity > 40)
                throw new InvalidDataException("Porosity value out of range!");
            var length = _cWinEndIndex - _cWinStartIndex + 1;
            var result = cArr.Skip(_cWinStartIndex).Take(length).Sum();
            double[] oilLineSpec;
            double[] waterLineSpec;
            if (porosity % 5 == 0)
            {
                oilLineSpec = RepositoryInstance.Instance.CONearResultRepository.GetCONearResult(modelId, (int)porosity, 0).CInelasticSpec.Split(',').Select(v => Convert.ToDouble(v)).ToArray();
                waterLineSpec = RepositoryInstance.Instance.CONearResultRepository.GetCONearResult(modelId, (int)porosity, 100).CInelasticSpec.Split(',').Select(v => Convert.ToDouble(v)).ToArray();
            }
            else
            {
                var ceilingPorosity = Math.Ceiling(porosity / 5) * 5;
                double[] ceilingOilLineSpec = RepositoryInstance.Instance.CONearResultRepository.GetCONearResult(modelId, (int)ceilingPorosity, 0).CInelasticSpec.Split(',').Select(v => Convert.ToDouble(v)).ToArray();
                double[] ceilingWaterLineSpec = RepositoryInstance.Instance.CONearResultRepository.GetCONearResult(modelId, (int)ceilingPorosity, 100).CInelasticSpec.Split(',').Select(v => Convert.ToDouble(v)).ToArray();
                var floorPorosity = Math.Floor(porosity / 5) * 5;
                double[] floorOilLineSpec = RepositoryInstance.Instance.CONearResultRepository.GetCONearResult(modelId, (int)floorPorosity, 0).CInelasticSpec.Split(',').Select(v => Convert.ToDouble(v)).ToArray();
                double[] floorWaterLineSpec = RepositoryInstance.Instance.CONearResultRepository.GetCONearResult(modelId, (int)floorPorosity, 100).CInelasticSpec.Split(',').Select(v => Convert.ToDouble(v)).ToArray();
                oilLineSpec = ceilingOilLineSpec;
                waterLineSpec = ceilingWaterLineSpec;
                for (int i = 0; i < ceilingOilLineSpec.Length; i++)
                {
                    oilLineSpec[i] = Utility.Interpolate(porosity, floorPorosity, floorOilLineSpec[i], ceilingPorosity, ceilingOilLineSpec[i]);
                    waterLineSpec[i] = Utility.Interpolate(porosity, floorPorosity, floorWaterLineSpec[i], ceilingPorosity, ceilingWaterLineSpec[i]);
                }
            }
            if (sw == 0)
            {
                for (int i = 0; i < oilLineSpec.Length; i++)
                {
                    result.Add([i, oilLineSpec[i]]);
                }
            }
            else if (sw == 100)
            {
                for (int i = 0; i < waterLineSpec.Length; i++)
                {
                    result.Add([i, waterLineSpec[i]]);
                }
            }
            else if (sw > 0 && sw < 100)
            {
                for (int i = 0; i < waterLineSpec.Length; i++)
                {
                    var val = Utility.Interpolate(sw, 0, oilLineSpec[i], 100, waterLineSpec[i]);
                    result.Add([i, val]);
                }
            }
            return result;
        }
        public static double GetNearMergeOResult(string connectionString, string modelId, double porosity, double sw, double speed)
        public static (double, double) GetFarCROR(string modelId, double porosity, double sw, int countStart, int countEnd)
        {
            var repository = new CONearResultRepository(connectionString);
            var cResult = repository.GetCONearResult(modelId, porosity, 100);
            if (cResult == null)
                throw new InvalidDataException("CONearResult not found");
            var cArr = cResult.InelasticSpec?.Split(',').Select(v => Convert.ToDouble(v)).ToArray();
            if (cArr == null)
                throw new InvalidDataException("CONearResult InelasticSpec is null");
            int countLen = countEnd - countStart + 1;
            var cWinLength = _cWinEndIndex - _cWinStartIndex + 1;
            var oWinLength = _oWinEndIndex - _oWinStartIndex + 1;
            var oilLine = RepositoryInstance.Instance.COFarResultRepository?.GetCOFarResult(modelId, (int)porosity, 0);
            var waterLine = RepositoryInstance.Instance.COFarResultRepository?.GetCOFarResult(modelId, (int)porosity, 100);
            if (oilLine == null || waterLine == null)
                throw new InvalidDataException("COFarResult Line is null");
            var oilLineValArr = oilLine.CInelasticSpec.Split(',').Select(v => Convert.ToDouble(v)).ToArray();
            var waterLineValArr = waterLine.CInelasticSpec.Split(',').Select(v => Convert.ToDouble(v)).ToArray();
            var length = _oWinEndIndex - _oWinStartIndex + 1;
            var result = cArr.Skip(_oWinStartIndex).Take(length).Sum();
            var oilLineCR = oilLineValArr.Skip(_cWinStartIndex - 1).Take(cWinLength).Sum() / oilLineValArr.Skip(countStart).Take(countLen).Sum();
            var oilLineOR = oilLineValArr.Skip(_oWinStartIndex - 1).Take(oWinLength).Sum() / oilLineValArr.Skip(countStart).Take(countLen).Sum();
            var waterLineCR = waterLineValArr.Skip(_cWinStartIndex - 1).Take(cWinLength).Sum() / waterLineValArr.Skip(countStart).Take(countLen).Sum();
            var waterLineOR = waterLineValArr.Skip(_oWinStartIndex - 1).Take(oWinLength).Sum() / waterLineValArr.Skip(countStart).Take(countLen).Sum();
            double cRes = 0, oRes = 0;
            if (sw == 0)
            {
                cRes = oilLineCR;
                oRes = oilLineOR;
            }
            else if (sw == 100)
            {
                cRes = waterLineCR;
                oRes = waterLineOR;
            }
            else if (sw > 0 && sw < 100)
            {
                cRes = Utility.Interpolate(sw, 100, waterLineCR, 0, oilLineCR);
                oRes = Utility.Interpolate(sw, 0, oilLineOR, 100, waterLineOR);
            }
            return (cRes, oRes);
        }
        public static (double, double) GetNearCROR(string modelId, double porosity, double sw, int countStart, int countEnd)
        {
            int countLen = countEnd - countStart + 1;
            var cWinLength = _cWinEndIndex - _cWinStartIndex + 1;
            var oWinLength = _oWinEndIndex - _oWinStartIndex + 1;
            var oilLine = RepositoryInstance.Instance.CONearResultRepository?.GetCONearResult(modelId, (int)porosity, 0);
            var waterLine = RepositoryInstance.Instance.CONearResultRepository?.GetCONearResult(modelId, (int)porosity, 100);
            if (oilLine == null || waterLine == null)
                throw new InvalidDataException("COFarResult Line is null");
            var oilLineValArr = oilLine.CInelasticSpec.Split(',').Select(v => Convert.ToDouble(v)).ToArray();
            var waterLineValArr = waterLine.CInelasticSpec.Split(',').Select(v => Convert.ToDouble(v)).ToArray();
            var oilLineCR = oilLineValArr.Skip(_cWinStartIndex - 1).Take(cWinLength).Sum() / oilLineValArr.Skip(countStart).Take(countLen).Sum();
            var oilLineOR = oilLineValArr.Skip(_oWinStartIndex - 1).Take(oWinLength).Sum() / oilLineValArr.Skip(countStart).Take(countLen).Sum();
            var waterLineCR = waterLineValArr.Skip(_cWinStartIndex - 1).Take(cWinLength).Sum() / waterLineValArr.Skip(countStart).Take(countLen).Sum();
            var waterLineOR = waterLineValArr.Skip(_oWinStartIndex - 1).Take(oWinLength).Sum() / waterLineValArr.Skip(countStart).Take(countLen).Sum();
            double crRes = 0, orRes = 0;
            if (sw == 0)
            {
                crRes = oilLineCR;
                orRes = oilLineOR;
            }
            else if (sw == 100)
            {
                crRes = waterLineCR;
                orRes = waterLineOR;
            }
            else if (sw > 0 && sw < 100)
            {
                crRes = Utility.Interpolate(sw, 100, waterLineCR, 0, oilLineCR);
                orRes = Utility.Interpolate(sw, 0, oilLineOR, 100, waterLineOR);
            }
            return (crRes, orRes);
        }
        public static (double, double) GetFarCOORResult(string modelId, double porosity, double sw, int countStart, int countEnd)
        {
            if (porosity > 40)
                throw new InvalidDataException("Porosity value out of range!");
            (double, double) result = (0, 0);
            if (porosity % 5 == 0)
            {
                result = GetFarCROR(modelId, porosity, sw, countStart, countEnd);
            }
            else
            {
                var ceilingPorosity = Math.Ceiling(porosity / 5) * 5;
                var ceilingResult = GetFarCROR(modelId, ceilingPorosity, sw, countStart, countEnd);
                var floorPorosity = Math.Floor(porosity / 5) * 5;
                var floorResult = GetFarCROR(modelId, floorPorosity, sw, countStart, countEnd);
                result.Item1 = Utility.Interpolate(porosity, floorPorosity, floorResult.Item1, ceilingPorosity, ceilingResult.Item1);
                result.Item2 = Utility.Interpolate(porosity, floorPorosity, floorResult.Item2, ceilingPorosity, ceilingResult.Item2);
            }
            return result;
        }
        public static (double, double) GetNearCOORResult(string modelId, double porosity, double sw, int countStart, int countEnd)
        {
            if (porosity > 40)
                throw new InvalidDataException("Porosity value out of range!");
            (double, double) result = (0, 0);
            if (porosity % 5 == 0)
            {
                result = GetNearCROR(modelId, porosity, sw, countStart, countEnd);
            }
            else
            {
                var ceilingPorosity = Math.Ceiling(porosity / 5) * 5;
                var ceilingResult = GetNearCROR(modelId, ceilingPorosity, sw, countStart, countEnd);
                var floorPorosity = Math.Floor(porosity / 5) * 5;
                var floorResult = GetNearCROR(modelId, floorPorosity, sw, countStart, countEnd);
                result.Item1 = Utility.Interpolate(porosity, floorPorosity, floorResult.Item1, ceilingPorosity, ceilingResult.Item1);
                result.Item2 = Utility.Interpolate(porosity, floorPorosity, floorResult.Item2, ceilingPorosity, ceilingResult.Item2);
            }
            return result;
        }