CtrEditor/Documentation/Hidraulic/FluidSystemEnhancements.md

410 lines
13 KiB
Markdown

# 🔧 Mejoras Necesarias al Sistema de Fluidos - CtrEditor
## 🎯 Problemas Identificados
### 1. **Tuberías (osHydPipe)** - Falta Información de Fluidos
**Problema**: Las tuberías no muestran:
- Tipo de fluido que las atraviesa
- Propiedades del fluido (temperatura, Brix, viscosidad)
- Flujo en unidades apropiadas (L/min)
- Color visual basado en el tipo de fluido
**Estado Actual**:
```csharp
[Category("📊 Estado")]
[Description("Flujo actual a través de la tubería en m³/s")]
public double CurrentFlow { get; set; }
[Category("📊 Estado")]
[Description("Pérdida de presión en la tubería en Pa")]
public double PressureDrop { get; set; }
```
**Propiedades Faltantes**:
```csharp
// Propiedades de fluido que deben agregarse
public FluidProperties CurrentFluid { get; set; }
public string CurrentFluidDescription { get; }
public double CurrentFlowLMin { get; } // Flujo en L/min
public SolidColorBrush FluidColor { get; } // Color basado en el fluido
```
### 2. **Bomba (osHydPump)** - Sin Información del Fluido Bombeado
**Problema**: La bomba no muestra:
- Tipo de fluido que está bombeando
- Propiedades del fluido actual
- Efecto de la viscosidad en el rendimiento
- Color visual según el fluido
**Propiedades Faltantes**:
```csharp
public FluidProperties CurrentFluid { get; set; }
public string CurrentFluidDescription { get; }
public double ViscosityEffect { get; } // Factor de eficiencia por viscosidad
public double EffectiveFlow { get; } // Flujo ajustado por viscosidad
```
### 3. **Tanques (osHydTank)** - Gestión Inadecuada de Fluidos Duales
**Problema**:
- Los niveles de fluidos primario/secundario no disminuyen proporcionalmente
- Falta selector de tipo de flujo de salida (Primario/Secundario/Mix)
- El volumen total no se gestiona correctamente
**Funcionalidades Faltantes**:
```csharp
// Enum para tipo de salida
public enum TankOutputMode
{
Primary, // Solo fluido primario
Secondary, // Solo fluido secundario
Mixed // Mezcla según configuración
}
public TankOutputMode OutputMode { get; set; }
public double PrimaryLevelM { get; } // Nivel específico del primario
public double SecondaryLevelM { get; } // Nivel específico del secundario
```
## 🛠️ Implementación Propuesta
### Fase 1: Mejoras en osHydPipe
```csharp
public partial class osHydPipe : osBase, IHydraulicComponent
{
// Propiedades de fluido actuales
private FluidProperties _currentFluid = new FluidProperties(FluidType.Air);
[Category("🧪 Fluido Actual")]
[DisplayName("Tipo de fluido")]
[Description("Tipo de fluido que atraviesa la tubería")]
[ReadOnly(true)]
public FluidType CurrentFluidType
{
get => _currentFluid.Type;
private set
{
if (_currentFluid.Type != value)
{
_currentFluid.Type = value;
OnPropertyChanged();
OnPropertyChanged(nameof(CurrentFluidDescription));
OnPropertyChanged(nameof(FluidColor));
}
}
}
[Category("🧪 Fluido Actual")]
[DisplayName("Descripción")]
[Description("Descripción completa del fluido actual")]
[ReadOnly(true)]
public string CurrentFluidDescription => _currentFluid.Description;
[Category("📊 Estado")]
[DisplayName("Flujo (L/min)")]
[Description("Flujo actual en litros por minuto")]
[ReadOnly(true)]
public double CurrentFlowLMin => CurrentFlow * 60000.0; // Conversión de m³/s a L/min
[JsonIgnore]
public SolidColorBrush FluidColor
{
get
{
var colorHex = _currentFluid.Color;
return new SolidColorBrush((Color)ColorConverter.ConvertFromString(colorHex));
}
}
// Método para actualizar fluido desde componente fuente
public void UpdateFluidFromSource(FluidProperties sourceFluid)
{
if (sourceFluid != null)
{
_currentFluid = sourceFluid.Clone();
OnPropertyChanged(nameof(CurrentFluidType));
OnPropertyChanged(nameof(CurrentFluidDescription));
OnPropertyChanged(nameof(FluidColor));
}
}
}
```
### Fase 2: Mejoras en osHydPump
```csharp
public partial class osHydPump : osBase, IHydraulicComponent
{
private FluidProperties _currentFluid = new FluidProperties(FluidType.Air);
[Category("🧪 Fluido Actual")]
[DisplayName("Tipo de fluido")]
[Description("Tipo de fluido que está bombeando")]
[ReadOnly(true)]
public FluidType CurrentFluidType => _currentFluid.Type;
[Category("🧪 Fluido Actual")]
[DisplayName("Descripción")]
[Description("Descripción del fluido que se está bombeando")]
[ReadOnly(true)]
public string CurrentFluidDescription => _currentFluid.Description;
[Category("📊 Estado Actual")]
[DisplayName("Factor Viscosidad")]
[Description("Factor de eficiencia debido a la viscosidad del fluido")]
[ReadOnly(true)]
public double ViscosityEffect
{
get
{
// Factor basado en viscosidad del fluido vs agua
var waterViscosity = 0.001; // Pa·s
var currentViscosity = _currentFluid.Viscosity;
return Math.Max(0.1, Math.Min(1.0, waterViscosity / currentViscosity));
}
}
[Category("📊 Estado Actual")]
[DisplayName("Flujo Efectivo (L/min)")]
[Description("Flujo real ajustado por viscosidad")]
[ReadOnly(true)]
public double EffectiveFlowLMin => CurrentFlow * 60000.0 * ViscosityEffect;
// Método para actualizar fluido desde tanque de succión
public void UpdateFluidFromSuction()
{
// Buscar tanque o componente conectado en la succión
var suctionComponent = FindSuctionComponent();
if (suctionComponent is osHydTank tank)
{
_currentFluid = tank.CurrentOutputFluid.Clone();
OnPropertyChanged(nameof(CurrentFluidType));
OnPropertyChanged(nameof(CurrentFluidDescription));
OnPropertyChanged(nameof(ViscosityEffect));
OnPropertyChanged(nameof(EffectiveFlowLMin));
}
}
}
```
### Fase 3: Mejoras en osHydTank
```csharp
public partial class osHydTank : osBase, IHydraulicComponent
{
private TankOutputMode _outputMode = TankOutputMode.Primary;
[Category("🔄 Control de Salida")]
[DisplayName("Modo de salida")]
[Description("Selecciona qué fluido sale del tanque")]
public TankOutputMode OutputMode
{
get => _outputMode;
set
{
if (SetProperty(ref _outputMode, value))
{
OnPropertyChanged(nameof(CurrentOutputFluid));
OnPropertyChanged(nameof(CurrentFluidDescription));
InvalidateHydraulicNetwork();
}
}
}
[Category("📊 Niveles Específicos")]
[DisplayName("Nivel Primario (m)")]
[Description("Nivel específico del fluido primario")]
[ReadOnly(true)]
public double PrimaryLevelM
{
get
{
if (CrossSectionalArea <= 0) return 0;
return PrimaryVolumeL / 1000.0 / CrossSectionalArea;
}
}
[Category("📊 Niveles Específicos")]
[DisplayName("Nivel Secundario (m)")]
[Description("Nivel específico del fluido secundario")]
[ReadOnly(true)]
public double SecondaryLevelM
{
get
{
if (CrossSectionalArea <= 0) return 0;
return SecondaryVolumeL / 1000.0 / CrossSectionalArea;
}
}
// Modificación del CurrentOutputFluid para considerar OutputMode
[JsonIgnore]
public override FluidProperties CurrentOutputFluid
{
get
{
return OutputMode switch
{
TankOutputMode.Primary => PrimaryVolumeL > 0 ? _primaryFluid.Clone() : new FluidProperties(FluidType.Air),
TankOutputMode.Secondary => SecondaryVolumeL > 0 ? _secondaryFluid.Clone() : new FluidProperties(FluidType.Air),
TankOutputMode.Mixed => CalculateMixedOutput(),
_ => new FluidProperties(FluidType.Air)
};
}
}
private FluidProperties CalculateMixedOutput()
{
if (PrimaryVolumeL <= 0 && SecondaryVolumeL <= 0)
return new FluidProperties(FluidType.Air);
if (PrimaryVolumeL <= 0)
return _secondaryFluid.Clone();
if (SecondaryVolumeL <= 0)
return _primaryFluid.Clone();
// Calcular ratio de mezcla basado en volúmenes
var totalVolume = PrimaryVolumeL + SecondaryVolumeL;
var mixRatio = SecondaryVolumeL / totalVolume;
return _primaryFluid.MixWith(_secondaryFluid, mixRatio);
}
// Método para actualizar volúmenes proporcionalmente durante el flujo
protected override void UpdateVolumeFromFlow(double deltaTimeSec)
{
var flowOutLMin = OutletFlow;
var flowInLMin = InletFlow;
var netFlowLMin = flowInLMin - flowOutLMin;
var deltaVolumeL = netFlowLMin * deltaTimeSec / 60.0;
if (deltaVolumeL < 0) // Salida neta
{
var outVolumeL = Math.Abs(deltaVolumeL);
// Reducir volúmenes según el modo de salida
switch (OutputMode)
{
case TankOutputMode.Primary:
PrimaryVolumeL = Math.Max(0, PrimaryVolumeL - outVolumeL);
break;
case TankOutputMode.Secondary:
SecondaryVolumeL = Math.Max(0, SecondaryVolumeL - outVolumeL);
break;
case TankOutputMode.Mixed:
// Reducir proporcionalmente
var totalVol = PrimaryVolumeL + SecondaryVolumeL;
if (totalVol > 0)
{
var primaryRatio = PrimaryVolumeL / totalVol;
var secondaryRatio = SecondaryVolumeL / totalVol;
PrimaryVolumeL = Math.Max(0, PrimaryVolumeL - (outVolumeL * primaryRatio));
SecondaryVolumeL = Math.Max(0, SecondaryVolumeL - (outVolumeL * secondaryRatio));
}
break;
}
}
else if (deltaVolumeL > 0) // Entrada neta
{
// El fluido que entra se añade al primario por defecto
// TODO: Implementar lógica para determinar tipo de fluido entrante
PrimaryVolumeL += deltaVolumeL;
}
// Actualizar nivel total
CurrentVolumeL = PrimaryVolumeL + SecondaryVolumeL;
CurrentLevelM = CurrentVolumeL / 1000.0 / Math.Max(0.1, CrossSectionalArea);
}
}
public enum TankOutputMode
{
[Description("Solo fluido primario")]
Primary,
[Description("Solo fluido secundario")]
Secondary,
[Description("Mezcla proporcional")]
Mixed
}
```
## 🔄 Lógica de Propagación de Fluidos
### Algoritmo de Propagación:
1. **Tanques** determinan el tipo de fluido que sale según `OutputMode`
2. **Bombas** toman el fluido del componente de succión
3. **Tuberías** transportan el fluido desde el componente fuente
4. **Actualización en tiempo real** durante la simulación
### Implementación en UpdateControl():
```csharp
public override void UpdateControl(int elapsedMilliseconds)
{
base.UpdateControl(elapsedMilliseconds);
// Actualizar propiedades del fluido
UpdateFluidProperties();
// Actualizar volúmenes (solo tanques)
if (this is osHydTank tank)
{
tank.UpdateVolumeFromFlow(elapsedMilliseconds / 1000.0);
}
}
private void UpdateFluidProperties()
{
// Lógica específica para cada tipo de componente
if (this is osHydPump pump)
{
pump.UpdateFluidFromSuction();
}
else if (this is osHydPipe pipe)
{
pipe.UpdateFluidFromSource();
}
}
```
## 📋 Plan de Implementación
### Prioridad 1: Básico
- [ ] Agregar propiedades de fluido a osHydPipe
- [ ] Agregar propiedades de fluido a osHydPump
- [ ] Implementar TankOutputMode en osHydTank
### Prioridad 2: Funcional
- [ ] Implementar propagación de fluidos
- [ ] Actualización de volúmenes proporcional
- [ ] Colores visuales según tipo de fluido
### Prioridad 3: Avanzado
- [ ] Efectos de viscosidad en bombas
- [ ] Transitorios de mezcla
- [ ] Optimización de rendimiento
## 🧪 Tests de Validación
### Test 1: Propagación Básica
- Tanque con agua → Bomba → Tubería → Tanque
- Verificar que todas las propiedades se propaguen
### Test 2: Cambio de Modo de Salida
- Tanque con fluidos duales
- Cambiar OutputMode y verificar propagación
### Test 3: Efectos de Viscosidad
- Comparar bombeo de agua vs jarabe
- Verificar factor de eficiencia
---
*Documento Técnico - Mejoras Sistema de Fluidos*
*Fecha: Septiembre 2025*