CtrEditor/test_inp_division_debug.py

251 lines
9.1 KiB
Python

#!/usr/bin/env python3
"""
Test script para verificar el archivo INP problemático directamente en conda tsa_net
Este script prueba el archivo network_20250911_235556.inp que está causando división por cero
"""
import sys
import os
import tempfile
import traceback
from pathlib import Path
def test_inp_file_direct():
"""
Prueba el archivo INP directamente con TSNet para identificar el problema de división por cero
"""
print("=== Test directo del archivo INP problemático ===")
print(f"Python version: {sys.version}")
print(f"Python executable: {sys.executable}")
print(f"Working directory: {os.getcwd()}")
# Verificar que estamos en el entorno correcto
try:
import tsnet
print(f"✓ TSNet importado exitosamente")
print(f"✓ TSNet version: {tsnet.__version__}")
except ImportError as e:
print(f"✗ Error al importar TSNet: {e}")
print("Asegúrate de estar en el entorno conda 'tsa_net'")
return False
# Importar otras dependencias
try:
import wntr
import numpy as np
import pandas as pd
print(f"✓ WNTR version: {wntr.__version__}")
print(f"✓ NumPy version: {np.__version__}")
print(f"✓ Pandas version: {pd.__version__}")
except ImportError as e:
print(f"✗ Error al importar dependencias: {e}")
return False
# Ruta al archivo INP problemático
inp_file_path = (
r"c:\Users\migue\AppData\Local\Temp\TSNet\network_20250911_235556.inp"
)
if not os.path.exists(inp_file_path):
print(f"✗ Archivo INP no encontrado: {inp_file_path}")
return False
print(f"✓ Archivo INP encontrado: {inp_file_path}")
# Leer el contenido del archivo INP para análisis
print("\n=== Análisis del contenido del archivo INP ===")
try:
with open(inp_file_path, "r") as f:
content = f.read()
print(f"Tamaño del archivo: {len(content)} caracteres")
# Buscar secciones potencialmente problemáticas
lines = content.split("\n")
for i, line in enumerate(lines):
line = line.strip()
if line.startswith("PUMP"):
print(f"Línea {i+1} - Bomba encontrada: {line}")
elif "CURVE" in line and not line.startswith(";"):
print(f"Línea {i+1} - Curva encontrada: {line}")
elif line.startswith("Duration") or line.startswith("Hydraulic Timestep"):
print(f"Línea {i+1} - Configuración temporal: {line}")
except Exception as e:
print(f"✗ Error leyendo archivo INP: {e}")
return False
# Test 1: Intentar cargar con WNTR primero (más robusto)
print("\n=== Test 1: Carga con WNTR ===")
try:
import wntr
wn = wntr.network.WaterNetworkModel(inp_file_path)
print(f"✓ WNTR cargó el archivo exitosamente")
print(f" - Junctions: {len(wn.junction_name_list)}")
print(f" - Tanks: {len(wn.tank_name_list)}")
print(f" - Reservoirs: {len(wn.reservoir_name_list)}")
print(f" - Pipes: {len(wn.pipe_name_list)}")
print(f" - Pumps: {len(wn.pump_name_list)}")
print(f" - Valves: {len(wn.valve_name_list)}")
# Verificar configuración temporal
print(f" - Duration: {wn.options.time.duration}")
print(f" - Hydraulic timestep: {wn.options.time.hydraulic_timestep}")
print(f" - Report timestep: {wn.options.time.report_timestep}")
# Verificar bombas y curvas
for pump_name in wn.pump_name_list:
pump = wn.get_link(pump_name)
print(f" - Bomba '{pump_name}': {pump.pump_type}")
if hasattr(pump, "pump_curve_name") and pump.pump_curve_name:
print(f" Curva: {pump.pump_curve_name}")
for curve_name in wn.curve_name_list:
curve = wn.get_curve(curve_name)
print(f" - Curva '{curve_name}': {curve.num_points} puntos")
if curve.num_points > 0:
points = curve.points
print(f" Primer punto: x={points[0][0]}, y={points[0][1]}")
print(f" Último punto: x={points[-1][0]}, y={points[-1][1]}")
except Exception as e:
print(f"✗ Error con WNTR: {e}")
traceback.print_exc()
return False
# Test 2: Simulación WNTR básica
print("\n=== Test 2: Simulación WNTR básica ===")
try:
sim = wntr.sim.EpanetSimulator(wn)
results = sim.run_sim()
print(f"✓ Simulación WNTR exitosa")
print(f" - Nodos con resultados: {len(results.node)}")
print(f" - Enlaces con resultados: {len(results.link)}")
except Exception as e:
print(f"✗ Error en simulación WNTR: {e}")
traceback.print_exc()
return False
# Test 3: Intentar cargar con TSNet
print("\n=== Test 3: Carga con TSNet ===")
try:
# Método 1: TSNet TransientModel directo
tm = tsnet.network.TransientModel(inp_file_path)
print(f"✓ TSNet cargó el modelo transient exitosamente")
# Verificar configuración del modelo
print(f" - Número de nodos: {len(tm.nodes)}")
print(f" - Número de enlaces: {len(tm.links)}")
except Exception as e:
print(f"✗ Error cargando con TSNet TransientModel: {e}")
traceback.print_exc()
# Método 2: Intentar con wntr primero y luego convertir
try:
print(" Intentando método alternativo: WNTR -> TSNet...")
tm = tsnet.network.TransientModel(wn)
print(f"✓ TSNet cargó desde modelo WNTR exitosamente")
except Exception as e2:
print(f"✗ Error con método alternativo: {e2}")
traceback.print_exc()
return False
# Test 4: Configuración para evitar división por cero
print("\n=== Test 4: Configuración anti-división por cero ===")
try:
# Configurar timestep más pequeño para estabilidad numérica
# TSNet requiere configuración específica
print("Configurando parámetros de simulación...")
# Verificar y ajustar configuración temporal
if hasattr(tm, "options"):
if hasattr(tm.options, "time"):
original_duration = tm.options.time.duration
original_timestep = tm.options.time.hydraulic_timestep
print(f" - Duración original: {original_duration}")
print(f" - Timestep original: {original_timestep}")
# Configurar valores más seguros
if original_timestep >= original_duration:
new_timestep = original_duration / 10.0 # 10 pasos mínimo
print(f" - Ajustando timestep a: {new_timestep}")
tm.options.time.hydraulic_timestep = new_timestep
if original_timestep <= 0:
print(f" - Timestep <= 0 detectado, configurando a 0.1")
tm.options.time.hydraulic_timestep = 0.1
if original_duration <= 0:
print(f" - Duración <= 0 detectada, configurando a 1.0")
tm.options.time.duration = 1.0
print("✓ Configuración ajustada para evitar división por cero")
except Exception as e:
print(f"✗ Error configurando parámetros: {e}")
traceback.print_exc()
# Test 5: Simulación TSNet
print("\n=== Test 5: Simulación TSNet ===")
try:
print("Iniciando simulación TSNet...")
# Usar el simulador MOC de TSNet
results = tsnet.simulation.MOCSimulator(
tm, results_obj="results", friction="steady"
)
print(f"✓ Simulación TSNet exitosa!")
print(f"✓ Resultados generados")
return True
except Exception as e:
print(f"✗ Error en simulación TSNet: {e}")
traceback.print_exc()
# Información adicional sobre el error
error_str = str(e).lower()
if "division" in error_str and "zero" in error_str:
print("\n💡 DIAGNÓSTICO: División por cero detectada")
print("Posibles causas:")
print(" 1. Timestep igual o mayor que la duración")
print(" 2. Diámetro de tubería = 0")
print(" 3. Diferencia de elevación = 0 en bombas")
print(" 4. Caudal inicial = 0 en configuración transient")
print(" 5. Curva de bomba con puntos duplicados o inválidos")
elif "matrix" in error_str or "singular" in error_str:
print("\n💡 DIAGNÓSTICO: Matriz singular detectada")
print("Posibles causas:")
print(" 1. Red hidráulica mal conectada")
print(" 2. Nodos aislados")
print(" 3. Configuración de bomba inválida")
return False
def main():
"""Función principal"""
success = test_inp_file_direct()
if success:
print("\n🎉 ¡Todas las pruebas pasaron!")
print("El archivo INP funciona correctamente con TSNet")
else:
print("\n❌ Las pruebas fallaron")
print("El archivo INP tiene problemas que causan división por cero")
return success
if __name__ == "__main__":
success = main()
sys.exit(0 if success else 1)