# 🔧 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*