lx
2025-11-24 e5a570db2036a6b155c2ddc289b42bd050b9ad3c
ErrorAnalysis.Service/COMergeCalcService.cs
@@ -1,4 +1,5 @@
using ErrorAnalysis.Repository;
using ErrorAnalysis.Repository.Entity;
using Microsoft.VisualBasic;
using System;
using System.Collections.Generic;
@@ -25,8 +26,9 @@
        //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)
        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);
@@ -36,14 +38,14 @@
            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).Take(cWinLength).Sum() / oilLineValArr.Sum();
            var oilLineOR = oilLineValArr.Skip(_oWinStartIndex).Take(oWinLength).Sum() / oilLineValArr.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 oilLineC = 36d / 160d * oilLineCR * yieldCounting / speed * depth * 0.0762d;
            var oilLineO = 36d / 160d * oilLineOR * yieldCounting / speed * depth * 0.0762d;
            var waterLineCR = waterLineValArr.Skip(_cWinStartIndex).Take(cWinLength).Sum() / waterLineValArr.Sum();
            var waterLineOR = waterLineValArr.Skip(_oWinStartIndex).Take(oWinLength).Sum() / waterLineValArr.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();
            var waterLineC = 36d / 160d * waterLineCR * yieldCounting / speed * depth * 0.0762d;
            var waterLineO = 36d / 160d * waterLineOR * yieldCounting / speed * depth * 0.0762d;
@@ -66,8 +68,9 @@
            return (cRes, oRes);
        }
        private static (double, double) GetNearInterplolateResult(string modelId, double porosity, double sw, double speed, double depth, double yieldCounting)
        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);
@@ -77,13 +80,13 @@
            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).Take(cWinLength).Sum() / oilLineValArr.Sum();
            var oilLineOR = oilLineValArr.Skip(_oWinStartIndex).Take(oWinLength).Sum() / oilLineValArr.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 oilLineC = (36d / 160d) * oilLineCR * yieldCounting / speed * depth * 0.0762d;
            var oilLineO = (36d / 160d) * oilLineOR * yieldCounting / speed * depth * 0.0762d;
            var waterLineCR = waterLineValArr.Skip(_cWinStartIndex).Take(cWinLength).Sum() / waterLineValArr.Sum();
            var waterLineOR = waterLineValArr.Skip(_oWinStartIndex).Take(oWinLength).Sum() / waterLineValArr.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();
            var waterLineC = (36d / 160d) * waterLineCR * yieldCounting / speed * depth * 0.0762d;
            var waterLineO = (36d / 160d) * waterLineOR * yieldCounting / speed * depth * 0.0762d;
@@ -107,7 +110,7 @@
        }
        /// <summary>
        /// 获取远探头C或O值
        /// 获取远探头C或O值(废弃)
        /// </summary>
        /// <param name="connectionString">数据库连接字符串</param>
        /// <param name="modelId">管柱ID</param>
@@ -118,7 +121,7 @@
        /// <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)
        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!");
@@ -126,15 +129,15 @@
            (double, double) result = (0, 0);
            if (porosity % 5 == 0)
            {
                result = GetFarInterplolateResult(modelId, porosity, sw, speed, depth, yieldCounting);
                result = GetFarInterplolateResult(modelId, porosity, sw, speed, depth, yieldCounting, countStart, countEnd);
            }
            else
            {
                var ceilingPorosity = Math.Ceiling(porosity / 5) * 5;
                var ceilingResult = GetFarInterplolateResult(modelId, ceilingPorosity, sw, speed, depth, yieldCounting);
                var ceilingResult = GetFarInterplolateResult(modelId, ceilingPorosity, sw, speed, depth, yieldCounting, countStart, countEnd);
                var floorPorosity = Math.Floor(porosity / 5) * 5;
                var floorResult = GetFarInterplolateResult(modelId, floorPorosity, sw, speed, depth, yieldCounting);
                var floorResult = GetFarInterplolateResult(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);
@@ -143,7 +146,7 @@
        }
        /// <summary>
        /// 获取近探头C或O值
        /// 获取近探头C或O值(废弃)
        /// </summary>
        /// <param name="connectionString">数据库连接字符串</param>
        /// <param name="modelId">管柱ID</param>
@@ -154,7 +157,7 @@
        /// <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)
        public static (double, double) GetNearMergeCOResult(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!");
@@ -162,15 +165,15 @@
            (double, double) result = (0, 0);
            if (porosity % 5 == 0)
            {
                result = GetNearInterplolateResult(modelId, porosity, sw, speed, depth, yieldCounting);
                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);
                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);
                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);
@@ -178,8 +181,127 @@
            return result;
        }
        public static (double, double) GetFarCROR(string modelId, double porosity, double sw)
        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, int countStart, int countEnd)
        {
            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);
@@ -189,11 +311,11 @@
            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).Take(cWinLength).Sum() / oilLineValArr.Sum();
            var oilLineOR = oilLineValArr.Skip(_oWinStartIndex).Take(oWinLength).Sum() / oilLineValArr.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).Take(cWinLength).Sum() / waterLineValArr.Sum();
            var waterLineOR = waterLineValArr.Skip(_oWinStartIndex).Take(oWinLength).Sum() / waterLineValArr.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)
@@ -214,8 +336,9 @@
            return (cRes, oRes);
        }
        public static (double, double) GetNearCROR(string modelId, double porosity, double sw)
        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);
@@ -225,11 +348,11 @@
            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).Take(cWinLength).Sum() / oilLineValArr.Sum();
            var oilLineOR = oilLineValArr.Skip(_oWinStartIndex).Take(oWinLength).Sum() / oilLineValArr.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).Take(cWinLength).Sum() / waterLineValArr.Sum();
            var waterLineOR = waterLineValArr.Skip(_oWinStartIndex).Take(oWinLength).Sum() / waterLineValArr.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)
@@ -250,7 +373,7 @@
            return (crRes, orRes);
        }
        public static (double, double) GetFarCOORResult(string modelId, double porosity, double sw)
        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!");
@@ -258,15 +381,15 @@
            (double, double) result = (0, 0);
            if (porosity % 5 == 0)
            {
                result = GetFarCROR(modelId, porosity, sw);
                result = GetFarCROR(modelId, porosity, sw, countStart, countEnd);
            }
            else
            {
                var ceilingPorosity = Math.Ceiling(porosity / 5) * 5;
                var ceilingResult = GetFarCROR(modelId, ceilingPorosity, sw);
                var ceilingResult = GetFarCROR(modelId, ceilingPorosity, sw, countStart, countEnd);
                var floorPorosity = Math.Floor(porosity / 5) * 5;
                var floorResult = GetFarCROR(modelId, floorPorosity, sw);
                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);
@@ -274,7 +397,7 @@
            return result;
        }
        public static (double, double) GetNearCOORResult(string modelId, double porosity, double sw)
        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!");
@@ -282,15 +405,15 @@
            (double, double) result = (0, 0);
            if (porosity % 5 == 0)
            {
                result = GetNearCROR(modelId, porosity, sw);
                result = GetNearCROR(modelId, porosity, sw, countStart, countEnd);
            }
            else
            {
                var ceilingPorosity = Math.Ceiling(porosity / 5) * 5;
                var ceilingResult = GetNearCROR(modelId, ceilingPorosity, sw);
                var ceilingResult = GetNearCROR(modelId, ceilingPorosity, sw, countStart, countEnd);
                var floorPorosity = Math.Floor(porosity / 5) * 5;
                var floorResult = GetNearCROR(modelId, floorPorosity, sw);
                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);