13 KiB
13 KiB
🔧 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:
[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:
// 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:
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:
// 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
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
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
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:
- Tanques determinan el tipo de fluido que sale según
OutputMode
- Bombas toman el fluido del componente de succión
- Tuberías transportan el fluido desde el componente fuente
- Actualización en tiempo real durante la simulación
Implementación en UpdateControl():
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