lx
2025-11-18 e81cbb4c978bec283c58629156c07106aaa46943
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,56 +24,127 @@
        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(string modelId, double porosity, double sw, int readSw, double speed, double depth)
        {
            double result = 0;
            var cResult = RepositoryInstance.Instance.COFarResultRepository?.GetCOFarResult(modelId, (int)porosity, readSw);
            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");
        //const double _coef = 1e8 * 2.54 * 2.54 * 4 * 6 * 2 * 11 * 77 * 0.2 / 0.6;
            var length = readSw == 0 ? _cWinEndIndex - _cWinStartIndex + 1 : _oWinEndIndex - _oWinStartIndex + 1;
            var originC = cArr.Skip(readSw == 0 ? _cWinStartIndex : _oWinStartIndex).Take(length).Sum();
            var coef = originC * 1e8 * 2.54 * 2.54 * 4 * 6 * 2 * 11 * 77 * 0.2 / 0.6 * speed * depth * 0.07;
            result = coef;
            if (sw > 0 && sw < 100)
        private static (double, double) GetFarInterplolateResult(string modelId, double porosity, double sw, double speed, double depth, double yieldCounting)
        {
            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(17).Take(237).Sum();
            var oilLineOR = oilLineValArr.Skip(_oWinStartIndex - 1).Take(oWinLength).Sum() / oilLineValArr.Skip(17).Take(237).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(17).Take(237).Sum();
            var waterLineOR = waterLineValArr.Skip(_oWinStartIndex - 1).Take(oWinLength).Sum() / waterLineValArr.Skip(17).Take(237).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)
            {
                if (readSw == 0)
                    result = Utility.Interpolate(sw, 100, 0, 0, coef);
                else
                    result = Utility.Interpolate(sw, 0, 0, 100, coef);
                cRes = oilLineC;
                oRes = oilLineO;
            }
            return result;
            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(string modelId, double porosity, double sw, int readSw, double speed, double depth)
        private static (double, double) GetNearInterplolateResult(string modelId, double porosity, double sw, double speed, double depth, double yieldCounting)
        {
            double result = 0;
            var cResult = RepositoryInstance.Instance.CONearResultRepository?.GetCONearResult(modelId, (int)porosity, readSw);
            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 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 length = readSw == 0 ? _cWinEndIndex - _cWinStartIndex + 1 : _oWinEndIndex - _oWinStartIndex + 1;
            var originC = cArr.Skip(readSw == 0 ? _cWinStartIndex : _oWinStartIndex).Take(length).Sum();
            var coef = originC * 1e8 * 2.54 * 2.54 * 2 * 6 * 11 * 2 * 77 * 0.2 / 0.6 * speed * depth * 0.07;
            result = coef;
            if (sw > 0 && sw < 100)
            var oilLineCR = oilLineValArr.Skip(_cWinStartIndex - 1).Take(cWinLength).Sum() / oilLineValArr.Skip(17).Take(237).Sum();
            var oilLineOR = oilLineValArr.Skip(_oWinStartIndex - 1).Take(oWinLength).Sum() / oilLineValArr.Skip(17).Take(237).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(17).Take(237).Sum();
            var waterLineOR = waterLineValArr.Skip(_oWinStartIndex - 1).Take(oWinLength).Sum() / waterLineValArr.Skip(17).Take(237).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)
            {
                if (readSw == 0)
                    result = Utility.Interpolate(sw, 100, 0, 0, coef);
                else
                    result = Utility.Interpolate(sw, 0, 0, 100, coef);
                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);
        }
        /// <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)
        {
            if (porosity > 40)
                throw new InvalidDataException("Porosity value out of range!");
            (double, double) result = (0, 0);
            if (porosity % 5 == 0)
            {
                result = GetFarInterplolateResult(modelId, porosity, sw, speed, depth, yieldCounting);
            }
            else
            {
                var ceilingPorosity = Math.Ceiling(porosity / 5) * 5;
                var ceilingResult = GetFarInterplolateResult(modelId, ceilingPorosity, sw, speed, depth, yieldCounting);
                var floorPorosity = Math.Floor(porosity / 5) * 5;
                var floorResult = GetFarInterplolateResult(modelId, floorPorosity, sw, speed, depth, yieldCounting);
                result.Item1 = Utility.Interpolate(porosity, floorPorosity, floorResult.Item1, ceilingPorosity, ceilingResult.Item1);
                result.Item2 = Utility.Interpolate(porosity, floorPorosity, floorResult.Item2, ceilingPorosity, ceilingResult.Item2);
            }
            return result;
        }
        /// <summary>
        /// 获取远探头C或O值
        /// 获取近探头C或O值(废弃)
        /// </summary>
        /// <param name="connectionString">数据库连接字符串</param>
        /// <param name="modelId">管柱ID</param>
@@ -82,68 +155,267 @@
        /// <param name="depth">深度</param>
        /// <returns>碳或氧值</returns>
        /// <exception cref="InvalidDataException">孔隙度超过范围</exception>
        public static double GetFarMergeCOResult(string modelId, double porosity, double sw, int readSw, double speed, double depth)
        public static (double, double) GetNearMergeCOResult(string modelId, double porosity, double sw, double speed, double depth, double yieldCounting)
        {
            if (porosity > 40)
                throw new InvalidDataException("Porosity value out of range!");
            double result = 0;
            (double, double) result = (0, 0);
            if (porosity % 5 == 0)
            {
                result = GetFarInterplolateResult(modelId, porosity, sw, readSw, speed, depth);
                result = GetNearInterplolateResult(modelId, porosity, sw, speed, depth, yieldCounting);
            }
            else
            {
                double ceilingResult = 0;
                var ceilingPorosity = Math.Ceiling(porosity / 5) * 5;
                ceilingResult = GetFarInterplolateResult(modelId, ceilingPorosity, sw, readSw, speed, depth);
                var ceilingResult = GetNearInterplolateResult(modelId, ceilingPorosity, sw, speed, depth, yieldCounting);
                double floorResult = 0;
                var floorPorosity = Math.Floor(porosity / 5) * 5;
                floorResult = GetFarInterplolateResult(modelId, floorPorosity, sw, readSw, speed, depth);
                var floorResult = GetNearInterplolateResult(modelId, floorPorosity, sw, speed, depth, yieldCounting);
                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;
        }
        /// <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 GetNearMergeCOResult(string modelId, double porosity, double sw, int readSw, double speed, double depth)
        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 List<double[]> GetNearSpectrum(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.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, double) GetFarCROR(string modelId, double porosity, double sw)
        {
            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(17).Take(237).Sum();
            var oilLineOR = oilLineValArr.Skip(_oWinStartIndex - 1).Take(oWinLength).Sum() / oilLineValArr.Skip(17).Take(237).Sum();
            var waterLineCR = waterLineValArr.Skip(_cWinStartIndex - 1).Take(cWinLength).Sum() / waterLineValArr.Skip(17).Take(237).Sum();
            var waterLineOR = waterLineValArr.Skip(_oWinStartIndex - 1).Take(oWinLength).Sum() / waterLineValArr.Skip(17).Take(237).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)
        {
            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(17).Take(237).Sum();
            var oilLineOR = oilLineValArr.Skip(_oWinStartIndex - 1).Take(oWinLength).Sum() / oilLineValArr.Skip(17).Take(237).Sum();
            var waterLineCR = waterLineValArr.Skip(_cWinStartIndex - 1).Take(cWinLength).Sum() / waterLineValArr.Skip(17).Take(237).Sum();
            var waterLineOR = waterLineValArr.Skip(_oWinStartIndex - 1).Take(oWinLength).Sum() / waterLineValArr.Skip(17).Take(237).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)
        {
            if (porosity > 40)
                throw new InvalidDataException("Porosity value out of range!");
            double result = 0;
            (double, double) result = (0, 0);
            if (porosity % 5 == 0)
            {
                result = GetNearInterplolateResult(modelId, porosity, sw, readSw, speed, depth);
                result = GetFarCROR(modelId, porosity, sw);
            }
            else
            {
                double ceilingResult = 0;
                var ceilingPorosity = Math.Ceiling(porosity / 5) * 5;
                ceilingResult = GetNearInterplolateResult(modelId, ceilingPorosity, sw, readSw, speed, depth);
                var ceilingResult = GetFarCROR(modelId, ceilingPorosity, sw);
                double floorResult = 0;
                var floorPorosity = Math.Floor(porosity / 5) * 5;
                floorResult = GetNearInterplolateResult(modelId, floorPorosity, sw, readSw, speed, depth);
                var floorResult = GetFarCROR(modelId, floorPorosity, sw);
                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, double) GetNearCOORResult(string modelId, double porosity, double sw)
        {
            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);
            }
            else
            {
                var ceilingPorosity = Math.Ceiling(porosity / 5) * 5;
                var ceilingResult = GetNearCROR(modelId, ceilingPorosity, sw);
                var floorPorosity = Math.Floor(porosity / 5) * 5;
                var floorResult = GetNearCROR(modelId, floorPorosity, sw);
                result.Item1 = Utility.Interpolate(porosity, floorPorosity, floorResult.Item1, ceilingPorosity, ceilingResult.Item1);
                result.Item2 = Utility.Interpolate(porosity, floorPorosity, floorResult.Item2, ceilingPorosity, ceilingResult.Item2);
            }
            return result;
        }
    }
}