232 lines
8.8 KiB
Python
232 lines
8.8 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
Script para arreglar el problema 'Pipe' object has no attribute 'initial_head' en TSNet
|
|
Este error indica incompatibilidad entre TSNet y la versión de WNTR
|
|
"""
|
|
|
|
import sys
|
|
import os
|
|
import traceback
|
|
|
|
|
|
def fix_tsnet_initial_head_problem():
|
|
"""
|
|
Investiga y corrige el problema de 'initial_head' en TSNet
|
|
"""
|
|
print("=== Corrección del problema 'initial_head' en TSNet ===")
|
|
|
|
try:
|
|
import tsnet
|
|
import wntr
|
|
import numpy as np
|
|
|
|
print(f"✓ TSNet version: {tsnet.__version__}")
|
|
print(f"✓ WNTR version: {wntr.__version__}")
|
|
print(f"✓ NumPy version: {np.__version__}")
|
|
except ImportError as e:
|
|
print(f"✗ Error al importar: {e}")
|
|
return False
|
|
|
|
# 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}")
|
|
|
|
try:
|
|
print("\n=== Investigando el problema de initial_head ===")
|
|
|
|
# Cargar modelo con WNTR primero
|
|
wn = wntr.network.WaterNetworkModel(inp_file_path)
|
|
print("✓ WNTR cargó el modelo exitosamente")
|
|
|
|
# Investigar las propiedades de los pipes en WNTR
|
|
print(f"\n=== Análisis de Pipes en WNTR ===")
|
|
for pipe_name in wn.pipe_name_list:
|
|
pipe = wn.get_link(pipe_name)
|
|
print(f"Pipe '{pipe_name}':")
|
|
print(f" - Tipo: {type(pipe)}")
|
|
|
|
# Listar todas las propiedades del pipe
|
|
pipe_attrs = [attr for attr in dir(pipe) if not attr.startswith("_")]
|
|
print(f" - Atributos disponibles: {len(pipe_attrs)}")
|
|
|
|
# Buscar atributos relacionados con 'head'
|
|
head_attrs = [attr for attr in pipe_attrs if "head" in attr.lower()]
|
|
print(f" - Atributos con 'head': {head_attrs}")
|
|
|
|
# Verificar si initial_head existe
|
|
if hasattr(pipe, "initial_head"):
|
|
print(f" - ✓ initial_head existe: {pipe.initial_head}")
|
|
else:
|
|
print(f" - ✗ initial_head NO existe")
|
|
|
|
# Buscar alternativas
|
|
alternatives = []
|
|
for attr in [
|
|
"head",
|
|
"initial_setting",
|
|
"start_node_name",
|
|
"end_node_name",
|
|
]:
|
|
if hasattr(pipe, attr):
|
|
alternatives.append(f"{attr}: {getattr(pipe, attr)}")
|
|
|
|
print(f" - Alternativas posibles: {alternatives}")
|
|
|
|
break # Solo analizar el primer pipe
|
|
|
|
print(f"\n=== Intentando cargar con TSNet ===")
|
|
|
|
# Intentar cargar con TSNet
|
|
tm = tsnet.network.TransientModel(inp_file_path)
|
|
print("✓ TSNet cargó el modelo")
|
|
|
|
# Verificar parámetros temporales (ya corregidos)
|
|
print(f" - simulation_period: {getattr(tm, 'simulation_period', 'N/A')}")
|
|
print(f" - time_step: {getattr(tm, 'time_step', 'N/A')}")
|
|
|
|
# Corregir parámetros si es necesario
|
|
if hasattr(tm, "simulation_period") and tm.simulation_period <= 0:
|
|
tm.simulation_period = 1.0
|
|
print(" - Corregido simulation_period = 1.0")
|
|
|
|
if hasattr(tm, "time_step") and tm.time_step <= 0:
|
|
tm.time_step = 0.1
|
|
print(" - Corregido time_step = 0.1")
|
|
|
|
print(f"\n=== Análisis de Links en TSNet ===")
|
|
if hasattr(tm, "links"):
|
|
print(f" - Número de links: {len(tm.links)}")
|
|
|
|
for i, link in enumerate(tm.links):
|
|
if hasattr(link, "__class__"):
|
|
print(f" - Link {i}: {link.__class__.__name__}")
|
|
|
|
# Verificar si es un Pipe y si tiene initial_head
|
|
if "Pipe" in str(type(link)):
|
|
print(f" * Es un Pipe")
|
|
link_attrs = [
|
|
attr for attr in dir(link) if not attr.startswith("_")
|
|
]
|
|
head_attrs = [
|
|
attr for attr in link_attrs if "head" in attr.lower()
|
|
]
|
|
print(f" * Atributos con 'head': {head_attrs}")
|
|
|
|
if hasattr(link, "initial_head"):
|
|
print(f" * ✓ initial_head existe: {link.initial_head}")
|
|
else:
|
|
print(f" * ✗ initial_head NO existe")
|
|
|
|
# Intentar crear/asignar initial_head
|
|
try:
|
|
# Opción 1: Asignar un valor por defecto
|
|
link.initial_head = 0.0
|
|
print(
|
|
f" * ✓ initial_head asignado: {link.initial_head}"
|
|
)
|
|
except Exception as e:
|
|
print(f" * ✗ No se pudo asignar initial_head: {e}")
|
|
|
|
# Opción 2: Buscar un método alternativo
|
|
if hasattr(link, "start_node") and hasattr(
|
|
link, "end_node"
|
|
):
|
|
try:
|
|
# Calcular head inicial basado en elevación de nodos
|
|
start_elev = getattr(
|
|
link.start_node, "elevation", 0.0
|
|
)
|
|
end_elev = getattr(
|
|
link.end_node, "elevation", 0.0
|
|
)
|
|
avg_elev = (start_elev + end_elev) / 2.0
|
|
link.initial_head = avg_elev
|
|
print(
|
|
f" * ✓ initial_head calculado: {link.initial_head}"
|
|
)
|
|
except Exception as e2:
|
|
print(
|
|
f" * ✗ Cálculo alternativo falló: {e2}"
|
|
)
|
|
|
|
if i >= 2: # Solo analizar los primeros 3 links
|
|
break
|
|
|
|
print(f"\n=== Intentando simulación TSNet corregida ===")
|
|
|
|
# Intentar simulación
|
|
try:
|
|
results = tsnet.simulation.MOCSimulator(
|
|
tm, results_obj="results", friction="steady"
|
|
)
|
|
print("🎉 ¡SIMULACIÓN TSNET EXITOSA!")
|
|
print("✓ El problema de 'initial_head' está resuelto")
|
|
return True
|
|
|
|
except Exception as sim_error:
|
|
print(f"✗ Error en simulación: {sim_error}")
|
|
error_str = str(sim_error).lower()
|
|
|
|
if "initial_head" in error_str:
|
|
print("\n💡 DIAGNÓSTICO ESPECÍFICO:")
|
|
print(
|
|
"1. TSNet requiere que todos los Pipe objects tengan 'initial_head'"
|
|
)
|
|
print("2. La versión actual de WNTR no proporciona este atributo")
|
|
print("3. Necesitamos monkey-patch o pre-procesamiento del modelo")
|
|
|
|
# Intentar monkey-patch
|
|
print("\n=== Intentando Monkey-Patch ===")
|
|
try:
|
|
# Asignar initial_head a todos los pipes
|
|
for link in tm.links:
|
|
if "Pipe" in str(type(link)) and not hasattr(
|
|
link, "initial_head"
|
|
):
|
|
link.initial_head = 0.0 # Valor por defecto
|
|
|
|
print("✓ Monkey-patch aplicado")
|
|
|
|
# Reintentar simulación
|
|
results = tsnet.simulation.MOCSimulator(
|
|
tm, results_obj="results", friction="steady"
|
|
)
|
|
print("🎉 ¡SIMULACIÓN EXITOSA CON MONKEY-PATCH!")
|
|
return True
|
|
|
|
except Exception as patch_error:
|
|
print(f"✗ Monkey-patch falló: {patch_error}")
|
|
|
|
return False
|
|
|
|
except Exception as e:
|
|
print(f"✗ Error: {e}")
|
|
traceback.print_exc()
|
|
return False
|
|
|
|
|
|
def main():
|
|
"""Función principal"""
|
|
success = fix_tsnet_initial_head_problem()
|
|
|
|
if success:
|
|
print("\n🎉 ¡PROBLEMA RESUELTO!")
|
|
print("TSNet puede ejecutar simulaciones sin fallback")
|
|
else:
|
|
print("\n❌ PROBLEMA NO RESUELTO")
|
|
print("Se requiere investigación adicional o actualización de dependencias")
|
|
|
|
return success
|
|
|
|
|
|
if __name__ == "__main__":
|
|
success = main()
|
|
sys.exit(0 if success else 1)
|