Please check the build logs for more information.
See Builds for ideas on how to fix a failed build, or Metadata for how to configure docs.rs builds.
If you believe this is docs.rs' fault, open an issue.
rlx-fdm
Force density method (FDM) for pin-jointed structures in RLX, with logic ported from jax_fdm.
Borrowed from jax_fdm
| jax_fdm module | rlx-fdm |
|---|---|
datastructures / FDNetwork |
network::Network |
equilibrium/structures (connectivity, free/fixed split) |
structure::Structure |
equilibrium/models (stiffness_matrix, load_matrix, nodes_equilibrium) |
equilibrium |
equilibrium/fdm (fdm, validation) |
reference::fdm |
equilibrium/states |
state::EquilibriumState |
goals/edge/length, goals/network/loadpath |
goals, objective::Goal |
constraints + constrained_fdm |
constraints, optimize::constrained_fdm |
data/json/*.json |
io::json (feature io) |
equilibrium/sparse + custom VJP |
Planned: rlx-sparse + symmetric solve (K is SPD for physical q) |
constrained_fdm + optimizers |
constrained_fdm (GD or L-BFGS on q, optional L2 on q) |
| Visualization (COMPAS / compas_view2) | Out of scope |
Quick start
use ;
let network = arch_chain;
let eq = fdm.expect;
// Free-node z should sag negative under vertical load.
assert!;
Features
| Feature | Description |
|---|---|
reference (default) |
Dense CPU FDM solve |
io |
Load jax_fdm-style JSON networks |
ir |
Emit Graph with Op::DenseSolve for RLX autodiff |
Sparse + nonlinear
use ;
let mut net = arch_chain;
net.edges_load_uniform;
let opts = nonlinear;
let eq = fdm_with_options?;
sparse:SparseStiffnessCSR + PCG (sparse.rs,solve.rs)nonlinear: fixed-pointx ← K⁻¹ P(x)with edge loads × length (iterative.rs,loads.rs)
Deferred features (implemented)
| jax_fdm | rlx-fdm |
|---|---|
EquilibriumStructureSparse / index_array |
SparseStiffnessFast — O(nnz) assembly |
| Face tributary loads | loads + mesh::MeshStructure |
solver_fixedpoint_implicit |
grad_loss_wrt_q_fixedpoint — unrolled adjoint (edge + face loads, local LCS) |
LBFGSB |
lbfgs::Lbfgs + OptimizerKind::Lbfgs |
| Mesh goals | MeshArea, MeshPlanarity, MeshFaceRectangular, MeshLaplacian |
| PCG adjoint | solve_adjoint_columns + grad_loss_wrt_q_linear_with_solver |
| Support design params | grad_loss_wrt_xyz_fixed_linear (dL/dX_fixed) |
rlx_sparse PCG |
rlx_op (feature rlx-sparse) |
Inverse design
inverse_design: manual GD onqfor one edge-length target.constrained_arch:constrained_fdmwithNetworkLoadpath+EdgeLengthgoals andEdgeQ/ length caps.
use ;
let net = arch_chain;
let goals = vec!;
let constraints = vec!;
let cfg = arch_form_finding; // L-BFGS + linear FDM + sparse PCG
let res = constrained_fdm?;
End-to-end loop (one iteration): equilibrium solve → goal + constraint grads → implicit dL/dq using
EquilibriumModel::pack_xyz_free (no extra fixed-point re-solve). Topology is cached in
OptWorkspace; L-BFGS line search trials only vary q.
Fused MIR (feature ir, fuse_mir): FusedEquilibriumRunner compiles q → x_f once per
topology and reuses it inside constrained_fdm (enabled by default in
OptimizeConfig::arch_form_finding). With feature fuse,
FusedAutodiffFormFinding adds loss + dL/dq through sparse PCG in one compiled graph.
Chain rule: goals_grad_xyz_free + constraint grads → grad_loss_wrt_q (implicit adjoint).
Design parameters, losses, optimizers (jax_fdm 1–5)
DesignParam/DesignVector: all-edgeq, singleEdgeQ, support XYZ, free-node loads.Loss+ErrorKind: squared / RMS / absolute / prediction / log-max aggregation (pass viaOptimizeConfig::lossesor default fromgoals).OptimizerKind::Slsqp/Ipopt: penalty + L-BFGS on boxxwith FD on nonlinear inequalities (Constraint::edge_angle, node tangent / normal).OptimizeConfig::force_dense_with_constraints: dense FDM when constraints are active (jax_fdm policy).
Goals (jax_fdm subset)
| Goal | Description |
|---|---|
NetworkLoadpath |
Total load path energy |
EdgeLength / MeanEdgeLength |
Edge length targets |
EdgeForce / MeanEdgeForce |
Axial force targets |
NodeCoord / MinFreeZ |
Node position / sag |
Residual |
Equilibrium misfit penalty |
MeshArea / MeshPlanarity |
Total face area / mean planarity (needs mesh on Network) |
MeshFaceRectangular / MeshLaplacian |
Quad corner orthogonality / edge spring smoothing |
Mesh I/O (feature io)
use ;
let mut net = from_json_path?;
let mesh = mesh_from_json_str?;
merge_mesh;
let json = to_json_str?;
MIR optimizer hook (feature ir + rlx-sparse)
With features = ["ir", "rlx-sparse"], FdmMirOptimizer::build_equilibrium_graph wires fdm_q → fdm.assemble_csr_values → rlx_sparse.pcg_solve (×3) with param fdm_P. Autodiff through the graph matches the host PCG adjoint in solve_adjoint_columns.
MIR optimizer hook (feature ir)
use ;
use ;
let opt = FdmMirOptimizer ;
let gq = goals_grad_wrt_q?;
build_grad_q_custom_fn emits fdm_dq param; fill with set_grad_q_param before Session::run for host dL/dq in fused graphs.
RLX integration path
- Today: nonlinear fixed-point adjoint (edge loads), full goal library, mesh JSON,
FdmMirOptimizer+constrained_fdm. - Next: IPOPT interface (external); tighter PCG-VJP vs host linear adjoint.
Anderson acceleration: set IterativeConfig::anderson_depth > 0 on nonlinear solves. Implicit adjoint unrolls a full tmax trajectory (eta = 0) so it matches central-difference dL/dq.
License
MIT OR Apache-2.0.