External Force for Affine Body
AffineBodyExternalForce is a constraint-based constitution that applies external 12D generalized forces to affine body instances.
UID
- UID:
666
Description
This constitution adds external forces to affine bodies through a constraint mechanism, supporting both translational forces and affine forces. It is useful for simulating: - External forces (gravity, wind, thrust) - Torques and rotational effects - Combined translational and affine dynamics
Architecture
Unlike traditional energy-based constitutions, AffineBodyExternalForce uses the Constraint architecture:
- ExternalForceConstraint: Reads
external_forceattribute from geometry and stores raw forces - GlobalExternalForceManager: New lifecycle phase after animator update
- ABDExternalForceReporter: Computes acceleration from forces (
M^{-1} * F) - ABDTimeIntegrator: Uses the acceleration in
do_predict_dof
Lifecycle
Each frame:
1. GlobalAnimator::step()
└─ ExternalForceConstraint::do_step()
- Reads "external_force" attribute
- Stores to body_id_to_external_force
2. GlobalExternalForceManager::step()
└─ ABDExternalForceReporter::do_step()
- Computes M^{-1} * F (acceleration)
- Updates body_id_to_external_force_acc
3. ABDTimeIntegrator::do_predict_dof()
- Uses: q_tilde = q_prev + q_v*dt + (gravity + external_force_acc)*dt^2
Force Formulation
The external force is applied directly in the time integrator as acceleration:
where: - \(\mathbf{F}_{ext} \in \mathbb{R}^{12}\) is the generalized force vector - \(\mathbf{M} \in \mathbb{R}^{12 \times 12}\) is the affine body mass matrix - \(\mathbf{a}_{ext} \in \mathbb{R}^{12}\) is the resulting acceleration
The force vector is structured as:
where: - \(\mathbf{f} \in \mathbb{R}^3\) is the translational force - \(\mathbf{f}_a \in \mathbb{R}^{9}\) is the affine force (flattened 3x3 matrix)
Usage
C++
#include <uipc/constitution/affine_body_external_force.h>
// Create constitution
auto ext_force = uipc::constitution::AffineBodyExternalForce();
scene.constitution_tabular().insert(ext_force);
// Apply translational force only
Vector3 force(0, -9.8, 0);
ext_force.apply_to(cube, force);
// Apply full 12D force (translational + affine)
Vector12 force12;
force12.segment<3>(0) = Vector3(0, -9.8, 0); // translational force
force12.segment<9>(3).setZero(); // affine force
force12(5) = 0.1; // f_a13
force12(9) = -0.1; // f_a31
ext_force.apply_to(cube, force12);
Python
from uipc.constitution import AffineBodyExternalForce
import numpy as np
# Create constitution
ext_force = AffineBodyExternalForce()
scene.constitution_tabular().insert(ext_force)
# Apply translational force only
force = np.array([0.0, -9.8, 0.0])
ext_force.apply_to(cube, force)
# Apply full 12D force
force12 = np.zeros(12)
force12[0:3] = [0.0, -9.8, 0.0] # translational force
force12[5] = 0.1 # f_a13
force12[9] = -0.1 # f_a31
ext_force.apply_to(cube, force12)
Dynamic Force Updates
The constraint framework supports dynamic force updates through animators:
def animate_force(info: Animation.UpdateInfo):
time = info.dt() * info.frame()
# Compute time-varying force
angle = 0.2 * time
force = np.array([np.cos(angle), 0, np.sin(angle)]) * 0.1
force12 = np.zeros(12)
force12[0:3] = force
force12[5] = 0.01 # f_a13
force12[9] = -0.01
# Update force attribute
for geo_slot in info.geo_slots():
geo = geo_slot.geometry()
force_attr = geo.instances().find("external_force")
if force_attr:
view(force_attr)[:] = force12.reshape(-1, 1)
scene.animator().insert(object, animate_force)
Notes
- Uses constraint architecture instead of energy-based approach
- Supports multiple constraints on the same geometry
- Forces are converted to accelerations before integration
- No energy/gradient/hessian computation needed
- Thread-safe parallel computation on GPU
- Attribute name:
external_force(changed fromexternal_wrench) - Meta attribute:
constraint_uids(changed fromextra_constitution_uids)
Example
See the test cases: - C++: apps/tests/sim_case/affine_body_external_force_test.cpp - Python: python/tests/test_affine_body_external_force.py
Both tests demonstrate a cube with combined orbital motion (translational force) and affine dynamics.