Construir y calcular un modelo en Python

Siete objetos cubren casi cualquier modelo: Node, Material, Section, Member, MemberSet, NodalSupport y NodalLoad. Los ensambla, llama a run_analysis() y lee un conjunto de resultados indexado por hipótesis de carga.

Los objetos principales

Todo se importa desde fers_core. Un modelo es una instancia de FERS que contiene grupos de barras; las cargas cuelgan de las hipótesis y no del modelo, de modo que la misma geometría puede soportar varias hipótesis independientes.

  • Node — un punto X, Y, Z. Y es la vertical hacia arriba. Los nudos llevan su condición de apoyo.
  • Material — módulo de elasticidad, módulo de cortante, densidad y límite elástico. Todo en SI: pascales y kg/m³.
  • Section — área y momentos de inercia, referidos a un material.
  • Member — un elemento viga de dos nudos con seis grados de libertad por nudo, referido a una sección.
  • MemberSet — el grupo que añade al modelo y también la unidad sobre la que actúan las comprobaciones.
  • NodalSupport — la condición de contorno asignada a un nudo.
  • NodalLoad — una fuerza o un momento aplicado a un nudo dentro de una hipótesis de carga.
from fers_core import (
    FERS, Node, Member, Section, Material,
    MemberSet, NodalSupport, NodalLoad
)

Definir geometría, material y sección

Las coordenadas van en metros y las propiedades del material en pascales. La sección de abajo es un IPE 180 tomado de la biblioteca de perfiles de FERS.

Fíjese en el convenio de ejes, porque es con diferencia la causa más habitual de un resultado erróneo: i_z es el eje fuerte e i_y el débil. Una viga que flecta en su plano habitual se gobierna por i_z.

# Nodes (x, y, z coordinates in metres)
node1 = Node(0, 0, 0)
node2 = Node(5, 0, 0)

# Material (Steel S235)
steel = Material(
    name="Steel S235",
    e_mod=210e9,     # Pa
    g_mod=80.769e9,  # Pa
    density=7850,    # kg/m³
    yield_stress=235e6  # Pa
)

# Cross-section (IPE 180), values from the FERS steel section library.
# Axis convention: i_z is the STRONG axis (bending in the local x-y plane),
# i_y the weak axis — see ferscloud.com/conventions
section = Section(
    name="IPE 180",
    material=steel,
    i_y=1.009e-6,  # m⁴ (weak axis)
    i_z=13.17e-6,  # m⁴ (strong axis)
    j=0.0477e-6,   # m⁴
    area=0.00240   # m²
)

Todos los convenios de ejes, signos y unidades están en la página de convenios. El contrato JSON espera ángulos en grados, no en radianes.

Crear la barra, aplicar apoyo y carga

Un NodalSupport() sin argumentos está totalmente empotrado. Para una articulación o un apoyo deslizante, pase displacement_conditions y rotation_conditions explícitos — los ejemplos muestran ambos casos.

Las direcciones de carga son vectores unitarios globales, así que (0, 1, 0) con módulo negativo es una fuerza hacia abajo.

# Create beam element
beam = Member(start_node=node1, end_node=node2, section=section)

# Fixed support at node1
node1.nodal_support = NodalSupport()

# Organise members into a set and add to model
model = FERS()
model.add_member_set(MemberSet(members=[beam]))

# Load case with a −1 kN point load at node2
lc = model.create_load_case(name="Gravity")
NodalLoad(node=node2, load_case=lc, magnitude=-1000, direction=(0, 1, 0))

Lanzar el cálculo y leer resultados

run_analysis() resuelve todas las hipótesis. Los resultados quedan en model.resultsbundle, indexados por nombre de hipótesis, con desplazamientos y reacciones indexados por identificador de nudo como cadena.

Los comentarios muestran la salida real para estas entradas exactas.

model.run_analysis()

results = model.resultsbundle.loadcases["Gravity"]

dy = results.displacement_nodes["2"].dy
Vy = results.reaction_nodes["1"].nodal_forces.fy
Mz = results.reaction_nodes["1"].nodal_forces.mz

print(f"Tip deflection : {dy*1000:.3f} mm")   # -15.065 mm
print(f"Reaction Vy    : {Vy:.1f} N")         # 1000.0 N
print(f"Reaction Mz    : {Mz:.1f} Nm")        # 5000.0 Nm

Comprobación manual: una ménsula de 5 m que flecta respecto a su eje fuerte da δ = PL³ / 3EI_z = 1000·5³ / (3 · 210×10⁹ · 13,17×10⁻⁶) = 15,07 mm, con una reacción de 1 kN y un momento de empotramiento de 5 kN·m por equilibrio. El solver devuelve 15,065 mm.

Más allá de la estática lineal

El mismo objeto de modelo lleva la configuración de los demás tipos de análisis. El análisis de segundo orden (P-Delta), el pandeo lineal con factor de carga crítica, el análisis modal y el sísmico por espectro de respuesta se gobiernan desde los ajustes de análisis, no desde una API distinta.

Las comprobaciones se asocian a grupos de barras y se evalúan tras el cálculo, devolviendo aprovechamientos cláusula a cláusula junto con los valores intermedios que los produjeron: una comprobación se lee como un cálculo manual y no como un número suelto.

Páginas relacionadas

Véase también

Preguntas frecuentes

¿Por qué mis desplazamientos están indexados por una cadena?

Los diccionarios de resultados se indexan por identificador de nudo y de barra como cadena, porque el conjunto de resultados viaja por JSON. Es displacement_nodes["2"], no [2].

¿Para qué sirve un MemberSet?

Es la unidad que añade al modelo y la unidad sobre la que actúan las comprobaciones. Agrupar barras que forman un mismo elemento físico — por ejemplo un pilar empalmado en dos tramos — permite que una longitud de pandeo o una comprobación normativa abarque el conjunto.

¿Cómo modelo una articulación o un apoyo deslizante?

Pase condiciones explícitas a NodalSupport. Una articulación fija las tres traslaciones y deja libres los giros de flexión; retenga además el giro de torsión o la barra tendrá un modo de sólido rígido y el sistema será singular. El ejemplo de viga biapoyada muestra ambos.

¿Qué momento de inercia corresponde al eje fuerte?

i_z. FERS trata el eje z local como eje fuerte de flexión en todo el sistema: solver, comprobaciones y diagramas coinciden. Intercambiar i_y e i_z es el error de modelado más común.

¿Necesito conexión a Internet para calcular?

No. run_analysis() ejecuta el solver compilado dentro de su propio proceso. Solo se usa la red si llama a un punto final en la nube.

¿Puedo obtener la deformada y no solo los valores de extremo?

Sí, y es exacta respecto a la carga en lugar de interpolada entre los desplazamientos de extremo: una viga biempotrada bajo carga uniforme da la flecha real wL⁴/384EI. Actívela en las opciones de análisis.