Boundary conditions and loads#
Dirichlet constraints (fixed DOFs) and nodal forces / moments are
the minimum set of boundary conditions every structural analysis
needs. femorph-solver exposes both with MAPDL’s verbs:
d() for Dirichlet and
f() for loads.
DOF labels#
Every node has at most six DOFs, drawn from the enum
femorph_solver.DOFLabel:
Label |
Meaning |
|---|---|
|
Translational displacement along global x / y / z. |
|
Rotation about global x / y / z (beam / shell only). |
The effective DOF set at a node is the union of the DOFs every
adjacent element needs — a SHELL181 node has all six; a SOLID185 node
has three (UX, UY, UZ); a node touched by both sees all
six. Rotational DOFs on a solid-only region are silently dropped.
Loads use femorph_solver.ForceLabel — the parallel enum with
FX / FY / FZ and MX / MY / MZ.
D — Dirichlet constraints#
m.d(1, "UX", 0.0) # pin node 1 in x
m.d(1, "UY", 0.0)
m.d(1, "UZ", 0.0)
m.d(2, "UZ", 1e-3) # prescribe z-displacement at node 2
Model.d() accepts either the raw string or a
DOFLabel member; the two calls below are
identical:
from femorph_solver import DOFLabel
m.d(1, DOFLabel.UX, 0.0)
m.d(1, "UX", 0.0)
Multiple calls with the same (node, label) pair overwrite —
re-pinning a DOF updates its value instead of duplicating.
F — Nodal forces / moments#
m.f(101, "FY", -1000.0) # 1 kN downward at node 101
m.f(101, "MZ", +50.0) # 50 N·m moment about z at node 101
As with d(), either ForceLabel members or raw strings work.
The prescribed= argument#
Every solver entry point also accepts a prescribed dict so you
can bypass the Model’s D records and set constraints directly
from an array-driven script:
K = m.stiffness_matrix()
M = m.mass_matrix()
# Fix DOFs for nodes 1..10 in all three translational directions.
dof_map = m.dof_map()
fixed_dofs = {
i for i, (node, d) in enumerate(dof_map)
if node <= 10 and d < 3 # 0=UX, 1=UY, 2=UZ
}
prescribed = {i: 0.0 for i in fixed_dofs}
result = solve_modal(K, M, prescribed=prescribed, n_modes=10)
Model.solve() / Model.modal_solve() /
Model.transient_solve() merge the Model’s D records into this
dict automatically — use prescribed only when you’re calling
solve_modal / solve_static / solve_transient directly.
Cyclic-symmetry face constraints#
Cyclic-symmetry analyses add a second kind of constraint: paired
low-face / high-face DOFs relate by a phase-dependent rotation.
That’s a first-class argument to
solve_cyclic_modal() rather than a
D record — see Cyclic-symmetry modal analysis.
Limitations (today)#
Only zero-value Dirichlet is lossless. Non-zero
d(node, label, value)constraints work insolve_static()but the modal / cyclic paths require zero-value BCs at prescribed DOFs (they drop the row/column entirely rather than shifting the eigenproblem).No inertia / body-force loads.
ACEL-style gravity isn’t exposed yet; build the equivalent nodal force yourself if you need a body load.No element-face pressure.
SFEpressure loads are parsed from a CDB but not converted into equivalent nodal forces.
See also#
The Model — the
n/e/et/mat/realverbs that bracketd/f.Static analysis — how
K u = Fis partitioned when Dirichlet DOFs are present.