Skip to content

Commit

Permalink
Merge branch 'develop' into feature/gunney/marching-cubes-mask
Browse files Browse the repository at this point in the history
  • Loading branch information
rhornung67 committed Jul 11, 2024
2 parents f1bb261 + 6c1392a commit 2ba53d9
Show file tree
Hide file tree
Showing 22 changed files with 906 additions and 132 deletions.
5 changes: 5 additions & 0 deletions RELEASE-NOTES.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,11 @@ The Axom project release numbers follow [Semantic Versioning](http://semver.org/
## [Unreleased] - Release date yyyy-mm-dd

### Added
- Primal: Adds a `clip()` operator overload for clipping a 2D polygon against
another 2D polygon.
- Primal: Adds `Polygon::reverseOrientation()` to reverse orientation of
a polygon in-place.
- Adds `StaticArray`, a wrapper for `StackArray` with a size member variable.
- Multidimenional `core::Array` supports column-major and arbitrary stride ordering,
in addition to the default row-major ordering.
- Adds new `PolygonArray` and `MAX_VERTS` template parameters to `primal::Polygon` for dynamic
Expand Down
1 change: 1 addition & 0 deletions src/axom/core/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ set(core_headers
Path.hpp
RangeAdapter.hpp
StackArray.hpp
StaticArray.hpp
Types.hpp
memory_management.hpp

Expand Down
75 changes: 75 additions & 0 deletions src/axom/core/StaticArray.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
// Copyright (c) 2017-2024, Lawrence Livermore National Security, LLC and
// other Axom Project Developers. See the top-level LICENSE file for details.
//
// SPDX-License-Identifier: (BSD-3-Clause)

#ifndef AXOM_STATICARRAY_HPP_
#define AXOM_STATICARRAY_HPP_

#include "axom/config.hpp" // for compile-time defines
#include "axom/core/Macros.hpp" // for axom macros
#include "axom/core/StackArray.hpp" // for StackArray

namespace axom
{
/*!
* \accelerated
* \class StaticArray
*
* \brief Provides a wrapper for a StackArray with an additional size member.
*
* \tparam T the type of the values to hold.
* \tparam N the number of values in the array.
*
* \note Type \a T must be default-constructible on device for device
* execution.
*/
template <typename T, int N>
struct StaticArray : public StackArray<T, N>
{
/*!
* \brief Returns the size of the static array
*
* \return The size of the static array
*/
AXOM_HOST_DEVICE int size() const { return m_size; }

/*!
* \brief Pushes an object to the back of the static array
*
* \param [in] obj the object to be added to the back.
*
* \note The number of push_backs must not exceed N,
* the max number of values in the array.
*
* \note If the static array is full, push_back
* will not modify the static array.
*/
AXOM_HOST_DEVICE void push_back(const T& obj)
{
assert(m_size < N);
if(m_size < N)
{
StackArray<T, N>::m_data[m_size++] = obj;
}
}

/*!
* \brief Clears the data from the static array
*/
AXOM_HOST_DEVICE void clear()
{
for(T& datum : StackArray<T, N>::m_data)
{
datum = T();
}
m_size = 0;
}

private:
int m_size {0};
};

} /* namespace axom */

#endif /* AXOM_STATICARRAY_HPP_ */
1 change: 1 addition & 0 deletions src/axom/core/tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ set(core_serial_tests
core_memory_management.hpp
core_Path.hpp
core_stack_array.hpp
core_static_array.hpp

numerics_determinants.hpp
numerics_eigen_solve.hpp
Expand Down
1 change: 1 addition & 0 deletions src/axom/core/tests/core_serial_main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include "core_memory_management.hpp"
#include "core_Path.hpp"
#include "core_stack_array.hpp"
#include "core_static_array.hpp"

#ifndef AXOM_USE_MPI
#include "core_types.hpp"
Expand Down
100 changes: 100 additions & 0 deletions src/axom/core/tests/core_static_array.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
// Copyright (c) 2017-2024, Lawrence Livermore National Security, LLC and
// other Axom Project Developers. See the top-level LICENSE file for details.
//
// SPDX-License-Identifier: (BSD-3-Clause)

#include "axom/config.hpp" // for compile time definitions

#include "axom/core/StaticArray.hpp"

// for gtest macros
#include "gtest/gtest.h"

//------------------------------------------------------------------------------
// HELPER METHOD
//------------------------------------------------------------------------------
namespace
{
template <typename ExecSpace>
void check_static_array_policy()
{
const int MAX_SIZE = 10;
using StaticArrayType = axom::StaticArray<int, MAX_SIZE>;

// Get ids of necessary allocators
const int host_allocator = axom::execution_space<axom::SEQ_EXEC>::allocatorID();
const int kernel_allocator = axom::execution_space<ExecSpace>::allocatorID();

axom::Array<StaticArrayType> s_arrays_device(MAX_SIZE,
MAX_SIZE,
kernel_allocator);
auto s_arrays_view = s_arrays_device.view();

axom::Array<StaticArrayType> sizes_device(1, 1, kernel_allocator);
auto sizes_view = sizes_device.view();

axom::for_all<ExecSpace>(
MAX_SIZE,
AXOM_LAMBDA(int i) {
// Sanity check - function is callable on device
s_arrays_view[i].clear();

for(int idx = 0; idx <= i; idx++)
{
s_arrays_view[i].push_back(idx);
}

sizes_view[0][i] = s_arrays_view[i].size();
});

// Copy static arrays and their sizes back to host
axom::Array<StaticArrayType> s_arrays_host =
axom::Array<StaticArrayType>(s_arrays_device, host_allocator);
axom::Array<StaticArrayType> sizes_host =
axom::Array<StaticArrayType>(sizes_device, host_allocator);

// Verify values
for(int i = 0; i < MAX_SIZE; i++)
{
EXPECT_EQ(sizes_host[0][i], i + 1);
for(int j = 0; j <= i; j++)
{
EXPECT_EQ(s_arrays_host[i][j], j);
}
}
}

} /* end anonymous namespace */

//------------------------------------------------------------------------------
// UNIT TESTS
//------------------------------------------------------------------------------

//------------------------------------------------------------------------------
TEST(core_static_array, check_static_array_seq)
{
check_static_array_policy<axom::SEQ_EXEC>();
}

#if defined(AXOM_USE_OPENMP) && defined(AXOM_USE_RAJA)
TEST(core_static_array, check_static_array_omp)
{
check_static_array_policy<axom::OMP_EXEC>();
}
#endif

#if defined(AXOM_USE_CUDA) && defined(AXOM_USE_RAJA) && defined(AXOM_USE_UMPIRE)
TEST(core_static_array, check_static_array_cuda)
{
check_static_array_policy<axom::CUDA_EXEC<256>>();
check_static_array_policy<axom::CUDA_EXEC<256, axom::ASYNC>>();
}
#endif

#if defined(AXOM_USE_HIP) && defined(AXOM_USE_RAJA) && defined(AXOM_USE_UMPIRE)
TEST(core_static_array, check_static_array_hip)
{
check_static_array_policy<axom::HIP_EXEC<256>>();
check_static_array_policy<axom::HIP_EXEC<256, axom::ASYNC>>();
}
#endif
1 change: 1 addition & 0 deletions src/axom/primal/geometry/Point.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,7 @@ class Point
/*!
* \brief Inequality operator for points
*/
AXOM_HOST_DEVICE
friend inline bool operator!=(const Point& lhs, const Point& rhs)
{
return !(lhs == rhs);
Expand Down
103 changes: 68 additions & 35 deletions src/axom/primal/geometry/Polygon.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#define AXOM_PRIMAL_POLYGON_HPP_

#include "axom/core/Array.hpp"
#include "axom/core/StaticArray.hpp"
#include "axom/primal/geometry/Point.hpp"
#include "axom/primal/geometry/Vector.hpp"

Expand All @@ -25,39 +26,6 @@ namespace primal
namespace
{
static constexpr int DEFAULT_MAX_NUM_VERTICES = 8;

/*!
* \brief A helper class for the Polygon class
*
* This class helps define a StackArray with a current size and additional
* functions to mirror axom::Array.
*/
template <typename T, int N>
struct StaticArray : public StackArray<T, N>
{
AXOM_HOST_DEVICE int size() const { return m_size; }
AXOM_HOST_DEVICE void push_back(const T& obj)
{
assert(m_size < N);
if(m_size < N)
{
StackArray<T, N>::m_data[m_size++] = obj;
}
}

AXOM_HOST_DEVICE void clear()
{
for(T& datum : StackArray<T, N>::m_data)
{
datum = T();
}
m_size = 0;
}

private:
int m_size {0};
};

} /* end anonymous namespace */

/**
Expand Down Expand Up @@ -106,7 +74,7 @@ class Polygon
// axom::Array for dynamic array type, StaticArray for static array type
using ArrayType = std::conditional_t<ARRAY_TYPE == PolygonArray::Dynamic,
axom::Array<PointType>,
StaticArray<PointType, MAX_VERTS>>;
axom::StaticArray<PointType, MAX_VERTS>>;

public:
/// Default constructor for an empty polygon (dynamic array specialization).
Expand All @@ -123,6 +91,45 @@ class Polygon
AXOM_HOST_DEVICE Polygon()
{ }

/*!
* \brief Destructor for Polygon. Suppress CUDA warnings for
* dynamic axom::Array.
*/
AXOM_SUPPRESS_HD_WARN
AXOM_HOST_DEVICE
~Polygon() { m_vertices.clear(); }

/*!
* \brief Copy assignment operator for Polygon. Suppress CUDA warnings for
* dynamic axom::Array.
*/
AXOM_SUPPRESS_HD_WARN
AXOM_HOST_DEVICE
Polygon& operator=(const Polygon& other)
{
if(this == &other)
{
return *this;
}

m_vertices = other.m_vertices;
return *this;
}

/// Copy constructor for Polygon. Specializations are necessary to
/// remove __host__ __device__ warning for axom::Array usage with
/// the dynamic array type.
template <PolygonArray P_ARRAY_TYPE = ARRAY_TYPE,
std::enable_if_t<P_ARRAY_TYPE == PolygonArray::Dynamic, int> = 0>
Polygon(const Polygon& other) : m_vertices(other.m_vertices)
{ }

/// Copy constructor for Polygon (static array specialization)
template <PolygonArray P_ARRAY_TYPE = ARRAY_TYPE,
std::enable_if_t<P_ARRAY_TYPE == PolygonArray::Static, int> = 0>
AXOM_HOST_DEVICE Polygon(const Polygon& other) : m_vertices(other.m_vertices)
{ }

/*!
* \brief Constructor for an empty polygon that reserves space for
* the given number of vertices. Only available for dynamic arrays.
Expand Down Expand Up @@ -175,7 +182,17 @@ class Polygon
AXOM_HOST_DEVICE
int numVertices() const { return static_cast<int>(m_vertices.size()); }

/// Appends a vertex to the list of vertices
/*!
* \brief Appends a vertex to the list of vertices
*
* \param [in] pt the point to be appended to the list of vertices
*
* \note If the array type is static and the list of vertices is full,
* addVertex will not modify the list of vertices.
*
* \sa axom::StaticArray::push_back() for behavior when array type is static
* and the list of vertices is full.
*/
AXOM_HOST_DEVICE
void addVertex(const PointType& pt) { m_vertices.push_back(pt); }

Expand Down Expand Up @@ -231,6 +248,22 @@ class Polygon
return normal;
}

/// \brief Reverses orientation of the polygon in-place
AXOM_HOST_DEVICE
void reverseOrientation()
{
const int nverts = numVertices();
const int mid = nverts >> 1;

// Swap leftmost/rightmost vertices, midpoint unchanged
for(int i = 0; i < mid; ++i)
{
const int left = i;
const int right = nverts - i - 1;
axom::utilities::swap(m_vertices[left], m_vertices[right]);
}
}

/*!
* \brief Computes the average of the polygon's vertex positions
*
Expand Down
Loading

0 comments on commit 2ba53d9

Please sign in to comment.