251 lines
9.1 KiB
Python
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)
|