Skip to content

[bug] Coordinate rotation function breaks down when normal vector too close to (1.0, 0.0, 0.0) #246

Closed
@drobnyjt

Description

@drobnyjt

Description
RustBCA's library provides a handful of helper functions for code coupling. One of these, rotate_given_surface_normal, rotates the direction of a particle that strikes the wall in a simulation from the simulation's coordinate system into the RustBCA coordinate system (where +x is into the surface); the particle direction is denoted u and the normal vector n.

This function uses an algorithm that constructs a rotation matrix that aligns the global into-the-surface vector (-n) with the RustBCA into-the-surface vector, (1, 0, 0). This algorithm includes the following calculation:

R = I + V  V^2/(1 + c)

Where R is the rotation matrix, I is the identity, V is a matrix constructed from the elements of the cross product of the global and local (i.e., RustBCA) into-the-surface vectors, and c is the dot product of the local and global into-the-surface vectors.

There is an obvious singularity when c = -1, which is the case for n = (1, 0, 0) and u = (-1, 0, 0). I believe this is related to gimbal lock. Currently, if c == -1, the code correctly ignores the algorithm and instead calculates R as a 180-degree rotation around the y axis (chosen arbitrarily without loss of generality). However, when c is very close to -1, the last term in the above equation blows up and the algorithm produces incorrect rotation matrices that result in "initial direction out of surface" error messages.

To Reproduce

>>> import numpy as np
>>> from libRustBCA import rotate_given_surface_normal_py
>>> nx = 1 - 1e-9
>>> ny = 1 - nx*nx
>>> ux1, uy1, uz1 = rotate_given_surface_normal_py(nx, ny, 0.0, -np.sqrt(2)/2, np.sqrt(2)/2, 0)
thread '<unnamed>' panicked at src/lib.rs:1398:5:
Error: RustBCA initial direction out of surface. Please check surface normals and incident direction. n = (0.999999999, 0.000000001999999943436137, 0) u = (-0.707106775943907, -0.7071067811865476, 0)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
pyo3_runtime.PanicException: Error: RustBCA initial direction out of surface. Please check surface normals and incident direction. n = (0.999999999, 0.000000001999999943436137, 0) u = (-0.707106775943907, -0.7071067811865476, 0)

Expected behavior
There should be a threshold for c being too close to -1 that should revert to a 180-degree rotation around y. There is probably a way to calculate an ideal threshold, but from testing the code functions normally when nx = 1 - 1e-6 and breaks when nx = 1 - 1e-9, so the threshold should be somewhere in between those two values.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions