#!/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)