Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft: Add missing functions in primal #1313

Open
wants to merge 9 commits into
base: develop
Choose a base branch
from

Conversation

adayton1
Copy link
Member

@adayton1 adayton1 commented Apr 8, 2024

Summary

  • This PR is a feature
  • It does the following:
    • Adds missing AXOM_HOST_DEVICE specifiers to several methods in Point, Segment, and Vector classes
    • Adds length_squared method to the Segment class
    • Adds cross, normalize, and unitize methods to the Vector class
    • Adds squared_distance operator

Resolves #1309

@@ -113,6 +114,7 @@ class Point
* \return d the dimension of the point.
* \post d >= 1.
*/
AXOM_HOST_DEVICE
static int dimension() { return NDIMS; };
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be a constexpr function?

Copy link
Member

@kennyweiss kennyweiss left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for adding these @adayton1 -- looks good to me, but I'd have a bit more confidence if there were a few unit tests, especially for the new Vector::cross implementation in 2D and 3D.

I'd also like to hear more about the need for both Vector::normalize() and Vector::unitize()

Comment on lines +360 to +370
/*!
* \brief In-place normalization of the vector.
*/
AXOM_HOST_DEVICE
void normalize();

/*!
* \brief In-place unitization (normalization) of the vector.
*/
AXOM_HOST_DEVICE
void unitize();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggestion: Is there a good reason to have two functions that do the same thing?
If not, my preference would be to only have normalize() (which is the conventional way to refer to this operation).

Comment on lines +542 to +566
template <typename T, int NDIMS>
AXOM_HOST_DEVICE inline void Vector<T, NDIMS>::normalize()
{
const double len_sq = squared_norm();

if(len_sq >= primal::PRIMAL_TINY)
{
m_components /= (std::sqrt(len_sq));
}
else
{
// TODO: Would it be better to do nothing if the vector is really the
// zero vector? Or if it is tiny but not the zero vector, find
// the component with the largest magnitude and set it to 1 (all
// the other components would then be set to 0).

// Set the first component to 1 and all others to 0
m_components[0] = static_cast<T>(1.);

for(int i = 1; i < NDIMS; ++i)
{
m_components[i] = static_cast<T>(0.);
}
}
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should Vector::unitVector() be implemented in terms of this one?

Here's the current implementation:

//------------------------------------------------------------------------------
template <typename T, int NDIMS>
AXOM_HOST_DEVICE inline Vector<T, NDIMS> Vector<T, NDIMS>::unitVector() const
{
Vector v(*this);
const double len_sq = squared_norm();
if(len_sq >= primal::PRIMAL_TINY)
{
v /= (std::sqrt(len_sq));
}
else
{
// Create a vector whose first coordinate is 1 and all others are 0
v = Vector(static_cast<T>(1.), 1);
}
return v;
}

Comment on lines +595 to +600
//------------------------------------------------------------------------------
template <typename T, int NDIMS>
AXOM_HOST_DEVICE inline T Vector<T, NDIMS>::cross(const Vector<T, NDIMS>& vec) const
{
return cross_product(*this, vec);
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We might need to be careful about this one -- the current cross_product overloads are defined as:

  • cross_product(Vector3, Vector3) -> Vector3
  • cross_product(Vector2, Vector2) -> Vector3 // where the x- and y- components are 0

//------------------------------------------------------------------------------
template <typename T, int NDIMS>
AXOM_HOST_DEVICE inline Vector<T, 3> Vector<T, NDIMS>::cross_product(
const Vector<T, 2>& u,
const Vector<T, 2>& v)
{
return Vector<T, 3> {0, 0, numerics::determinant(u[0], u[1], v[0], v[1])};
}
//------------------------------------------------------------------------------
template <typename T, int NDIMS>
AXOM_HOST_DEVICE inline Vector<T, 3> Vector<T, NDIMS>::cross_product(
const Vector<T, 3>& u,
const Vector<T, 3>& v)
{
// note: u and v are transposed in second component
return Vector<T, 3> {numerics::determinant(u[1], u[2], v[1], v[2]),
numerics::determinant(v[0], v[2], u[0], u[2]),
numerics::determinant(u[0], u[1], v[0], v[1])};
}

Comment on lines +766 to 769
AXOM_HOST_DEVICE
inline Vector<T, NDIMS> Vector<T, NDIMS>::make_vector(const T& x,
const T& y,
const T& z)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Side note (outside the scope of this PR):

The make_vector utility function was introduced before we had an initializer list constructor for a primal::Vector. I'm not sure if we still need the make_vector helper function. (and similarly for Point::make_point)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Request for additional Primal::Vector methods
2 participants