Summary
RodStraightSection::getRestTransformOnX computes the wrong rest position for any section that is not the first entry in WireRestShape.wireMaterials. Using two consecutive RodStraightSection instances causes massive elastic forces at every timestep, leading to guidewire explosion on vessel-wall contact.
Affected component
- File:
src/BeamAdapter/component/model/RodStraightSection.inl
- Method:
RodStraightSection<DataTypes>::getRestTransformOnX
The bug
// CURRENT (buggy)
void RodStraightSection<DataTypes>::getRestTransformOnX(
Transform& global_H_local, const Real x_used, const Real x_start)
{
global_H_local.set(type::Vec3(x_start + x_used, 0.0, 0.0), Quat());
}
x_used is the global curvilinear abscissa along the entire wire (e.g., 430 mm for a point 10 mm into a section that starts at 420 mm). x_start is the section's start key-point (keyPts[i-1] in WireRestShape::getRestTransformOnX).
The formula x_start + x_used adds the section start twice, placing the rest-shape node at 2 × x_start + local_offset instead of the correct x_used.
Numerical example — stiff section 420 mm, flex section 30 mm:
|
x_start |
x_used |
Computed position |
Correct position |
| Section 0 (stiff) |
0 |
210 |
0 + 210 = 210 ✓ |
210 |
| Section 1 (flex) |
420 |
430 |
420 + 430 = 850 ✗ |
430 |
The flex-tip rest shape is placed ~420 mm past where it should be. Mechanical DOFs sit at ~430 mm; rest position at ~850 mm → AdaptiveBeamForceFieldAndMass generates a huge elastic restoring force every step → explosion on any disturbance.
Correct pattern
Both RodSpireSection and RodMeshSection follow the correct pattern — compute a local offset, then add x_start once:
// RodSpireSection
Real lengthCurve = x_used - x_start; // local offset
// ... helix geometry from lengthCurve ...
type::Vec3 SpirePos = PosEndCurve + type::Vec3(x_start, 0, 0); // back to global
// RodMeshSection
Real abs_curr = x_used - x_start; // local offset
// ... mesh interpolation → PosEndCurve ...
type::Vec3 ExtremityPos = PosEndCurve + type::Vec3(x_start, 0, 0); // back to global
For a straight section the local offset is trivially x_used - x_start, so the global position reduces to simply x_used.
Proposed fix
// FIXED — src/BeamAdapter/component/model/RodStraightSection.inl
void RodStraightSection<DataTypes>::getRestTransformOnX(
Transform& global_H_local, const Real x_used, const Real x_start)
{
global_H_local.set(type::Vec3(x_used, 0.0, 0.0), Quat());
}
One-line change. Zero effect on single-section wires (x_start = 0 → old and new formulas identical).
Workaround
Use RodMeshSection with a two-point straight mesh for the non-first sections. This exercises the correct code path until the fix lands.
Summary
RodStraightSection::getRestTransformOnXcomputes the wrong rest position for any section that is not the first entry inWireRestShape.wireMaterials. Using two consecutiveRodStraightSectioninstances causes massive elastic forces at every timestep, leading to guidewire explosion on vessel-wall contact.Affected component
src/BeamAdapter/component/model/RodStraightSection.inlRodStraightSection<DataTypes>::getRestTransformOnXThe bug
x_usedis the global curvilinear abscissa along the entire wire (e.g., 430 mm for a point 10 mm into a section that starts at 420 mm).x_startis the section's start key-point (keyPts[i-1]inWireRestShape::getRestTransformOnX).The formula
x_start + x_usedadds the section start twice, placing the rest-shape node at2 × x_start + local_offsetinstead of the correctx_used.Numerical example — stiff section 420 mm, flex section 30 mm:
x_startx_usedThe flex-tip rest shape is placed ~420 mm past where it should be. Mechanical DOFs sit at ~430 mm; rest position at ~850 mm →
AdaptiveBeamForceFieldAndMassgenerates a huge elastic restoring force every step → explosion on any disturbance.Correct pattern
Both
RodSpireSectionandRodMeshSectionfollow the correct pattern — compute a local offset, then addx_startonce:For a straight section the local offset is trivially
x_used - x_start, so the global position reduces to simplyx_used.Proposed fix
One-line change. Zero effect on single-section wires (
x_start = 0→ old and new formulas identical).Workaround
Use
RodMeshSectionwith a two-point straight mesh for the non-first sections. This exercises the correct code path until the fix lands.