Merge pull request 'Алгоритм автоопределения операции "Проработка"' (#245) from feature/#29897297-conditioning into dev

Reviewed-on: http://test.digitaldrilling.ru:8080/DDrilling/AsbCloudServer/pulls/245
This commit is contained in:
Никита Фролов 2024-04-02 11:41:48 +05:00
commit 8c9bce8d18
10 changed files with 9606 additions and 8 deletions

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,32 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace AsbCloudDb.Migrations
{
/// <inheritdoc />
public partial class Update_WellOperationCategory_IdConditioning : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.UpdateData(
table: "t_well_operation_category",
keyColumn: "id",
keyValue: 5007,
column: "name",
value: "Проработка");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.UpdateData(
table: "t_well_operation_category",
keyColumn: "id",
keyValue: 5007,
column: "name",
value: "Проработка перед наращиванием");
}
}
}

View File

@ -6484,7 +6484,7 @@ namespace AsbCloudDb.Migrations
IdParent = 4003,
KeyValueName = "dT",
KeyValueUnits = "мин",
Name = "Проработка перед наращиванием"
Name = "Проработка"
},
new
{

View File

@ -154,9 +154,9 @@ namespace AsbCloudDb.Model
/// </summary>
public const int IdFlashingBeforeConnection = 5005;
/// <summary>
/// Проработка перед наращиванием
/// Проработка
/// </summary>
public const int IdDevelopment = 5007;
public const int IdConditioning = 5007;
/// <summary>
/// Шаблонировка во время бурения
/// </summary>
@ -278,7 +278,7 @@ namespace AsbCloudDb.Model
new () {Id = IdStaticSurveying, IdParent = 4002, Name = "Замер ЗТС (запись MWD)", KeyValueName = "dT", KeyValueUnits = "мин" },
new () {Id = IdFlashingBeforeConnection, IdParent = 4003, Name = "Промывка перед наращиванием", KeyValueName = "dT", KeyValueUnits = "мин" },
new () {Id = 5006, IdParent = 4003, Name = "Проработка во время бурения", KeyValueName = "dT", KeyValueUnits = "мин" },
new () {Id = IdDevelopment, IdParent = 4003, Name = "Проработка перед наращиванием", KeyValueName = "dT", KeyValueUnits = "мин" },
new () {Id = IdConditioning, IdParent = 4003, Name = "Проработка", KeyValueName = "dT", KeyValueUnits = "мин" },
new () {Id = IdTemplatingWhileDrilling, IdParent = 4003, Name = "Шаблонировка во время бурения", KeyValueName = "dT", KeyValueUnits = "мин" },
new () {Id = IdTemplating, IdParent = 4003, Name = "Шаблонировка перед наращиванием", KeyValueName = "dT", KeyValueUnits = "мин" },
new () {Id = 5010, IdParent = 4004, Name = "Наращивание", KeyValueName = "dT", KeyValueUnits = "мин" },

View File

@ -29,6 +29,7 @@ public class DetectedOperationService : IDetectedOperationService
new DetectorDrilling(),
new DetectorSlipsTime(),
new DetectorFlashing(),
new DetectorConditioning(),
};
public DetectedOperationService(

View File

@ -0,0 +1,55 @@
using AsbCloudApp.Data.DetectedOperation;
using AsbCloudDb.Model;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors
{
public class DetectorConditioning : DetectorAbstract
{
protected override double CalcValue(DetectableTelemetry[] telemetry, int begin, int end) =>
CalcDeltaMinutes(telemetry, begin, end);
protected override bool DetectBegin(DetectableTelemetry[] telemetry, int position, DetectedOperationDto? previousOperation)
{
var currentPoint = telemetry[position];
if (currentPoint.Pressure < 10)
return false;
if (currentPoint.RotorSpeed <= 8)
return false;
var delta = currentPoint.WellDepth - currentPoint.BitDepth;
if (delta < 0.03d)
return false;
if (currentPoint.BitDepth < 150)
return false;
return true;
}
protected override int DetectEnd(DetectableTelemetry[] telemetry, int position, DetectedOperationDto? previousOperation)
{
var currentPoint = telemetry[position];
if (currentPoint.Pressure < 10)
return IdReasonOfEnd_PressureIsLo;
if (currentPoint.RotorSpeed <=8)
return IdReasonOfEnd_RotorSpeedIsHi;
if ((currentPoint.WellDepth - currentPoint.BitDepth) < 0.03d)
return IdReasonOfEnd_DeltaWellDepthAndBithDepthIsLo;
if (currentPoint.BitDepth < 150)
return IdReasonOfEnd_BithDepthIsLo;
return IdReasonOfEnd_NotDetected;
}
protected override (int IdCategory, IDictionary<string, object> ExtraData) GetSpecificInformation(DetectableTelemetry[] telemetry, int begin, int end)
{
return (WellOperationCategory.IdConditioning, new Dictionary<string, object>());
}
}
}

View File

@ -23,7 +23,7 @@ namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors
return false;
var delta = currentPoint.WellDepth - currentPoint.BitDepth;
if (delta < 0.03d)
if (delta < 0.01d)
return false;
if (currentPoint.RotorSpeed > 8)
@ -47,7 +47,7 @@ namespace AsbCloudInfrastructure.Services.DetectOperations.Detectors
if (currentPoint.Pressure < 10)
return IdReasonOfEnd_PressureIsLo;
if ((currentPoint.WellDepth - currentPoint.BitDepth) < 0.03d)
if ((currentPoint.WellDepth - currentPoint.BitDepth) < 0.01d)
return IdReasonOfEnd_DeltaWellDepthAndBithDepthIsLo;
if (currentPoint.RotorSpeed > 8)
return IdReasonOfEnd_RotorSpeedIsHi;

View File

@ -13,13 +13,13 @@
Признак начала операции =
( давление >= 10 атм ) И
( обороты ротора <= 8 об/мин) И
( расстояние от долота до забоя >= 0.03 м) И
( расстояние от долота до забоя >= 0.01 м) И
( глубина забоя не изменяется) И
( глубина долота >= 150 м);
Признак окончания операции =
( давление < 10 атм ) ИЛИ
( расстояние от долота до забоя < 0.03 м ) ИЛИ
( расстояние от долота до забоя < 0.01 м ) ИЛИ
( обороты ротора > 8 об/мин) ИЛИ
( глубина долота < 150 м);

View File

@ -0,0 +1,29 @@
# Алгоритм определения проработки
## Описание
Проработка операция, во время которой производится подъем или спуск бурильного инструмента с вращением и циркуляцией. Следующей операцией после проработки будет либо шаблонировка (аналогично проработке, но БЕЗ вращением и циркуляции), либо разгрузка инструмента в клинья (снижение веса на крюке) наращивание или отворот бурильного инструмента.
Проработка определяется как время между:
- начало подъема/спуска бурильного инструмента с циркуляцией и вращением;
- разгрузкой инструмента на клинья (остается только вес крюкоблока и ВСП). При этом давление менее 20 атм. ЛИБО
- начало подъема/спуска бурильного инструмента с циркуляцией, НО БЕЗ вращения
Разделяется два вида проработки:
1. перед наращиванием - соотношение глубины забоя и глубины долота <= 30 метров;
2. при спуско-подъёмных операциях (СПО)соотношение глубины забоя - глубины долота > 30 метров.
## Метод определения
Признак начала операции =
( давление >= 10 атм ) И
( обороты ротора > 8 об/мин ) И
( расстояние от долота до забоя >= 0.03м ) И
( глубина долота >= 150м);
Признак окончания операции =
( обороты ротора <= 8 об/мин ) ИЛИ
( давление < 10 атм ) ИЛИ
( расстояние от долота до забоя < 0.03м ) ИЛИ
( глубина долота < 150м);
## Ключевой параметр
Продолжительность операции.

View File

@ -0,0 +1,92 @@
using AsbCloudDb.Model;
using AsbCloudInfrastructure.Services.DetectOperations;
using AsbCloudInfrastructure.Services.DetectOperations.Detectors;
using System;
using Xunit;
namespace AsbCloudWebApi.Tests.Services.DetectedOperations.Detectors;
/// <summary>
/// Тестирование автоопределения операции "Проработка"
/// </summary>
public class DetectorConditioningTests : DetectorFlashing
{
private readonly DetectorConditioning detector = new();
/// <summary>
/// Операция, попадающая под автоопределение операции промывки
/// </summary>
private readonly DetectableTelemetry telemetry = new()
{
Pressure = 21,
RotorSpeed = 9,
WellDepth = 152,
BitDepth = 151,
DateTime = DateTimeOffset.Now,
};
[Fact]
public void DetectOperation_find_startOperation_notFind_endOperation()
{
//arrange
var point0 = telemetry.Copy();
var point1 = telemetry.Copy();
point1.DateTime = point0.DateTime.AddMinutes(3);
var telemetries = new[] { point0, point1 };
//act
var isDetectOperation = detector.TryDetect(0, telemetries, 0, telemetries.Length - 1, null, out var result);
//assert
Assert.True(isDetectOperation);
Assert.NotNull(result);
Assert.Equal(WellOperationCategory.IdConditioning, result.Operation.IdCategory);
Assert.Equal(IdReasonOfEnd_NotDetected, result.Operation.ExtraData["IdReasonOfEnd"]);
}
[Fact]
public void DetectOperation_with_BitDepth_LE_150_is_fail()
{
//arrange
var point0 = telemetry.Copy();
point0.BitDepth = 150;
var point1 = telemetry.Copy();
var telemetries = new[] { point0, point1 };
//act
var isDetectOperation = detector.TryDetect(0, telemetries, 0, telemetries.Length - 1, null, out var result);
//assert
Assert.False(isDetectOperation);
Assert.NotNull(result);
Assert.Equal(WellOperationCategory.IdConditioning, result.Operation.IdCategory);
Assert.Equal(IdReasonOfEnd_NotDetected, result.Operation.ExtraData["IdReasonOfEnd"]);
}
[Fact]
public void DetectOperations_Begin_And_End_by_Pressure_Less_10_is_success()
{
//arrange
var point0 = telemetry.Copy();
var point1 = telemetry.Copy();
point1.Pressure = 9;
var telemetries = new[] { point0, point1 };
//act
var isDetectOperation = detector.TryDetect(0, telemetries, 0, telemetries.Length - 1, null, out var result);
//assert
Assert.False(isDetectOperation);
Assert.NotNull(result);
Assert.Equal(WellOperationCategory.IdConditioning, result.Operation.IdCategory);
Assert.Equal(IdReasonOfEnd_PressureIsLo, result.Operation.ExtraData["IdReasonOfEnd"]);
}
}