Código

Trampas de conversión de unidades en scripts de ingeniería civil

Por qué un script que «converge» puede seguir estando mal por 10⁹ — milímetros mezclados con metros, MPa frente a pascales, y densidad frente a peso específico.

Los scripts civiles fallan más a menudo por unidades mezcladas que por el solver. Los motores de elementos finitos, incluido OpenSees, son adimensionales: devolverán de buen grado un desplazamiento de 1e6 «algo» si E, I y L no comparten un sistema. Las hojas de cálculo esconden el mismo error detrás de un formato de celda.

Este artículo no es una librería completa de unidades. Muestra los modos de falla que aparecen en scripts estructurales y BIM, y una lista corta que los atrapa antes de que confíes en un número.

Requisitos previos

  • Python 3
  • La forma cerrada del voladizo δ = P L³ / (3 E I) (resistencia de materiales elemental)
  • Disposición a imprimir ambos el resultado de unidades mezcladas y el de unidades coherentes en la misma corrida

La trampa: tres números que se ven bien

Supón un voladizo de acero de 4 m, sección cuadrada 100 mm × 100 mm, E = 200 GPa, carga en la punta 1 kN. Un script apresurado suele verse así:

E = 200_000      # "MPa" in the comment, used as if it were N and mm
I = 8.333e6      # mm⁴  (100 mm × 100 mm rectangle)
L = 4.0          # metres  — the silent mix
P = 1_000        # newtons

delta_mixed = P * L**3 / (3.0 * E * I)
print(delta_mixed)

Cada literal es una cantidad real que alguien escribió en un plano. Juntos no son un modelo. L³ está en m³ mientras EI está en N·mm² si te tomaste el comentario en serio — o peor, el comentario se ignora y los valores son solo floats.

Dos sistemas coherentes que deben coincidir

Quédate dentro de un sistema, y luego convierte el desplazamiento al final.

Newton–milímetro (E en N/mm², que es MPa; I en mm⁴; L en mm; P en N; δ en mm):

E_nmm = 200_000.0       # N/mm²
I_nmm = 100.0 * 100.0**3 / 12.0  # mm⁴
L_nmm = 4_000.0         # mm
P_n = 1_000.0           # N
delta_mm = P_n * L_nmm**3 / (3.0 * E_nmm * I_nmm)

Newton–metro (SI):

E_si = 2.0e11           # Pa
I_si = I_nmm * 1e-12    # mm⁴ → m⁴
L_si = 4.0              # m
delta_m = P_n * L_si**3 / (3.0 * E_si * I_si)
delta_mm_from_si = delta_m * 1_000.0
rel = abs(delta_mm - delta_mm_from_si) / abs(delta_mm_from_si)
print(f"δ = {delta_mm:.6f} mm (N-mm system)")
print(f"δ = {delta_mm_from_si:.6f} mm (SI, converted)")
print(f"relative difference = {rel:.3e}")
if rel > 1e-9:
    raise SystemExit("unit systems disagree — stop")

Si los dos sistemas difieren, no tienes un problema de redondeo. Tienes un factor de conversión mal (suele ser 10³, 10⁶, 10⁹ o 10¹² en I).

Una tercera corrida que a propósito deja L en metros con E e I en unidades milimétricas debería diferir del resultado coherente por muchos órdenes de magnitud. Conserva esa llamada rota en un test llamado test_mixed_mm_m_is_detected para que la trampa siga visible.

Otros clásicos civiles

Densidad frente a peso específico

El hormigón alrededor de 2400 kg/m³ no es 2400 kN/m³. El peso específico es γ = ρ g. Usar 9.81 m/s² da unos 23.5 kN/m³. Usar 2400 en un patrón de carga que espera kN/m³ es un error de unos dos órdenes de magnitud. Lo inverso — tratar 25 kN/m³ como kg/m³ en una matriz de masa — es igual de malo.

Los scripts en unidades US customary añaden g = 32.2 ft/s² frente a 9.81 m/s², y kips frente a libras. No conviertas g «a ojo».

Propiedades de sección

I de mm⁴ a m⁴ es un factor de 10⁻¹², no 10⁻⁶. Área mm² a m² es 10⁻⁶. Mezclar esos dos factores es cómo una columna «funciona» en un notebook y pandea en la comprobación real de unidades.

BIM e IFC

Los archivos IFC llevan una unidad de longitud del proyecto. Una cantidad almacenada como float sin aplicar ifcopenshell.util.unit (o el equivalente) no es un metro solo porque tu variable se llame length_m. Ese es el siguiente tutorial.

Solvers sin sistema de unidades

OpenSees, muchos códigos de investigación y una gran fracción de Python interno no te avisarán. Un primer modelo elástico que coincida con P L³ / (3 E I) en un conjunto de unidades documentado es el test de regresión más barato que puedes añadir.

Validación

  1. Ida y vuelta: convierte mm → m → mm en L, I y δ por separado; cada ida y vuelta debería alcanzar error relativo de precisión de máquina a estas escalas.
  2. Orden de magnitud: una barra de acero de 4 m, cuadrada de 100 mm, 1 kN en la punta es una flecha pequeña de milímetros a centímetros, no metros ni nanómetros. Si la impresión es 1e5 o 1e-12, cree en las unidades, no en el solver.
  3. Sistema independiente: N-mm frente a SI deben coincidir después de convertir δ.
  4. No aceptes un factor de 1000 generado por un LLM sin escribir en papel la dimensión de I.

Limitaciones

  • Esta página no reemplaza una librería de unidades (pint, unyt o un enum de proyecto). Esas herramientas siguen fallando si pegas la unidad equivocada en el borde (IFC, CSV, una GUI).
  • Unidades térmicas, unidades estructurales US customary (kip, kip·in²) y kPa geotécnico frente a ksf solo se esbozan. Añade tests para los pares de unidades que tu oficina realmente mezcla.
  • Peso propio, factores de carga y combinaciones de norma no son conversiones de unidades. No los metas en el mismo ayudante.
  • El acuerdo numérico entre dos expresiones Python no sustituye una fórmula de viga citada ni una verificación de solver.

Contexto profesional

Si un paquete de cálculo no declara el sistema de unidades en la misma página que el resultado, los revisores no pueden comprobarlo. Pon el conjunto de unidades en el encabezado del script, en la línea de log junto a cada desplazamiento impreso, y en la nota de verificación que guardas con el modelo.

Referencias

  • BIPM. The International System of Units (SI). Folleto vigente — nombres y prefijos, no una norma estructural.
  • Timoshenko, S. P., y Gere, J. M. Mechanics of Materials. Resultado del voladizo usado como expresión árbitro.
  • Documentación de OpenSeesPy: el motor no convierte unidades por ti. https://openseespydoc.readthedocs.io/