diff --git a/src/restruct_poc/beams/create_beams.hpp b/src/restruct_poc/beams/create_beams.hpp index 052e282b..8e8517c5 100644 --- a/src/restruct_poc/beams/create_beams.hpp +++ b/src/restruct_poc/beams/create_beams.hpp @@ -2,11 +2,9 @@ #include "beams.hpp" #include "calculate_jacobian.hpp" -#include "interpolate_QP_acceleration.hpp" #include "interpolate_QP_position.hpp" #include "interpolate_QP_rotation.hpp" -#include "interpolate_QP_state.hpp" -#include "interpolate_QP_velocity.hpp" +#include "interpolate_to_quadrature_points.hpp" #include "populate_element_views.hpp" #include "set_node_state_indices.hpp" @@ -105,35 +103,14 @@ inline Beams CreateBeams(const BeamsInput& beams_input) { } ); + auto range_policy = Kokkos::TeamPolicy<>(beams.num_elems, Kokkos::AUTO()); Kokkos::parallel_for( - "InterpolateQPState", beams.num_elems, - InterpolateQPState{ + "InterpolateToQuadraturePoints", range_policy, + InterpolateToQuadraturePoints{ beams.elem_indices, beams.shape_interp, beams.shape_deriv, beams.qp_jacobian, - beams.node_u, beams.qp_u, beams.qp_u_prime, beams.qp_r, beams.qp_r_prime} - ); - Kokkos::parallel_for( - "InterpolateQPVelocity", - Kokkos::MDRangePolicy{{0, 0}, {beams.num_elems, beams.max_elem_qps}}, - InterpolateQPVelocity_Translation{ - beams.elem_indices, beams.shape_interp, beams.node_u_dot, beams.qp_u_dot} - ); - Kokkos::parallel_for( - "InterpolateQPVelocity", - Kokkos::MDRangePolicy{{0, 0}, {beams.num_elems, beams.max_elem_qps}}, - InterpolateQPVelocity_Angular{ - beams.elem_indices, beams.shape_interp, beams.node_u_dot, beams.qp_omega} - ); - Kokkos::parallel_for( - "InterpolateQPAcceleration", - Kokkos::MDRangePolicy{{0, 0}, {beams.num_elems, beams.max_elem_qps}}, - InterpolateQPAcceleration_Translation{ - beams.elem_indices, beams.shape_interp, beams.node_u_ddot, beams.qp_u_ddot} - ); - Kokkos::parallel_for( - "InterpolateQPAcceleration", - Kokkos::MDRangePolicy{{0, 0}, {beams.num_elems, beams.max_elem_qps}}, - InterpolateQPAcceleration_Angular{ - beams.elem_indices, beams.shape_interp, beams.node_u_ddot, beams.qp_omega_dot} + beams.node_u, beams.node_u_dot, beams.node_u_ddot, beams.qp_u, beams.qp_u_prime, + beams.qp_r, beams.qp_r_prime, beams.qp_u_dot, beams.qp_omega, beams.qp_u_ddot, + beams.qp_omega_dot} ); return beams; } diff --git a/src/restruct_poc/beams/interpolate_QP_acceleration.hpp b/src/restruct_poc/beams/interpolate_QP_acceleration.hpp deleted file mode 100644 index 2a11ee42..00000000 --- a/src/restruct_poc/beams/interpolate_QP_acceleration.hpp +++ /dev/null @@ -1,105 +0,0 @@ -#pragma once - -#include - -#include "beams.hpp" - -#include "src/restruct_poc/types.hpp" - -namespace openturbine { - -struct InterpolateQPAcceleration_Translation { - Kokkos::View::const_type elem_indices; // Element indices - View_NxN::const_type shape_interp; // Num Nodes x Num Quadrature points - View_Nx6::const_type node_u_ddot; // Node translation & angular velocity - View_Nx3 qp_u_ddot; // qp translation velocity - - KOKKOS_FUNCTION - void operator()(const int i_elem) const { - auto idx = elem_indices(i_elem); - for (int j_index = 0; j_index < idx.num_qps; ++j_index) { - const auto j = idx.qp_range.first + j_index; - auto local_total = Kokkos::Array{}; - for (int i_index = 0; i_index < idx.num_nodes; ++i_index) { - const auto i = idx.node_range.first + i_index; - const auto phi = shape_interp(i, j_index); - for (int k = 0; k < 3; ++k) { - local_total[k] += node_u_ddot(i, k) * phi; - } - } - for (int k = 0; k < 3; ++k) { - qp_u_ddot(j, k) = local_total[k]; - } - } - } - - KOKKOS_FUNCTION - void operator()(const int i_elem, const int j_index) const { - auto idx = elem_indices(i_elem); - if (j_index >= idx.num_qps) { - return; - } - - const auto j = idx.qp_range.first + j_index; - auto local_total = Kokkos::Array{}; - for (int i_index = 0; i_index < idx.num_nodes; ++i_index) { - const auto i = idx.node_range.first + i_index; - const auto phi = shape_interp(i, j_index); - for (int k = 0; k < 3; ++k) { - local_total[k] += node_u_ddot(i, k) * phi; - } - } - for (int k = 0; k < 3; ++k) { - qp_u_ddot(j, k) = local_total[k]; - } - } -}; - -struct InterpolateQPAcceleration_Angular { - Kokkos::View::const_type elem_indices; // Element indices - View_NxN::const_type shape_interp; // Num Nodes x Num Quadrature points - View_Nx6::const_type node_u_ddot; // Node translation & angular velocity - View_Nx3 qp_omega_dot; // qp angular velocity - - KOKKOS_FUNCTION - void operator()(const int i_elem) const { - auto idx = elem_indices(i_elem); - for (int j_index = 0; j_index < idx.num_qps; ++j_index) { - const auto j = idx.qp_range.first + j_index; - auto local_total = Kokkos::Array{}; - for (int i_index = 0; i_index < idx.num_nodes; ++i_index) { - const auto i = idx.node_range.first + i_index; - const auto phi = shape_interp(i, j_index); - for (int k = 0; k < 3; ++k) { - local_total[k] += node_u_ddot(i, k + 3) * phi; - } - } - for (int k = 0; k < 3; ++k) { - qp_omega_dot(j, k) = local_total[k]; - } - } - } - - KOKKOS_FUNCTION - void operator()(const int i_elem, const int j_index) const { - auto idx = elem_indices(i_elem); - if (j_index >= idx.num_qps) { - return; - } - - const auto j = idx.qp_range.first + j_index; - auto local_total = Kokkos::Array{}; - for (int i_index = 0; i_index < idx.num_nodes; ++i_index) { - const auto i = idx.node_range.first + i_index; - const auto phi = shape_interp(i, j_index); - for (int k = 0; k < 3; ++k) { - local_total[k] += node_u_ddot(i, k + 3) * phi; - } - } - for (int k = 0; k < 3; ++k) { - qp_omega_dot(j, k) = local_total[k]; - } - } -}; - -} // namespace openturbine diff --git a/src/restruct_poc/beams/interpolate_QP_state.hpp b/src/restruct_poc/beams/interpolate_QP_state.hpp index 35d8aab7..415ebe4d 100644 --- a/src/restruct_poc/beams/interpolate_QP_state.hpp +++ b/src/restruct_poc/beams/interpolate_QP_state.hpp @@ -2,47 +2,24 @@ #include -#include "beams.hpp" - #include "src/restruct_poc/types.hpp" namespace openturbine { -struct InterpolateQPU { - Kokkos::View::const_type elem_indices; +struct InterpolateQPState_u { + int first_qp; + int first_node; + int num_nodes; View_NxN::const_type shape_interp; View_Nx7::const_type node_u; View_Nx3 qp_u; KOKKOS_FUNCTION - void operator()(const int i_elem) const { - auto idx = elem_indices(i_elem); - for (int j_index = 0; j_index < idx.num_qps; ++j_index) { - const auto j = idx.qp_range.first + j_index; - auto local_total = Kokkos::Array{}; - for (int i_index = 0; i_index < idx.num_nodes; ++i_index) { - const auto i = idx.node_range.first + i_index; - const auto phi = shape_interp(i, j_index); - for (int k = 0; k < 3; ++k) { - local_total[k] += node_u(i, k) * phi; - } - } - for (int k = 0; k < 3; ++k) { - qp_u(j, k) = local_total[k]; - } - } - } - - KOKKOS_FUNCTION - void operator()(const int i_elem, const int j_index) const { - auto idx = elem_indices(i_elem); - if (j_index >= idx.num_qps) { - return; - } - const auto j = idx.qp_range.first + j_index; + void operator()(int j_index) const { + const auto j = first_qp + j_index; auto local_total = Kokkos::Array{}; - for (int i_index = 0; i_index < idx.num_nodes; ++i_index) { - const auto i = idx.node_range.first + i_index; + for (int i_index = 0; i_index < num_nodes; ++i_index) { + const auto i = first_node + i_index; const auto phi = shape_interp(i, j_index); for (int k = 0; k < 3; ++k) { local_total[k] += node_u(i, k) * phi; @@ -54,45 +31,22 @@ struct InterpolateQPU { } }; -struct InterpolateQPU_Prime { - Kokkos::View::const_type elem_indices; +struct InterpolateQPState_uprime { + int first_qp; + int first_node; + int num_nodes; View_NxN::const_type shape_deriv; View_N::const_type qp_jacobian; View_Nx7::const_type node_u; View_Nx3 qp_uprime; KOKKOS_FUNCTION - void operator()(const int i_elem) const { - auto idx = elem_indices(i_elem); - for (int j_index = 0; j_index < idx.num_qps; ++j_index) { - const auto j = idx.qp_range.first + j_index; - const auto jacobian = qp_jacobian(j); - auto local_total = Kokkos::Array{}; - for (int i_index = 0; i_index < idx.num_nodes; ++i_index) { - const auto i = idx.node_range.first + i_index; - const auto dphi = shape_deriv(i, j_index); - for (int k = 0; k < 3; ++k) { - local_total[k] += node_u(i, k) * dphi / jacobian; - } - } - for (int k = 0; k < 3; ++k) { - qp_uprime(j, k) = local_total[k]; - } - } - } - - KOKKOS_FUNCTION - void operator()(const int i_elem, const int j_index) const { - auto idx = elem_indices(i_elem); - if (j_index >= idx.num_qps) { - return; - } - - const auto j = idx.qp_range.first + j_index; + void operator()(int j_index) const { + const auto j = first_qp + j_index; const auto jacobian = qp_jacobian(j); auto local_total = Kokkos::Array{}; - for (int i_index = 0; i_index < idx.num_nodes; ++i_index) { - const auto i = idx.node_range.first + i_index; + for (int i_index = 0; i_index < num_nodes; ++i_index) { + const auto i = first_node + i_index; const auto dphi = shape_deriv(i, j_index); for (int k = 0; k < 3; ++k) { local_total[k] += node_u(i, k) * dphi / jacobian; @@ -104,50 +58,20 @@ struct InterpolateQPU_Prime { } }; -struct InterpolateQPR { - Kokkos::View::const_type elem_indices; +struct InterpolateQPState_r { + int first_qp; + int first_node; + int num_nodes; View_NxN::const_type shape_interp; View_Nx7::const_type node_u; View_Nx4 qp_r; KOKKOS_FUNCTION - void operator()(const int i_elem) const { - auto idx = elem_indices(i_elem); - for (int j_index = 0; j_index < idx.num_qps; ++j_index) { - const auto j = idx.qp_range.first + j_index; - auto local_total = Kokkos::Array{}; - for (int i_index = 0; i_index < idx.num_nodes; ++i_index) { - const auto i = idx.node_range.first + i_index; - const auto phi = shape_interp(i, j_index); - for (int k = 0; k < 4; ++k) { - local_total[k] += node_u(i, k + 3) * phi; - } - } - const auto length = Kokkos::sqrt( - local_total[0] * local_total[0] + local_total[1] * local_total[1] + - local_total[2] * local_total[2] + local_total[3] * local_total[3] - ); - static constexpr auto length_zero_result = Kokkos::Array{1., 0., 0., 0.}; - if (length == 0.) { - local_total = length_zero_result; - } - for (int k = 0; k < 4; ++k) { - qp_r(j, k) = local_total[k]; - } - } - } - - KOKKOS_FUNCTION - void operator()(const int i_elem, const int j_index) const { - auto idx = elem_indices(i_elem); - if (j_index >= idx.num_qps) { - return; - } - - const auto j = idx.qp_range.first + j_index; + void operator()(int j_index) const { + const auto j = first_qp + j_index; auto local_total = Kokkos::Array{}; - for (int i_index = 0; i_index < idx.num_nodes; ++i_index) { - const auto i = idx.node_range.first + i_index; + for (int i_index = 0; i_index < num_nodes; ++i_index) { + const auto i = first_node + i_index; const auto phi = shape_interp(i, j_index); for (int k = 0; k < 4; ++k) { local_total[k] += node_u(i, k + 3) * phi; @@ -167,45 +91,22 @@ struct InterpolateQPR { } }; -struct InterpolateQPR_Prime { - Kokkos::View::const_type elem_indices; +struct InterpolateQPState_rprime { + int first_qp; + int first_node; + int num_nodes; View_NxN::const_type shape_deriv; View_N::const_type qp_jacobian; View_Nx7::const_type node_u; View_Nx4 qp_rprime; KOKKOS_FUNCTION - void operator()(const int i_elem) const { - auto idx = elem_indices(i_elem); - for (int j_index = 0; j_index < idx.num_qps; ++j_index) { - const auto j = idx.qp_range.first + j_index; - const auto jacobian = qp_jacobian(j); - auto local_total = Kokkos::Array{}; - for (int i_index = 0; i_index < idx.num_nodes; ++i_index) { - const auto i = idx.node_range.first + i_index; - const auto dphi = shape_deriv(i, j_index); - for (int k = 0; k < 4; ++k) { - local_total[k] += node_u(i, k + 3) * dphi / jacobian; - } - } - for (int k = 0; k < 4; ++k) { - qp_rprime(j, k) = local_total[k]; - } - } - } - - KOKKOS_FUNCTION - void operator()(const int i_elem, const int j_index) const { - auto idx = elem_indices(i_elem); - if (j_index >= idx.num_qps) { - return; - } - - const auto j = idx.qp_range.first + j_index; + void operator()(int j_index) const { + const auto j = first_qp + j_index; const auto jacobian = qp_jacobian(j); auto local_total = Kokkos::Array{}; - for (int i_index = 0; i_index < idx.num_nodes; ++i_index) { - const auto i = idx.node_range.first + i_index; + for (int i_index = 0; i_index < num_nodes; ++i_index) { + const auto i = first_node + i_index; const auto dphi = shape_deriv(i, j_index); for (int k = 0; k < 4; ++k) { local_total[k] += node_u(i, k + 3) * dphi / jacobian; @@ -217,90 +118,4 @@ struct InterpolateQPR_Prime { } }; -struct InterpolateQPState { - Kokkos::View::const_type elem_indices; - View_NxN::const_type shape_interp; - View_NxN::const_type shape_deriv; - View_N::const_type qp_jacobian; - View_Nx7::const_type node_u; - View_Nx3 qp_u; - View_Nx3 qp_uprime; - View_Nx4 qp_r; - View_Nx4 qp_rprime; - - KOKKOS_FUNCTION - void operator()(const int i_elem) const { - auto idx = elem_indices(i_elem); - for (int j_index = 0; j_index < idx.num_qps; ++j_index) { - const auto j = idx.qp_range.first + j_index; - auto local_total = Kokkos::Array{}; - for (int i_index = 0; i_index < idx.num_nodes; ++i_index) { - const auto i = idx.node_range.first + i_index; - const auto phi = shape_interp(i, j_index); - for (int k = 0; k < 3; ++k) { - local_total[k] += node_u(i, k) * phi; - } - } - for (int k = 0; k < 3; ++k) { - qp_u(j, k) = local_total[k]; - } - } - - for (int j_index = 0; j_index < idx.num_qps; ++j_index) { - const auto j = idx.qp_range.first + j_index; - const auto jacobian = qp_jacobian(j); - auto local_total = Kokkos::Array{}; - for (int i_index = 0; i_index < idx.num_nodes; ++i_index) { - const auto i = idx.node_range.first + i_index; - const auto dphi = shape_deriv(i, j_index); - for (int k = 0; k < 3; ++k) { - local_total[k] += node_u(i, k) * dphi / jacobian; - } - } - for (int k = 0; k < 3; ++k) { - qp_uprime(j, k) = local_total[k]; - } - } - - for (int j_index = 0; j_index < idx.num_qps; ++j_index) { - const auto j = idx.qp_range.first + j_index; - auto local_total = Kokkos::Array{}; - for (int i_index = 0; i_index < idx.num_nodes; ++i_index) { - const auto i = idx.node_range.first + i_index; - const auto phi = shape_interp(i, j_index); - for (int k = 0; k < 4; ++k) { - local_total[k] += node_u(i, k + 3) * phi; - } - } - const auto length = Kokkos::sqrt( - local_total[0] * local_total[0] + local_total[1] * local_total[1] + - local_total[2] * local_total[2] + local_total[3] * local_total[3] - ); - static constexpr auto length_zero_result = Kokkos::Array{1., 0., 0., 0.}; - if (length == 0.) { - local_total = length_zero_result; - } - for (int k = 0; k < 4; ++k) { - qp_r(j, k) = local_total[k]; - } - } - - for (int j_index = 0; j_index < idx.num_qps; ++j_index) { - const auto j = idx.qp_range.first + j_index; - const auto jacobian = qp_jacobian(j); - auto local_total = Kokkos::Array{}; - for (int i_index = 0; i_index < idx.num_nodes; ++i_index) { - const auto i = idx.node_range.first + i_index; - const auto dphi = shape_deriv(i, j_index); - for (int k = 0; k < 4; ++k) { - local_total[k] += node_u(i, k + 3) * dphi / jacobian; - } - } - for (int k = 0; k < 4; ++k) { - qp_rprime(j, k) = local_total[k]; - } - } - } -}; - } // namespace openturbine diff --git a/src/restruct_poc/beams/interpolate_QP_vector.hpp b/src/restruct_poc/beams/interpolate_QP_vector.hpp new file mode 100644 index 00000000..04086039 --- /dev/null +++ b/src/restruct_poc/beams/interpolate_QP_vector.hpp @@ -0,0 +1,34 @@ +#pragma once + +#include + +#include "src/restruct_poc/types.hpp" + +namespace openturbine { + +struct InterpolateQPVector { + int first_qp; + int first_node; + int num_nodes; + View_NxN::const_type shape_interp; + View_Nx3::const_type node_vector; + View_Nx3 qp_vector; + + KOKKOS_FUNCTION + void operator()(int j_index) const { + const auto j = first_qp + j_index; + auto local_total = Kokkos::Array{}; + for (int i_index = 0; i_index < num_nodes; ++i_index) { + const auto i = first_node + i_index; + const auto phi = shape_interp(i, j_index); + for (int k = 0; k < 3; ++k) { + local_total[k] += node_vector(i, k) * phi; + } + } + for (int k = 0; k < 3; ++k) { + qp_vector(j, k) = local_total[k]; + } + } +}; + +} // namespace openturbine \ No newline at end of file diff --git a/src/restruct_poc/beams/interpolate_QP_velocity.hpp b/src/restruct_poc/beams/interpolate_QP_velocity.hpp deleted file mode 100644 index a9474860..00000000 --- a/src/restruct_poc/beams/interpolate_QP_velocity.hpp +++ /dev/null @@ -1,103 +0,0 @@ -#pragma once - -#include - -#include "src/restruct_poc/types.hpp" - -namespace openturbine { - -struct InterpolateQPVelocity_Translation { - Kokkos::View::const_type elem_indices; // Element indices - View_NxN::const_type shape_interp; // Num Nodes x Num Quadrature points - View_Nx6 node_u_dot; // Node translation & angular velocity - View_Nx3 qp_u_dot; // qp translation velocity - - KOKKOS_FUNCTION - void operator()(const int i_elem) const { - auto idx = elem_indices(i_elem); - for (int j_index = 0; j_index < idx.num_qps; ++j_index) { - const auto j = idx.qp_range.first + j_index; - auto local_total = Kokkos::Array{}; - for (int i_index = 0; i_index < idx.num_nodes; ++i_index) { - const auto i = idx.node_range.first + i_index; - const auto phi = shape_interp(i, j_index); - for (int k = 0; k < 3; ++k) { - local_total[k] += node_u_dot(i, k) * phi; - } - } - for (int k = 0; k < 3; ++k) { - qp_u_dot(j, k) = local_total[k]; - } - } - } - - KOKKOS_FUNCTION - void operator()(const int i_elem, const int j_index) const { - auto idx = elem_indices(i_elem); - if (j_index >= idx.num_qps) { - return; - } - - const auto j = idx.qp_range.first + j_index; - auto local_total = Kokkos::Array{}; - for (int i_index = 0; i_index < idx.num_nodes; ++i_index) { - const auto i = idx.node_range.first + i_index; - const auto phi = shape_interp(i, j_index); - for (int k = 0; k < 3; ++k) { - local_total[k] += node_u_dot(i, k) * phi; - } - } - for (int k = 0; k < 3; ++k) { - qp_u_dot(j, k) = local_total[k]; - } - } -}; - -struct InterpolateQPVelocity_Angular { - Kokkos::View::const_type elem_indices; // Element indices - View_NxN::const_type shape_interp; // Num Nodes x Num Quadrature points - View_Nx6 node_u_dot; // Node translation & angular velocity - View_Nx3 qp_omega; // qp angular velocity - - KOKKOS_FUNCTION - void operator()(const int i_elem) const { - auto idx = elem_indices(i_elem); - for (int j_index = 0; j_index < idx.num_qps; ++j_index) { - const auto j = idx.qp_range.first + j_index; - auto local_total = Kokkos::Array{}; - for (int i_index = 0; i_index < idx.num_nodes; ++i_index) { - const auto i = idx.node_range.first + i_index; - const auto phi = shape_interp(i, j_index); - for (int k = 0; k < 3; ++k) { - local_total[k] += node_u_dot(i, k + 3) * phi; - } - } - for (int k = 0; k < 3; ++k) { - qp_omega(j, k) = local_total[k]; - } - } - } - - KOKKOS_FUNCTION - void operator()(const int i_elem, const int j_index) const { - auto idx = elem_indices(i_elem); - if (j_index >= idx.num_qps) { - return; - } - - const auto j = idx.qp_range.first + j_index; - auto local_total = Kokkos::Array{}; - for (int i_index = 0; i_index < idx.num_nodes; ++i_index) { - const auto i = idx.node_range.first + i_index; - const auto phi = shape_interp(i, j_index); - for (int k = 0; k < 3; ++k) { - local_total[k] += node_u_dot(i, k + 3) * phi; - } - } - for (int k = 0; k < 3; ++k) { - qp_omega(j, k) = local_total[k]; - } - } -}; - -} // namespace openturbine diff --git a/src/restruct_poc/beams/interpolate_to_quadrature_points.hpp b/src/restruct_poc/beams/interpolate_to_quadrature_points.hpp new file mode 100644 index 00000000..81be91b2 --- /dev/null +++ b/src/restruct_poc/beams/interpolate_to_quadrature_points.hpp @@ -0,0 +1,83 @@ +#pragma once + +#include + +#include "beams.hpp" +#include "interpolate_QP_state.hpp" +#include "interpolate_QP_vector.hpp" + +#include "src/restruct_poc/types.hpp" + +namespace openturbine { + +struct InterpolateToQuadraturePoints { + Kokkos::View::const_type elem_indices; + View_NxN::const_type shape_interp; + View_NxN::const_type shape_deriv; + View_N::const_type qp_jacobian; + View_Nx7::const_type node_u; + View_Nx6::const_type node_u_dot; + View_Nx6::const_type node_u_ddot; + View_Nx3 qp_u; + View_Nx3 qp_uprime; + View_Nx4 qp_r; + View_Nx4 qp_rprime; + View_Nx3 qp_u_dot; + View_Nx3 qp_omega; + View_Nx3 qp_u_ddot; + View_Nx3 qp_omega_dot; + + KOKKOS_FUNCTION + void operator()(Kokkos::TeamPolicy<>::member_type member) const { + const auto i_elem = member.league_rank(); + const auto idx = elem_indices(i_elem); + const auto first_qp = idx.qp_range.first; + const auto first_node = idx.node_range.first; + const auto num_nodes = idx.num_nodes; + Kokkos::parallel_for( + Kokkos::TeamThreadRange(member, idx.num_qps), + InterpolateQPState_u{first_qp, first_node, num_nodes, shape_interp, node_u, qp_u} + ); + Kokkos::parallel_for( + Kokkos::TeamThreadRange(member, idx.num_qps), + InterpolateQPState_uprime{ + first_qp, first_node, num_nodes, shape_deriv, qp_jacobian, node_u, qp_uprime} + ); + Kokkos::parallel_for( + Kokkos::TeamThreadRange(member, idx.num_qps), + InterpolateQPState_r{first_qp, first_node, num_nodes, shape_interp, node_u, qp_r} + ); + Kokkos::parallel_for( + Kokkos::TeamThreadRange(member, idx.num_qps), + InterpolateQPState_rprime{ + first_qp, first_node, num_nodes, shape_deriv, qp_jacobian, node_u, qp_rprime} + ); + + Kokkos::parallel_for( + Kokkos::TeamThreadRange(member, idx.num_qps), + InterpolateQPVector{ + first_qp, first_node, num_nodes, shape_interp, + Kokkos::subview(node_u_dot, Kokkos::ALL, Kokkos::pair(0, 3)), qp_u_dot} + ); + Kokkos::parallel_for( + Kokkos::TeamThreadRange(member, idx.num_qps), + InterpolateQPVector{ + first_qp, first_node, num_nodes, shape_interp, + Kokkos::subview(node_u_dot, Kokkos::ALL, Kokkos::pair(3, 6)), qp_omega} + ); + Kokkos::parallel_for( + Kokkos::TeamThreadRange(member, idx.num_qps), + InterpolateQPVector{ + first_qp, first_node, num_nodes, shape_interp, + Kokkos::subview(node_u_ddot, Kokkos::ALL, Kokkos::pair(0, 3)), qp_u_ddot} + ); + Kokkos::parallel_for( + Kokkos::TeamThreadRange(member, idx.num_qps), + InterpolateQPVector{ + first_qp, first_node, num_nodes, shape_interp, + Kokkos::subview(node_u_ddot, Kokkos::ALL, Kokkos::pair(3, 6)), qp_omega_dot} + ); + } +}; + +} // namespace openturbine \ No newline at end of file diff --git a/src/restruct_poc/system/assemble_inertia_matrix.hpp b/src/restruct_poc/system/assemble_inertia_matrix.hpp index f4e5fdb3..425b634a 100644 --- a/src/restruct_poc/system/assemble_inertia_matrix.hpp +++ b/src/restruct_poc/system/assemble_inertia_matrix.hpp @@ -14,10 +14,7 @@ inline void AssembleInertiaMatrix( ) { auto region = Kokkos::Profiling::ScopedRegion("Assemble Inertia Matrix"); auto range_policy = Kokkos::TeamPolicy<>(beams.num_elems, Kokkos::AUTO()); - // const auto max_elem_qp = beams.max_elem_qps; - // const auto max_elem_nodes = beams.max_elem_nodes; - // const auto coeff_size = Kokkos::View::shmem_size(max_elem_nodes, max_elem_nodes, - // max_elem_qp); range_policy.set_scratch_size(1, Kokkos::PerTeam(coeff_size)); + Kokkos::parallel_for( "IntegrateInertiaMatrix", range_policy, @@ -26,13 +23,6 @@ inline void AssembleInertiaMatrix( beams.qp_Guu, beta_prime, gamma_prime, M} ); - // Kokkos::parallel_for( - // "IntegrateInertiaMatrix", Kokkos::MDRangePolicy{ - // {0, 0, 0}, {beams.num_elems, beams.max_elem_nodes, beams.max_elem_nodes}}, - // IntegrateInertiaMatrix{ - // beams.elem_indices, beams.qp_weight, beams.qp_jacobian, - // beams.shape_interp, beams.qp_Muu, beams.qp_Guu, beta_prime, gamma_prime, M} - // ); } } // namespace openturbine diff --git a/src/restruct_poc/system/update_state.hpp b/src/restruct_poc/system/update_state.hpp index d0a3b052..4f5682db 100644 --- a/src/restruct_poc/system/update_state.hpp +++ b/src/restruct_poc/system/update_state.hpp @@ -21,9 +21,7 @@ #include "update_node_state.hpp" #include "src/restruct_poc/beams/beams.hpp" -#include "src/restruct_poc/beams/interpolate_QP_acceleration.hpp" -#include "src/restruct_poc/beams/interpolate_QP_state.hpp" -#include "src/restruct_poc/beams/interpolate_QP_velocity.hpp" +#include "src/restruct_poc/beams/interpolate_to_quadrature_points.hpp" #include "src/restruct_poc/types.hpp" namespace openturbine { @@ -44,55 +42,14 @@ inline void UpdateState(Beams& beams, View_Nx7 Q, View_Nx6 V, View_Nx6 A) { ); auto range_policy = Kokkos::TeamPolicy<>(beams.num_elems, Kokkos::AUTO()); + Kokkos::parallel_for( - "InterpolateQpU", Kokkos::MDRangePolicy{{0, 0}, {beams.num_elems, beams.max_elem_qps}}, - InterpolateQPU{beams.elem_indices, beams.shape_interp, beams.node_u, beams.qp_u} - ); - Kokkos::parallel_for( - "InterpolateQpU_Prime", Kokkos::MDRangePolicy{{0, 0}, {beams.num_elems, beams.max_elem_qps}}, - InterpolateQPU_Prime{ - beams.elem_indices, beams.shape_deriv, beams.qp_jacobian, beams.node_u, beams.qp_u_prime} - ); - Kokkos::parallel_for( - "InterpolateQpR", Kokkos::MDRangePolicy{{0, 0}, {beams.num_elems, beams.max_elem_qps}}, - InterpolateQPR{beams.elem_indices, beams.shape_interp, beams.node_u, beams.qp_r} - ); - Kokkos::parallel_for( - "InterpolateQpR_Prime", Kokkos::MDRangePolicy{{0, 0}, {beams.num_elems, beams.max_elem_qps}}, - InterpolateQPR_Prime{ - beams.elem_indices, beams.shape_deriv, beams.qp_jacobian, beams.node_u, beams.qp_r_prime} - ); - Kokkos::parallel_for( - "InterpolateQPVelocity_Translation", - Kokkos::MDRangePolicy{{0, 0}, {beams.num_elems, beams.max_elem_qps}}, - InterpolateQPVelocity_Translation{ - beams.elem_indices, beams.shape_interp, beams.node_u_dot, beams.qp_u_dot} - ); - Kokkos::parallel_for( - "InterpolateQPVelocity_Angular", - Kokkos::MDRangePolicy{{0, 0}, {beams.num_elems, beams.max_elem_qps}}, - InterpolateQPVelocity_Angular{ - beams.elem_indices, - beams.shape_interp, - beams.node_u_dot, - beams.qp_omega, - } - ); - Kokkos::parallel_for( - "InterpolateQPAcceleration_Translation", - Kokkos::MDRangePolicy{{0, 0}, {beams.num_elems, beams.max_elem_qps}}, - InterpolateQPAcceleration_Translation{ - beams.elem_indices, beams.shape_interp, beams.node_u_ddot, beams.qp_u_ddot} - ); - Kokkos::parallel_for( - "InterpolateQPAcceleration_Angular", - Kokkos::MDRangePolicy{{0, 0}, {beams.num_elems, beams.max_elem_qps}}, - InterpolateQPAcceleration_Angular{ - beams.elem_indices, - beams.shape_interp, - beams.node_u_ddot, - beams.qp_omega_dot, - } + "InterpolateToQuadraturePoints", range_policy, + InterpolateToQuadraturePoints{ + beams.elem_indices, beams.shape_interp, beams.shape_deriv, beams.qp_jacobian, + beams.node_u, beams.node_u_dot, beams.node_u_ddot, beams.qp_u, beams.qp_u_prime, + beams.qp_r, beams.qp_r_prime, beams.qp_u_dot, beams.qp_omega, beams.qp_u_ddot, + beams.qp_omega_dot} ); Kokkos::parallel_for( diff --git a/tests/unit_tests/restruct_poc/CMakeLists.txt b/tests/unit_tests/restruct_poc/CMakeLists.txt index b14d3a73..4a758289 100644 --- a/tests/unit_tests/restruct_poc/CMakeLists.txt +++ b/tests/unit_tests/restruct_poc/CMakeLists.txt @@ -10,6 +10,8 @@ target_sources( test_math.cpp test_utilities.cpp test_controller.cpp + beams/test_interpolate_QP_state.cpp + beams/test_interpolate_QP_vector.cpp solver/test_compute_number_of_non_zeros.cpp solver/test_copy_into_sparse_matrix.cpp solver/test_populate_sparse_indices.cpp diff --git a/tests/unit_tests/restruct_poc/beams/test_interpolate_QP.hpp b/tests/unit_tests/restruct_poc/beams/test_interpolate_QP.hpp new file mode 100644 index 00000000..2ac289cf --- /dev/null +++ b/tests/unit_tests/restruct_poc/beams/test_interpolate_QP.hpp @@ -0,0 +1,124 @@ +#pragma once + +#include +#include + +namespace openturbine::restruct_poc::tests { + +inline auto create_shape_interp_OneNodeOneQP() { + constexpr auto num_qp = 1; + constexpr auto num_nodes = 1; + constexpr auto num_entries = num_qp * num_nodes; + auto shape_interp = Kokkos::View("shape_interp"); + auto shape_interp_mirror = Kokkos::create_mirror(shape_interp); + + auto host_data = std::array{2.}; + auto shape_interp_host = + Kokkos::View(host_data.data()); + Kokkos::deep_copy(shape_interp_mirror, shape_interp_host); + Kokkos::deep_copy(shape_interp, shape_interp_mirror); + return shape_interp; +} + +inline auto create_shape_deriv_OneNodeOneQP() { + constexpr auto num_qp = 1; + constexpr auto num_nodes = 1; + constexpr auto num_entries = num_qp * num_nodes; + auto shape_deriv = Kokkos::View("shape_deriv"); + auto shape_deriv_mirror = Kokkos::create_mirror(shape_deriv); + + auto host_data = std::array{4.}; + auto shape_deriv_host = + Kokkos::View(host_data.data()); + Kokkos::deep_copy(shape_deriv_mirror, shape_deriv_host); + Kokkos::deep_copy(shape_deriv, shape_deriv_mirror); + return shape_deriv; +} + +inline auto create_jacobian_OneQP() { + constexpr auto num_qp = 1; + constexpr auto num_entries = num_qp; + auto jacobian = Kokkos::View("jacobian"); + auto jacobian_mirror = Kokkos::create_mirror(jacobian); + + auto host_data = std::array{2.}; + auto jacobian_host = Kokkos::View(host_data.data()); + Kokkos::deep_copy(jacobian_mirror, jacobian_host); + Kokkos::deep_copy(jacobian, jacobian_mirror); + return jacobian; +} + +inline auto create_shape_interp_OneNodeTwoQP() { + constexpr auto num_qp = 2; + constexpr auto num_nodes = 1; + constexpr auto num_entries = num_qp * num_nodes; + auto shape_interp = Kokkos::View("shape_interp"); + auto shape_interp_mirror = Kokkos::create_mirror(shape_interp); + + auto host_data = std::array{2., 4.}; + auto shape_interp_host = + Kokkos::View(host_data.data()); + Kokkos::deep_copy(shape_interp_mirror, shape_interp_host); + Kokkos::deep_copy(shape_interp, shape_interp_mirror); + return shape_interp; +} + +inline auto create_shape_deriv_OneNodeTwoQP() { + constexpr auto num_qp = 2; + constexpr auto num_nodes = 1; + constexpr auto num_entries = num_qp * num_nodes; + auto shape_deriv = Kokkos::View("shape_deriv"); + auto shape_deriv_mirror = Kokkos::create_mirror(shape_deriv); + + auto host_data = std::array{4., 9.}; + auto shape_deriv_host = + Kokkos::View(host_data.data()); + Kokkos::deep_copy(shape_deriv_mirror, shape_deriv_host); + Kokkos::deep_copy(shape_deriv, shape_deriv_mirror); + return shape_deriv; +} + +inline auto create_jacobian_TwoQP() { + constexpr auto num_qp = 2; + constexpr auto num_entries = num_qp; + auto jacobian = Kokkos::View("jacobian"); + auto jacobian_mirror = Kokkos::create_mirror(jacobian); + + auto host_data = std::array{2., 3.}; + auto jacobian_host = Kokkos::View(host_data.data()); + Kokkos::deep_copy(jacobian_mirror, jacobian_host); + Kokkos::deep_copy(jacobian, jacobian_mirror); + return jacobian; +} + +inline auto create_shape_interp_TwoNodeTwoQP() { + constexpr auto num_qp = 2; + constexpr auto num_nodes = 2; + constexpr auto num_entries = num_qp * num_nodes; + auto shape_interp = Kokkos::View("shape_interp"); + auto shape_interp_mirror = Kokkos::create_mirror(shape_interp); + + auto host_data = std::array{2., 3., 4., 5.}; + auto shape_interp_host = + Kokkos::View(host_data.data()); + Kokkos::deep_copy(shape_interp_mirror, shape_interp_host); + Kokkos::deep_copy(shape_interp, shape_interp_mirror); + return shape_interp; +} + +inline auto create_shape_deriv_TwoNodeTwoQP() { + constexpr auto num_qp = 2; + constexpr auto num_nodes = 2; + constexpr auto num_entries = num_qp * num_nodes; + auto shape_deriv = Kokkos::View("shape_deriv"); + auto shape_deriv_mirror = Kokkos::create_mirror(shape_deriv); + + auto host_data = std::array{4., 9., 8., 15.}; + auto shape_deriv_host = + Kokkos::View(host_data.data()); + Kokkos::deep_copy(shape_deriv_mirror, shape_deriv_host); + Kokkos::deep_copy(shape_deriv, shape_deriv_mirror); + return shape_deriv; +} + +} // namespace openturbine::restruct_poc::tests \ No newline at end of file diff --git a/tests/unit_tests/restruct_poc/beams/test_interpolate_QP_state.cpp b/tests/unit_tests/restruct_poc/beams/test_interpolate_QP_state.cpp new file mode 100644 index 00000000..b1282f16 --- /dev/null +++ b/tests/unit_tests/restruct_poc/beams/test_interpolate_QP_state.cpp @@ -0,0 +1,325 @@ +#include +#include + +#include "test_interpolate_QP.hpp" + +#include "src/restruct_poc/beams/interpolate_QP_state.hpp" + +namespace openturbine::restruct_poc::tests { + +inline auto create_node_u_OneNode() { + constexpr auto num_nodes = 1; + constexpr auto num_entries = num_nodes * 7; + auto node_u = Kokkos::View("node_u"); + auto node_u_mirror = Kokkos::create_mirror(node_u); + + auto host_data = std::array{1., 2., 3., 4., 5., 6., 7.}; + auto node_u_host = Kokkos::View(host_data.data()); + Kokkos::deep_copy(node_u_mirror, node_u_host); + Kokkos::deep_copy(node_u, node_u_mirror); + return node_u; +} + +TEST(InterpolateQPStateTests, u_OneNodeOneQP) { + constexpr auto first_qp = 0; + constexpr auto num_qp = 1; + constexpr auto first_node = 0; + constexpr auto num_nodes = 1; + auto shape_interp = create_shape_interp_OneNodeOneQP(); + auto node_u = create_node_u_OneNode(); + auto qp_u = Kokkos::View("qp_u"); + Kokkos::parallel_for( + num_qp, InterpolateQPState_u{first_qp, first_node, num_nodes, shape_interp, node_u, qp_u} + ); + auto qp_u_mirror = Kokkos::create_mirror(qp_u); + Kokkos::deep_copy(qp_u_mirror, qp_u); + constexpr auto tolerance = 1.e-16; + EXPECT_NEAR(qp_u_mirror(0, 0), 2., tolerance); + EXPECT_NEAR(qp_u_mirror(0, 1), 4., tolerance); + EXPECT_NEAR(qp_u_mirror(0, 2), 6., tolerance); +} + +TEST(InterpolateQPStateTests, uprime_OneNodeOneQP) { + constexpr auto first_qp = 0; + constexpr auto num_qp = 1; + constexpr auto first_node = 0; + constexpr auto num_nodes = 1; + auto shape_deriv = create_shape_deriv_OneNodeOneQP(); + auto jacobian = create_jacobian_OneQP(); + auto node_u = create_node_u_OneNode(); + auto qp_uprime = Kokkos::View("qp_uprime"); + Kokkos::parallel_for( + num_qp, + InterpolateQPState_uprime{ + first_qp, first_node, num_nodes, shape_deriv, jacobian, node_u, qp_uprime} + ); + auto qp_uprime_mirror = Kokkos::create_mirror(qp_uprime); + Kokkos::deep_copy(qp_uprime_mirror, qp_uprime); + constexpr auto tolerance = 1.e-16; + EXPECT_NEAR(qp_uprime_mirror(0, 0), 2., tolerance); + EXPECT_NEAR(qp_uprime_mirror(0, 1), 4., tolerance); + EXPECT_NEAR(qp_uprime_mirror(0, 2), 6., tolerance); +} + +TEST(InterpolateQPStateTests, r_OneNodeOneQP) { + constexpr auto first_qp = 0; + constexpr auto num_qp = 1; + constexpr auto first_node = 0; + constexpr auto num_nodes = 1; + auto shape_interp = create_shape_interp_OneNodeOneQP(); + auto node_u = create_node_u_OneNode(); + auto qp_r = Kokkos::View("qp_r"); + Kokkos::parallel_for( + num_qp, InterpolateQPState_r{first_qp, first_node, num_nodes, shape_interp, node_u, qp_r} + ); + auto qp_r_mirror = Kokkos::create_mirror(qp_r); + Kokkos::deep_copy(qp_r_mirror, qp_r); + constexpr auto tolerance = 1.e-16; + EXPECT_NEAR(qp_r_mirror(0, 0), 8., tolerance); + EXPECT_NEAR(qp_r_mirror(0, 1), 10., tolerance); + EXPECT_NEAR(qp_r_mirror(0, 2), 12., tolerance); + EXPECT_NEAR(qp_r_mirror(0, 3), 14., tolerance); +} + +TEST(InterpolateQPStateTests, rprime_OneNodeOneQP) { + constexpr auto first_qp = 0; + constexpr auto num_qp = 1; + constexpr auto first_node = 0; + constexpr auto num_nodes = 1; + auto shape_deriv = create_shape_deriv_OneNodeOneQP(); + auto jacobian = create_jacobian_OneQP(); + auto node_u = create_node_u_OneNode(); + auto qp_rprime = Kokkos::View("qp_uprime"); + Kokkos::parallel_for( + num_qp, + InterpolateQPState_rprime{ + first_qp, first_node, num_nodes, shape_deriv, jacobian, node_u, qp_rprime} + ); + auto qp_rprime_mirror = Kokkos::create_mirror(qp_rprime); + Kokkos::deep_copy(qp_rprime_mirror, qp_rprime); + constexpr auto tolerance = 1.e-16; + EXPECT_NEAR(qp_rprime_mirror(0, 0), 8., tolerance); + EXPECT_NEAR(qp_rprime_mirror(0, 1), 10., tolerance); + EXPECT_NEAR(qp_rprime_mirror(0, 2), 12., tolerance); + EXPECT_NEAR(qp_rprime_mirror(0, 3), 14., tolerance); +} + +TEST(InterpolateQPStateTests, u_OneNodeTwoQP) { + constexpr auto first_qp = 0; + constexpr auto num_qp = 2; + constexpr auto first_node = 0; + constexpr auto num_nodes = 1; + auto shape_interp = create_shape_interp_OneNodeTwoQP(); + auto node_u = create_node_u_OneNode(); + auto qp_u = Kokkos::View("qp_u"); + Kokkos::parallel_for( + num_qp, InterpolateQPState_u{first_qp, first_node, num_nodes, shape_interp, node_u, qp_u} + ); + auto qp_u_mirror = Kokkos::create_mirror(qp_u); + Kokkos::deep_copy(qp_u_mirror, qp_u); + constexpr auto tolerance = 1.e-16; + EXPECT_NEAR(qp_u_mirror(0, 0), 2., tolerance); + EXPECT_NEAR(qp_u_mirror(0, 1), 4., tolerance); + EXPECT_NEAR(qp_u_mirror(0, 2), 6., tolerance); + + EXPECT_NEAR(qp_u_mirror(1, 0), 4., tolerance); + EXPECT_NEAR(qp_u_mirror(1, 1), 8., tolerance); + EXPECT_NEAR(qp_u_mirror(1, 2), 12., tolerance); +} + +TEST(InterpolateQPStateTests, uprime_OneNodeTwoQP) { + constexpr auto first_qp = 0; + constexpr auto num_qp = 2; + constexpr auto first_node = 0; + constexpr auto num_nodes = 1; + auto shape_deriv = create_shape_deriv_OneNodeTwoQP(); + auto jacobian = create_jacobian_TwoQP(); + auto node_u = create_node_u_OneNode(); + auto qp_uprime = Kokkos::View("qp_uprime"); + Kokkos::parallel_for( + num_qp, + InterpolateQPState_uprime{ + first_qp, first_node, num_nodes, shape_deriv, jacobian, node_u, qp_uprime} + ); + auto qp_uprime_mirror = Kokkos::create_mirror(qp_uprime); + Kokkos::deep_copy(qp_uprime_mirror, qp_uprime); + constexpr auto tolerance = 1.e-16; + EXPECT_NEAR(qp_uprime_mirror(0, 0), 2., tolerance); + EXPECT_NEAR(qp_uprime_mirror(0, 1), 4., tolerance); + EXPECT_NEAR(qp_uprime_mirror(0, 2), 6., tolerance); + + EXPECT_NEAR(qp_uprime_mirror(1, 0), 3., tolerance); + EXPECT_NEAR(qp_uprime_mirror(1, 1), 6., tolerance); + EXPECT_NEAR(qp_uprime_mirror(1, 2), 9., tolerance); +} + +TEST(InterpolateQPStateTests, r_OneNodeTwoQP) { + constexpr auto first_qp = 0; + constexpr auto num_qp = 2; + constexpr auto first_node = 0; + constexpr auto num_nodes = 1; + auto shape_interp = create_shape_interp_OneNodeTwoQP(); + auto node_u = create_node_u_OneNode(); + auto qp_r = Kokkos::View("qp_r"); + Kokkos::parallel_for( + num_qp, InterpolateQPState_r{first_qp, first_node, num_nodes, shape_interp, node_u, qp_r} + ); + auto qp_r_mirror = Kokkos::create_mirror(qp_r); + Kokkos::deep_copy(qp_r_mirror, qp_r); + constexpr auto tolerance = 1.e-16; + EXPECT_NEAR(qp_r_mirror(0, 0), 8., tolerance); + EXPECT_NEAR(qp_r_mirror(0, 1), 10., tolerance); + EXPECT_NEAR(qp_r_mirror(0, 2), 12., tolerance); + EXPECT_NEAR(qp_r_mirror(0, 3), 14., tolerance); + + EXPECT_NEAR(qp_r_mirror(1, 0), 16., tolerance); + EXPECT_NEAR(qp_r_mirror(1, 1), 20., tolerance); + EXPECT_NEAR(qp_r_mirror(1, 2), 24., tolerance); + EXPECT_NEAR(qp_r_mirror(1, 3), 28., tolerance); +} + +TEST(InterpolateQPStateTests, rprime_OneNodeTwoQP) { + constexpr auto first_qp = 0; + constexpr auto num_qp = 2; + constexpr auto first_node = 0; + constexpr auto num_nodes = 1; + auto shape_deriv = create_shape_deriv_OneNodeTwoQP(); + auto jacobian = create_jacobian_TwoQP(); + auto node_u = create_node_u_OneNode(); + auto qp_rprime = Kokkos::View("qp_uprime"); + Kokkos::parallel_for( + num_qp, + InterpolateQPState_rprime{ + first_qp, first_node, num_nodes, shape_deriv, jacobian, node_u, qp_rprime} + ); + auto qp_rprime_mirror = Kokkos::create_mirror(qp_rprime); + Kokkos::deep_copy(qp_rprime_mirror, qp_rprime); + constexpr auto tolerance = 1.e-16; + EXPECT_NEAR(qp_rprime_mirror(0, 0), 8., tolerance); + EXPECT_NEAR(qp_rprime_mirror(0, 1), 10., tolerance); + EXPECT_NEAR(qp_rprime_mirror(0, 2), 12., tolerance); + EXPECT_NEAR(qp_rprime_mirror(0, 3), 14., tolerance); + + EXPECT_NEAR(qp_rprime_mirror(1, 0), 12., tolerance); + EXPECT_NEAR(qp_rprime_mirror(1, 1), 15., tolerance); + EXPECT_NEAR(qp_rprime_mirror(1, 2), 18., tolerance); + EXPECT_NEAR(qp_rprime_mirror(1, 3), 21., tolerance); +} + +inline auto create_node_u_TwoNode() { + constexpr auto num_nodes = 2; + constexpr auto num_entries = num_nodes * 7; + auto node_u = Kokkos::View("node_u"); + auto node_u_mirror = Kokkos::create_mirror(node_u); + + auto host_data = + std::array{1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12., 13., 14.}; + auto node_u_host = Kokkos::View(host_data.data()); + Kokkos::deep_copy(node_u_mirror, node_u_host); + Kokkos::deep_copy(node_u, node_u_mirror); + return node_u; +} + +TEST(InterpolateQPStateTests, u_TwoNodeTwoQP) { + constexpr auto first_qp = 0; + constexpr auto num_qp = 2; + constexpr auto first_node = 0; + constexpr auto num_nodes = 2; + auto shape_interp = create_shape_interp_TwoNodeTwoQP(); + auto node_u = create_node_u_TwoNode(); + auto qp_u = Kokkos::View("qp_u"); + Kokkos::parallel_for( + num_qp, InterpolateQPState_u{first_qp, first_node, num_nodes, shape_interp, node_u, qp_u} + ); + auto qp_u_mirror = Kokkos::create_mirror(qp_u); + Kokkos::deep_copy(qp_u_mirror, qp_u); + constexpr auto tolerance = 1.e-16; + EXPECT_NEAR(qp_u_mirror(0, 0), 34., tolerance); + EXPECT_NEAR(qp_u_mirror(0, 1), 40., tolerance); + EXPECT_NEAR(qp_u_mirror(0, 2), 46., tolerance); + + EXPECT_NEAR(qp_u_mirror(1, 0), 43., tolerance); + EXPECT_NEAR(qp_u_mirror(1, 1), 51., tolerance); + EXPECT_NEAR(qp_u_mirror(1, 2), 59., tolerance); +} + +TEST(InterpolateQPStateTests, uprime_TwoNodeTwoQP) { + constexpr auto first_qp = 0; + constexpr auto num_qp = 2; + constexpr auto first_node = 0; + constexpr auto num_nodes = 2; + auto shape_deriv = create_shape_deriv_TwoNodeTwoQP(); + auto jacobian = create_jacobian_TwoQP(); + auto node_u = create_node_u_TwoNode(); + auto qp_uprime = Kokkos::View("qp_uprime"); + Kokkos::parallel_for( + num_qp, + InterpolateQPState_uprime{ + first_qp, first_node, num_nodes, shape_deriv, jacobian, node_u, qp_uprime} + ); + auto qp_uprime_mirror = Kokkos::create_mirror(qp_uprime); + Kokkos::deep_copy(qp_uprime_mirror, qp_uprime); + constexpr auto tolerance = 1.e-16; + EXPECT_NEAR(qp_uprime_mirror(0, 0), 34., tolerance); + EXPECT_NEAR(qp_uprime_mirror(0, 1), 40., tolerance); + EXPECT_NEAR(qp_uprime_mirror(0, 2), 46., tolerance); + + EXPECT_NEAR(qp_uprime_mirror(1, 0), 43., tolerance); + EXPECT_NEAR(qp_uprime_mirror(1, 1), 51., tolerance); + EXPECT_NEAR(qp_uprime_mirror(1, 2), 59., tolerance); +} + +TEST(InterpolateQPStateTests, r_TwoNodeTwoQP) { + constexpr auto first_qp = 0; + constexpr auto num_qp = 2; + constexpr auto first_node = 0; + constexpr auto num_nodes = 2; + auto shape_interp = create_shape_interp_TwoNodeTwoQP(); + auto node_u = create_node_u_TwoNode(); + auto qp_r = Kokkos::View("qp_r"); + Kokkos::parallel_for( + num_qp, InterpolateQPState_r{first_qp, first_node, num_nodes, shape_interp, node_u, qp_r} + ); + auto qp_r_mirror = Kokkos::create_mirror(qp_r); + Kokkos::deep_copy(qp_r_mirror, qp_r); + constexpr auto tolerance = 1.e-16; + EXPECT_NEAR(qp_r_mirror(0, 0), 52., tolerance); + EXPECT_NEAR(qp_r_mirror(0, 1), 58., tolerance); + EXPECT_NEAR(qp_r_mirror(0, 2), 64., tolerance); + EXPECT_NEAR(qp_r_mirror(0, 3), 70., tolerance); + + EXPECT_NEAR(qp_r_mirror(1, 0), 67., tolerance); + EXPECT_NEAR(qp_r_mirror(1, 1), 75., tolerance); + EXPECT_NEAR(qp_r_mirror(1, 2), 83., tolerance); + EXPECT_NEAR(qp_r_mirror(1, 3), 91., tolerance); +} + +TEST(InterpolateQPStateTests, rprime_TwoNodeTwoQP) { + constexpr auto first_qp = 0; + constexpr auto num_qp = 2; + constexpr auto first_node = 0; + constexpr auto num_nodes = 2; + auto shape_deriv = create_shape_deriv_TwoNodeTwoQP(); + auto jacobian = create_jacobian_TwoQP(); + auto node_u = create_node_u_TwoNode(); + auto qp_rprime = Kokkos::View("qp_uprime"); + Kokkos::parallel_for( + num_qp, + InterpolateQPState_rprime{ + first_qp, first_node, num_nodes, shape_deriv, jacobian, node_u, qp_rprime} + ); + auto qp_rprime_mirror = Kokkos::create_mirror(qp_rprime); + Kokkos::deep_copy(qp_rprime_mirror, qp_rprime); + constexpr auto tolerance = 1.e-16; + EXPECT_NEAR(qp_rprime_mirror(0, 0), 52., tolerance); + EXPECT_NEAR(qp_rprime_mirror(0, 1), 58., tolerance); + EXPECT_NEAR(qp_rprime_mirror(0, 2), 64., tolerance); + EXPECT_NEAR(qp_rprime_mirror(0, 3), 70., tolerance); + + EXPECT_NEAR(qp_rprime_mirror(1, 0), 67., tolerance); + EXPECT_NEAR(qp_rprime_mirror(1, 1), 75., tolerance); + EXPECT_NEAR(qp_rprime_mirror(1, 2), 83., tolerance); + EXPECT_NEAR(qp_rprime_mirror(1, 3), 91., tolerance); +} + +} // namespace openturbine::restruct_poc::tests \ No newline at end of file diff --git a/tests/unit_tests/restruct_poc/beams/test_interpolate_QP_vector.cpp b/tests/unit_tests/restruct_poc/beams/test_interpolate_QP_vector.cpp new file mode 100644 index 00000000..239aa04b --- /dev/null +++ b/tests/unit_tests/restruct_poc/beams/test_interpolate_QP_vector.cpp @@ -0,0 +1,111 @@ +#include +#include + +#include "test_interpolate_QP.hpp" + +#include "src/restruct_poc/beams/interpolate_QP_vector.hpp" + +namespace openturbine::restruct_poc::tests { + +inline auto create_node_u_dot_OneNode() { + constexpr auto num_nodes = 1; + constexpr auto num_entries = num_nodes * 6; + auto node_u = Kokkos::View("node_u_dot"); + auto node_u_mirror = Kokkos::create_mirror(node_u); + + auto host_data = std::array{1., 2., 3., 4., 5., 6.}; + auto node_u_host = Kokkos::View(host_data.data()); + Kokkos::deep_copy(node_u_mirror, node_u_host); + Kokkos::deep_copy(node_u, node_u_mirror); + return node_u; +} + +TEST(InterpolateQPVectorTests, OneNodeOneQP) { + constexpr auto first_qp = 0; + constexpr auto num_qp = 1; + constexpr auto first_node = 0; + constexpr auto num_nodes = 1; + auto shape_interp = create_shape_interp_OneNodeOneQP(); + auto node_u_dot = create_node_u_dot_OneNode(); + auto qp_u_dot = Kokkos::View("qp_u_dot"); + Kokkos::parallel_for( + num_qp, + InterpolateQPVector{ + first_qp, first_node, num_nodes, shape_interp, + Kokkos::subview(node_u_dot, Kokkos::ALL, Kokkos::pair(0, 3)), qp_u_dot} + ); + auto qp_u_dot_mirror = Kokkos::create_mirror(qp_u_dot); + Kokkos::deep_copy(qp_u_dot_mirror, qp_u_dot); + constexpr auto tolerance = 1.e-16; + EXPECT_NEAR(qp_u_dot_mirror(0, 0), 2., tolerance); + EXPECT_NEAR(qp_u_dot_mirror(0, 1), 4., tolerance); + EXPECT_NEAR(qp_u_dot_mirror(0, 2), 6., tolerance); +} + +TEST(InterpolateQPVectorTests, OneNodeTwoQP) { + constexpr auto first_qp = 0; + constexpr auto num_qp = 2; + constexpr auto first_node = 0; + constexpr auto num_nodes = 1; + auto shape_interp = create_shape_interp_OneNodeTwoQP(); + auto node_u_dot = create_node_u_dot_OneNode(); + auto qp_u_dot = Kokkos::View("qp_u_dot"); + Kokkos::parallel_for( + num_qp, + InterpolateQPVector{ + first_qp, first_node, num_nodes, shape_interp, + Kokkos::subview(node_u_dot, Kokkos::ALL, Kokkos::pair(0, 3)), qp_u_dot} + ); + auto qp_u_dot_mirror = Kokkos::create_mirror(qp_u_dot); + Kokkos::deep_copy(qp_u_dot_mirror, qp_u_dot); + constexpr auto tolerance = 1.e-16; + EXPECT_NEAR(qp_u_dot_mirror(0, 0), 2., tolerance); + EXPECT_NEAR(qp_u_dot_mirror(0, 1), 4., tolerance); + EXPECT_NEAR(qp_u_dot_mirror(0, 2), 6., tolerance); + + EXPECT_NEAR(qp_u_dot_mirror(1, 0), 4., tolerance); + EXPECT_NEAR(qp_u_dot_mirror(1, 1), 8., tolerance); + EXPECT_NEAR(qp_u_dot_mirror(1, 2), 12., tolerance); +} + +inline auto create_node_u_dot_TwoNode() { + constexpr auto num_nodes = 2; + constexpr auto num_entries = num_nodes * 6; + auto node_u_dot = Kokkos::View("node_u_dot"); + auto node_u_dot_mirror = Kokkos::create_mirror(node_u_dot); + + auto host_data = + std::array{1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12.}; + auto node_u_dot_host = Kokkos::View(host_data.data()); + Kokkos::deep_copy(node_u_dot_mirror, node_u_dot_host); + Kokkos::deep_copy(node_u_dot, node_u_dot_mirror); + return node_u_dot; +} + +TEST(InterpolateQPVectorTests, TwoNodeTwoQP) { + constexpr auto first_qp = 0; + constexpr auto num_qp = 2; + constexpr auto first_node = 0; + constexpr auto num_nodes = 2; + auto shape_interp = create_shape_interp_TwoNodeTwoQP(); + auto node_u_dot = create_node_u_dot_TwoNode(); + auto qp_u_dot = Kokkos::View("qp_u_dot"); + Kokkos::parallel_for( + num_qp, + InterpolateQPVector{ + first_qp, first_node, num_nodes, shape_interp, + Kokkos::subview(node_u_dot, Kokkos::ALL, Kokkos::pair(0, 3)), qp_u_dot} + ); + auto qp_u_dot_mirror = Kokkos::create_mirror(qp_u_dot); + Kokkos::deep_copy(qp_u_dot_mirror, qp_u_dot); + constexpr auto tolerance = 1.e-16; + EXPECT_NEAR(qp_u_dot_mirror(0, 0), 30., tolerance); + EXPECT_NEAR(qp_u_dot_mirror(0, 1), 36., tolerance); + EXPECT_NEAR(qp_u_dot_mirror(0, 2), 42., tolerance); + + EXPECT_NEAR(qp_u_dot_mirror(1, 0), 38., tolerance); + EXPECT_NEAR(qp_u_dot_mirror(1, 1), 46., tolerance); + EXPECT_NEAR(qp_u_dot_mirror(1, 2), 54., tolerance); +} + +} // namespace openturbine::restruct_poc::tests \ No newline at end of file