API¶
The public Quivira interface provides symbolic matrix utilities and helpers
for assembling constrained Lagrangian equations of motion. These functions
work directly with heyoka.expression objects and NumPy arrays.
- quivira.create_block_diagonal(blocks)¶
Create a block-diagonal matrix from square symbolic arrays.
- Parameters:
blocks (
list) – A sequence of two-dimensional square arrays to place along the main diagonal.- Raises:
ValueError – If a block is not a two-dimensional square array.
Notes
Entries outside the diagonal blocks are filled with
heyoka.expressionobjects representing zero, rather than Python integer zeros. An empty sequence returns an empty(0, 0)object array.- Returns:
An object array containing the block-diagonal matrix.
- Return type:
- quivira.gaussian_elimination(S, b)¶
Solve a symbolic linear system using sparsity-aware Gaussian elimination.
Solves the linear system
\[S x = b\]by first computing an LU factorization of the coefficient matrix and then performing forward and backward substitution.
The factorization is computed for each call. To solve multiple systems with the same coefficient matrix more efficiently, use
gaussian_factorize()once and reuse the result withgaussian_solve_factored().- Parameters:
S (
numpy.ndarrayor sequence) – Square coefficient matrix containing symbolic or numeric entries, with shape(n, n).b (
numpy.ndarrayor sequence) – Right-hand side vector containing symbolic or numeric entries. Must contain exactlynelements.
- Raises:
ValueError – If
Sis not square orbhas an incompatible size.ZeroDivisionError – If a structurally zero pivot is encountered during factorization.
Notes
The underlying factorization skips known zero entries to reduce unnecessary symbolic operations. No row pivoting is performed, so the solver may fail for invertible matrices with zero pivots.
The input matrix and right-hand side are not modified.
- Returns:
Symbolic solution vector with shape
(n, 1).- Return type:
- quivira.identity(x)¶
Return the input unchanged.
This utility is useful as a no-op placeholder when a function is needed but the caller wants to preserve the original value.
- Parameters:
x – Any Python object to return unchanged.
- Returns:
The original object passed in.
- quivira.invert_matrix(matrix)¶
Return the inverse of a square matrix using Gaussian elimination.
The inverse is defined by
\[A A^{-1} = I,\]where \(I\) is the identity matrix. The implementation solves the linear systems
\[A x_j = e_j\]for each basis vector \(e_j\) and stores the resulting columns in the inverse matrix.
- Parameters:
matrix (
numpy.ndarrayor sequence) – Square matrix to invert.- Raises:
ValueError – If
matrixis not a square two-dimensional array.
Notes
This routine is intended for the symbolic matrices used throughout Quivira. It relies on the existing Gaussian elimination routine and is therefore compatible with
heyoka.expressionentries.- Returns:
- Inverse matrix with the same object dtype as the
input matrix.
- Return type:
Constrained Lagrangian mechanics¶
- quivira.build_mass_matrix(lagrangian, qd)¶
Return the symbolic mass matrix for a Lagrangian.
The mass matrix is defined by
\[M_{ij} = \frac{\partial^2 \mathcal L}{\partial \dot q_i \partial \dot q_j}.\]- Parameters:
lagrangian (
heyoka.expression) – Scalar Lagrangian \(\mathcal L(q, \dot q)\).qd (sequence) – Generalized velocities in the same ordering as the model coordinates.
- Returns:
Symbolic mass matrix with shape
[n, n].- Return type:
- quivira.build_Jdqd(J, q, qd)¶
Return the vector \(\dot J \dot q\) from the Jacobian and state rate.
The derivative of the constraint Jacobian along the trajectory is
\[\dot J = \sum_i \frac{\partial J}{\partial q_i} \dot q_i,\]so the product entering the constrained-acceleration equation is
\[\dot J \dot q = \sum_i \frac{\partial J}{\partial q_i} \dot q_i \dot q.\]- Parameters:
J (
numpy.ndarrayor sequence) – Constraint Jacobian \(J(q)\).q (sequence) – Generalized coordinates.
qd (sequence) – Generalized velocities \(\dot q\).
- Returns:
The vector \(\dot J \dot q\).
- Return type:
- quivira.build_constraint_jacobian(F, q)¶
Return the constraint Jacobian \(J = \partial F / \partial q\).
The algebraic constraints are expressed as a vector \(F(q) = 0\). The Jacobian maps coordinate perturbations into constraint-space variations and is used to enforce the acceleration-level constraint \(J \ddot{q} + \dot{J} \dot{q} = 0\).
- Parameters:
F (sequence) – Constraint residuals \(F(q)\).
q (sequence) – Generalized coordinates.
- Returns:
Jacobian matrix with shape
[m, n].- Return type:
- quivira.find_constrained_accelerations(qdd_free, J, M, Jdqd, Q_nc=None, *, return_W=False)¶
Return constrained accelerations and the constraint multipliers.
The constrained acceleration is
\[\ddot{q} = \ddot{q}_{\mathrm{free}} - M^{-1} J^T W^{-1} \left(J \ddot{q}_{\mathrm{free}} + \dot{J} \dot{q}\right),\]where
\[W = J M^{-1} J^T.\]this is simplified to: The constrained acceleration is
\[\ddot{q} = \ddot{q}_{\mathrm{applied}} + G \lambda,\]where
\[G = M^{-1} J^T, \qquad W = JG,\]and
\[W \lambda = -(J \ddot{q}_{\mathrm{applied}} + \dot{J}\dot{q}).\]The matrix G is calculated by solving M G = J^T, avoiding the explicit inversion of M. The mass matrix is factorized only once, and the factorization is reused for all right-hand sides.
- Parameters:
qdd_free (sequence) – Free acceleration vector.
J (
numpy.ndarrayor sequence) – Constraint Jacobian \(J\).M (
numpy.ndarrayor sequence) – Mass matrix \(M\).Jdqd (sequence) – Product \(\dot J \dot q\).
Q_nc (
numpy.ndarrayor sequence, optional) – Generalized applied forces, in the same ordering as q. Entries may be symbolic functions of q, qd, and time. Defaults to None.return_W (
bool, optional) – Whether to also return the Delassus matrix \(W\). Default is False.
- Returns:
By default, a pair
(qdd, lambda_mult)containing the constrained acceleration vector and Lagrange multiplier vector. Ifreturn_Wis True, a triple(qdd, lambda_mult, W)is returned; \(W = J M^{-1} J^T\) is the Delassus matrix. The multiplier entries follow the constraint-row ordering in \(J\).- Return type:
- quivira.lagrange_eom(lagrangian, F, q, qd, Q_nc=None, *, return_multipliers=False, return_W=False)¶
Assemble the first-order ODE system for the constrained dynamics.
This helper forms the free-acceleration terms from the Lagrangian, evaluates the constraint Jacobian and its time derivative, and then returns the equivalent first-order system that can be passed to a numerical integrator.
- Parameters:
lagrangian (
heyoka.expression) – Scalar Lagrangian.F (sequence) – Constraint residuals \(F(q)\).
q (sequence) – Generalized coordinates.
qd (sequence) – Generalized velocities.
Q_nc (sequence, optional) – Generalized applied forces, in the same ordering as q. Entries may be symbolic functions of q, qd, and time. Defaults to None.
return_multipliers (
bool, optional) – Whether to also return the Lagrange multiplier vector. Default is False.return_W (
bool, optional) – Whether to also return the Delassus matrix \(W = J M^{-1} J^T\). Default is False.
- Returns:
The ODE system as pairs
(state_var, rhs_expr). If both options are False, this list is returned directly. If onlyreturn_multipliersis True, returns(ode_system, lambda_mult); if onlyreturn_Wis True, returns(ode_system, W); if both are True, returns(ode_system, lambda_mult, W). The multiplier entries follow the constraint-row ordering in \(J\).- Return type:
Bar joint model class¶
- class quivira.bar_joint_model(tolerance=1e-10)¶
Bases:
objectAssembly of articulated bars with joints, supports, and external loads.
The model collects the geometric and force data needed to generate a Lagrangian formulation and the constraint equations for the system.
- add_bar(length, mass)¶
Append a new bar to the assembly.
- add_bar_at_attitude(x0, y0, theta0, length, mass)¶
Append a bar and assign its initial attitude in one step.
- add_bar_from_point_pair(start, end, mass_per_length=1.0)¶
Append a bar constructed from its endpoints.
- add_external_force(bar_index, s, fx, fy, torque=0.0)¶
Add a point load on a bar.
- add_joint(bar_index, s)¶
Add a joint linking selected points across bars.
- add_support(bar_index, s, dof_in_x, dof_in_y, x=None, y=None)¶
Add a support constraint on a point of a bar.
- Parameters:
bar_index (
int) – Index of the constrained bar.s (
float) – Local coordinate of the constrained point.dof_in_x (
bool) – IfTrue, x motion is unconstrained.dof_in_y (
bool) – IfTrue, y motion is unconstrained.x (
float, optional) – Support x position. If omitted, the initial bar position is used. Default isNone.y (
float, optional) – Support y position. If omitted, the initial bar position is used. Default isNone.
- Raises:
ValueError – Raised if the support position is requested before the bar has an initial state.
- build_lagrange_eom(return_multipliers=False, return_W=False)¶
Assemble the symbolic equations of motion for the model.
This method builds the system-level Lagrangian, constraint residuals, and external-force terms, then returns the equivalent symbolic first-order ODE system for numerical integration. When
return_multipliersorreturn_Wis enabled, the corresponding constraint quantities are included in the return value.- Parameters:
return_multipliers (
bool, optional) – IfTrue, also return the symbolic Lagrange multiplier vector associated with the algebraic constraints. Default isFalse.return_W (
bool, optional) – IfTrue, also return the Delassus matrix \(W = J M^{-1} J^T\), whereJis the constraint Jacobian andMis the mass matrix. Default isFalse.
- Returns:
The ODE system as pairs
(state_var, rhs_expr). If neither option is enabled, the function returns the ODE system directly. Ifreturn_multipliersisTrue, it returns(ode_system, lambda_mult); ifreturn_WisTrue, it returns(ode_system, W); and if both areTrue, it returns(ode_system, lambda_mult, W). The multiplier entries follow the ordering of the constraint residuals inself.F.- Return type:
- check_constraint_fulfillment(state)¶
- clear()¶
Remove all bars, joints, supports, and forces from the model.
- get_initial_state()¶
Return the stacked initial generalized coordinates and velocities.
- Returns:
State vector containing
[x0, y0, theta0, xd0, yd0, thetad0]for each bar.- Return type:
- infer_joints()¶
Infer joints from intersections of bars in their initial poses.
Detects intersections anywhere along the bars, groups bars meeting at the same point, and avoids duplicate joints.
- Returns:
Total number of joints after inference.
- Return type:
- print_model()¶
Print a human-readable summary of the assembled model.
- set_g(g)¶
Set the gravitational acceleration for the model.
- Parameters:
g (
float) – Gravitational acceleration in the global y direction.
- set_init_bar_attitude(bar_index, x0, y0, theta0)¶
Set the initial center position and orientation of a bar.
- set_init_bar_velocities(bar_index, xd0, yd0, thetad0)¶
Set the initial translational and angular velocities of a bar.
- set_initial_state(initial_state)¶
Set the initial bar poses and velocities from a flattened state vector.
- Parameters:
initial_state (
listornumpy.ndarray) – State vector in the same order asget_initial_state(), where all generalized coordinates are listed first and all generalized velocities follow.- Raises:
ValueError – Raised when the state length does not match the number of bars or when an individual bar state is malformed.
- Returns:
The stacked initial generalized coordinates and velocities.
- Return type: