diff --git a/packages/intrepid2/src/Discretization/Basis/Intrepid2_Basis.hpp b/packages/intrepid2/src/Discretization/Basis/Intrepid2_Basis.hpp index 74b34efb6681..5779d95741e8 100644 --- a/packages/intrepid2/src/Discretization/Basis/Intrepid2_Basis.hpp +++ b/packages/intrepid2/src/Discretization/Basis/Intrepid2_Basis.hpp @@ -379,6 +379,61 @@ using HostBasisPtr = BasisPtrinputPoints is only used to deduce the type of the points where to evaluate basis functions. + The rank of inputPoints and its size are not relevant, however, + when using DFAD types, inputPoints cannot be empty, + otherwise the size of the scracth space needed won't be deduced correctly. + + \param space [in] - inputPoints + \param perTeamSpaceSize [out] - size of the scratch space needed per team + \param perThreadeSize [out] - size of the scratch space beeded per thread + */ + virtual + void getScratchSpaceSize( ordinal_type& perTeamSpaceSize, + ordinal_type& perThreadSpaceSize, + const PointViewType inputPoints, + const EOperator operatorType = OPERATOR_VALUE) const { + INTREPID2_TEST_FOR_EXCEPTION_DEVICE_SAFE( true, std::logic_error, + ">>> ERROR (Basis::getValuesScratchSpace): this method is not supported or should be overridden accordingly by derived classes."); + } + + + /** \brief Team-level evaluation of basis functions on a reference cell. + + Returns values of operatorType acting on basis functions for a set of + points in the reference cell for which the basis is defined. + + The interface allow also to select basis functions associated to a particular entity. + As an example, if subcellDim==1 (edges) and subcellOrdinal==0, outputValues will contain all the basis functions associated with the first edge. + outputValues will contain all the cell basis functions when the default value (-1) is used for subcellDim and subcellOrdinal + + \param outputValues [out] - variable rank array with the basis values + \param inputPoints [in] - rank-2 array (P,D) with the evaluation points + \param operatorType [in] - the operator acting on the basis functions + \param teamMember [in] - team member of the Kokkos::TemaPolicy + \param scratchStorage [in] - scratch space to use by each team + \param subcellDim [in] - the dimension of the subcells, the default values of -1 returns basis functions associated to subcells of all dimensions + \param subcellOrdinal [in] - the ordinal of the subcell, the default values of -1 returns basis functions associated to subcells of all ordinals + + \remark This function is supposed to be called within a TeamPolicy kernel. + The size of the required scratch space is determined by the getScratchSpaceSize function. + */ + KOKKOS_INLINE_FUNCTION + virtual + void getValues( OutputViewType /* outputValues */, + const PointViewType /* inputPoints */, + const EOperator /* operatorType */, + const typename Kokkos::TeamPolicy::member_type& teamMember, + const typename ExecutionSpace::scratch_memory_space &scratchStorage, + const ordinal_type subcellDim=-1, + const ordinal_type subcellOrdinal=-1) const { + INTREPID2_TEST_FOR_EXCEPTION_DEVICE_SAFE( true, std::logic_error, + ">>> ERROR (Basis::getValues): this method is not supported or should be overridden accordingly by derived classes."); + } + /** \brief Evaluation of a FEM basis on a reference cell. Returns values of operatorType acting on FEM basis functions for a set of diff --git a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HCURL_HEX_I1_FEM.hpp b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HCURL_HEX_I1_FEM.hpp index 299054557fca..72d0e9112c01 100644 --- a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HCURL_HEX_I1_FEM.hpp +++ b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HCURL_HEX_I1_FEM.hpp @@ -185,6 +185,23 @@ namespace Intrepid2 { operatorType ); } + virtual void + getScratchSpaceSize( ordinal_type& perTeamSpaceSize, + ordinal_type& perThreadSpaceSize, + const PointViewType inputPointsconst, + const EOperator operatorType = OPERATOR_VALUE) const override; + + KOKKOS_INLINE_FUNCTION + virtual void + getValues( + OutputViewType outputValues, + const PointViewType inputPoints, + const EOperator operatorType, + const typename Kokkos::TeamPolicy::member_type& team_member, + const typename DeviceType::execution_space::scratch_memory_space & scratchStorage, + const ordinal_type subcellDim = -1, + const ordinal_type subcellOrdinal = -1) const override; + virtual void getDofCoords( ScalarViewType dofCoords ) const override { diff --git a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HCURL_HEX_I1_FEMDef.hpp b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HCURL_HEX_I1_FEMDef.hpp index 7eff91667e1b..71ea78656fc1 100644 --- a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HCURL_HEX_I1_FEMDef.hpp +++ b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HCURL_HEX_I1_FEMDef.hpp @@ -330,6 +330,57 @@ namespace Intrepid2 { } + template + void + Basis_HCURL_HEX_I1_FEM::getScratchSpaceSize( + ordinal_type& perTeamSpaceSize, + ordinal_type& perThreadSpaceSize, + const PointViewType inputPoints, + const EOperator operatorType) const { + perTeamSpaceSize = 0; + perThreadSpaceSize = 0; + } + + template + KOKKOS_INLINE_FUNCTION + void + Basis_HCURL_HEX_I1_FEM::getValues( + OutputViewType outputValues, + const PointViewType inputPoints, + const EOperator operatorType, + const typename Kokkos::TeamPolicy::member_type& team_member, + const typename DT::execution_space::scratch_memory_space & scratchStorage, + const ordinal_type subcellDim, + const ordinal_type subcellOrdinal) const { + + INTREPID2_TEST_FOR_ABORT( !((subcellDim == -1) && (subcellOrdinal == -1)), + ">>> ERROR: (Intrepid2::Basis_HCURL_HEX_I1_FEM::getValues), The capability of selecting subsets of basis functions has not been implemented yet."); + + (void) scratchStorage; //avoid unused variable warning + + const int numPoints = inputPoints.extent(0); + + switch(operatorType) { + case OPERATOR_VALUE: + Kokkos::parallel_for (Kokkos::TeamThreadRange (team_member, numPoints), [=] (ordinal_type& pt) { + auto output = Kokkos::subview( outputValues, Kokkos::ALL(), pt, Kokkos::ALL() ); + const auto input = Kokkos::subview( inputPoints, pt, Kokkos::ALL() ); + Impl::Basis_HCURL_HEX_I1_FEM::Serial::getValues( output, input); + }); + break; + case OPERATOR_CURL: + Kokkos::parallel_for (Kokkos::TeamThreadRange (team_member, numPoints), [=] (ordinal_type& pt) { + auto output = Kokkos::subview( outputValues, Kokkos::ALL(), pt, Kokkos::ALL() ); + const auto input = Kokkos::subview( inputPoints, pt, Kokkos::ALL() ); + Impl::Basis_HCURL_HEX_I1_FEM::Serial::getValues( output, input); + }); + break; + default: { + INTREPID2_TEST_FOR_ABORT( true, ">>> ERROR: (Intrepid2::Basis_HCURL_HEX_I1_FEM::getValues), Operator Type not supported."); + } + } + } + }// namespace Intrepid2 #endif diff --git a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HCURL_HEX_In_FEM.hpp b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HCURL_HEX_In_FEM.hpp index 1af120be9949..64327bb29c08 100644 --- a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HCURL_HEX_In_FEM.hpp +++ b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HCURL_HEX_In_FEM.hpp @@ -148,20 +148,21 @@ namespace Intrepid2 { class Basis_HCURL_HEX_In_FEM : public Basis { public: - using OrdinalTypeArray1DHost = typename Basis::OrdinalTypeArray1DHost; - using OrdinalTypeArray2DHost = typename Basis::OrdinalTypeArray2DHost; - using OrdinalTypeArray3DHost = typename Basis::OrdinalTypeArray3DHost; + using BasisBase = Basis; + using OrdinalTypeArray1DHost = typename BasisBase::OrdinalTypeArray1DHost; + using OrdinalTypeArray2DHost = typename BasisBase::OrdinalTypeArray2DHost; + using OrdinalTypeArray3DHost = typename BasisBase::OrdinalTypeArray3DHost; /** \brief Constructor. */ Basis_HCURL_HEX_In_FEM(const ordinal_type order, const EPointType pointType = POINTTYPE_EQUISPACED); - using OutputViewType = typename Basis::OutputViewType; - using PointViewType = typename Basis::PointViewType; - using ScalarViewType = typename Basis::ScalarViewType; + using OutputViewType = typename BasisBase::OutputViewType; + using PointViewType = typename BasisBase::PointViewType; + using ScalarViewType = typename BasisBase::ScalarViewType; - using Basis::getValues; + using BasisBase::getValues; virtual void @@ -184,6 +185,23 @@ namespace Intrepid2 { operatorType ); } + virtual void + getScratchSpaceSize( ordinal_type& perTeamSpaceSize, + ordinal_type& perThreadSpaceSize, + const PointViewType inputPointsconst, + const EOperator operatorType = OPERATOR_VALUE) const override; + + KOKKOS_INLINE_FUNCTION + virtual void + getValues( + OutputViewType outputValues, + const PointViewType inputPoints, + const EOperator operatorType, + const typename Kokkos::TeamPolicy::member_type& team_member, + const typename DeviceType::execution_space::scratch_memory_space & scratchStorage, + const ordinal_type subcellDim = -1, + const ordinal_type subcellOrdinal = -1) const override; + virtual void getDofCoords( ScalarViewType dofCoords ) const override { diff --git a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HCURL_HEX_In_FEMDef.hpp b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HCURL_HEX_In_FEMDef.hpp index 1d18b7887096..182c05d721b0 100644 --- a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HCURL_HEX_In_FEMDef.hpp +++ b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HCURL_HEX_In_FEMDef.hpp @@ -21,19 +21,19 @@ namespace Intrepid2 { // ------------------------------------------------------------------------------------- namespace Impl { - template + template template + typename InputViewType, + typename WorkViewType, + typename VinvViewType> KOKKOS_INLINE_FUNCTION void - Basis_HCURL_HEX_In_FEM::Serial:: + Basis_HCURL_HEX_In_FEM::Serial:: getValues( OutputViewType output, - const inputViewType input, - workViewType work, - const vinvViewType vinvLine, - const vinvViewType vinvBubble) { + const InputViewType input, + WorkViewType work, + const VinvViewType vinvLine, + const VinvViewType vinvBubble) { const ordinal_type cardLine = vinvLine.extent(0); const ordinal_type cardBubble = vinvBubble.extent(0); @@ -44,22 +44,22 @@ namespace Intrepid2 { const auto input_y = Kokkos::subview(input, Kokkos::ALL(), range_type(1,2)); const auto input_z = Kokkos::subview(input, Kokkos::ALL(), range_type(2,3)); - const ordinal_type dim_s = get_dimension_scalar(work); + const ordinal_type dim_s = get_dimension_scalar(input); auto ptr0 = work.data(); auto ptr1 = work.data() + cardLine*npts*dim_s; auto ptr2 = work.data() + 2*cardLine*npts*dim_s; auto ptr3 = work.data() + 3*cardLine*npts*dim_s; - typedef typename Kokkos::DynRankView viewType; - auto vcprop = Kokkos::common_view_alloc_prop(work); + typedef typename Kokkos::DynRankView ViewType; + auto vcprop = Kokkos::common_view_alloc_prop(input); - switch (opType) { + switch (OpType) { case OPERATOR_VALUE: { - viewType workLine(Kokkos::view_wrap(ptr0, vcprop), cardLine, npts); - viewType outputLine_A(Kokkos::view_wrap(ptr1, vcprop), cardLine, npts); - viewType outputLine_B(Kokkos::view_wrap(ptr2, vcprop), cardLine, npts); - viewType outputBubble(Kokkos::view_wrap(ptr3, vcprop), cardBubble, npts); + ViewType workLine(Kokkos::view_wrap(ptr0, vcprop), cardLine, npts); + ViewType outputLine_A(Kokkos::view_wrap(ptr1, vcprop), cardLine, npts); + ViewType outputLine_B(Kokkos::view_wrap(ptr2, vcprop), cardLine, npts); + ViewType outputBubble(Kokkos::view_wrap(ptr3, vcprop), cardBubble, npts); // tensor product ordinal_type idx = 0; @@ -142,12 +142,12 @@ namespace Intrepid2 { auto ptr4 = work.data() + 4*cardLine*npts*dim_s; auto ptr5 = work.data() + 5*cardLine*npts*dim_s; - viewType workLine(Kokkos::view_wrap(ptr0, vcprop), cardLine, npts); - viewType outputLine_A(Kokkos::view_wrap(ptr1, vcprop), cardLine, npts); - viewType outputLine_B(Kokkos::view_wrap(ptr2, vcprop), cardLine, npts); - viewType outputLine_DA(Kokkos::view_wrap(ptr3, vcprop), cardLine, npts, 1); - viewType outputLine_DB(Kokkos::view_wrap(ptr4, vcprop), cardLine, npts, 1); - viewType outputBubble(Kokkos::view_wrap(ptr5, vcprop), cardBubble, npts); + ViewType workLine(Kokkos::view_wrap(ptr0, vcprop), cardLine, npts); + ViewType outputLine_A(Kokkos::view_wrap(ptr1, vcprop), cardLine, npts); + ViewType outputLine_B(Kokkos::view_wrap(ptr2, vcprop), cardLine, npts); + ViewType outputLine_DA(Kokkos::view_wrap(ptr3, vcprop), cardLine, npts, 1); + ViewType outputLine_DB(Kokkos::view_wrap(ptr4, vcprop), cardLine, npts, 1); + ViewType outputBubble(Kokkos::view_wrap(ptr5, vcprop), cardBubble, npts); // tensor product ordinal_type idx = 0; @@ -588,6 +588,70 @@ namespace Intrepid2 { this->dofCoeffs_ = Kokkos::create_mirror_view(typename DT::memory_space(), dofCoeffsHost); Kokkos::deep_copy(this->dofCoeffs_, dofCoeffsHost); } -} + + template + void + Basis_HCURL_HEX_In_FEM::getScratchSpaceSize( + ordinal_type& perTeamSpaceSize, + ordinal_type& perThreadSpaceSize, + const PointViewType inputPoints, + const EOperator operatorType) const { + perTeamSpaceSize = 0; + ordinal_type scalarWorkViewExtent = (operatorType == OPERATOR_VALUE) ? + 3*this->vinvLine_.extent(0)+this->vinvBubble_.extent(0): + 5*this->vinvLine_.extent(0)+this->vinvBubble_.extent(0); + perThreadSpaceSize = scalarWorkViewExtent*get_dimension_scalar(inputPoints)*sizeof(typename BasisBase::scalarType); + } + + template + KOKKOS_INLINE_FUNCTION + void + Basis_HCURL_HEX_In_FEM::getValues( + OutputViewType outputValues, + const PointViewType inputPoints, + const EOperator operatorType, + const typename Kokkos::TeamPolicy::member_type& team_member, + const typename DT::execution_space::scratch_memory_space & scratchStorage, + const ordinal_type subcellDim, + const ordinal_type subcellOrdinal) const { + + INTREPID2_TEST_FOR_ABORT( !((subcellDim == -1) && (subcellOrdinal == -1)), + ">>> ERROR: (Intrepid2::Basis_HCURL_HEX_In_FEM::getValues), The capability of selecting subsets of basis functions has not been implemented yet."); + + const int numPoints = inputPoints.extent(0); + using ScalarType = typename ScalarTraits::scalar_type; + using WorkViewType = Kokkos::DynRankView< ScalarType,typename DT::execution_space::scratch_memory_space,Kokkos::MemoryTraits >; + ordinal_type scalarSizePerPoint = (operatorType == OPERATOR_VALUE) ? + 3*this->vinvLine_.extent(0)+this->vinvBubble_.extent(0): + 5*this->vinvLine_.extent(0)+this->vinvBubble_.extent(0); + ordinal_type sizePerPoint = scalarSizePerPoint*get_dimension_scalar(inputPoints); + WorkViewType workView(scratchStorage, sizePerPoint*team_member.team_size()); + using range_type = Kokkos::pair; + + switch(operatorType) { + case OPERATOR_VALUE: + Kokkos::parallel_for (Kokkos::TeamThreadRange (team_member, numPoints), [=] (ordinal_type& pt) { + auto output = Kokkos::subview( outputValues, Kokkos::ALL(), range_type (pt,pt+1), Kokkos::ALL() ); + const auto input = Kokkos::subview( inputPoints, range_type(pt, pt+1), Kokkos::ALL() ); + WorkViewType work(workView.data() + sizePerPoint*team_member.team_rank(), sizePerPoint); + Impl::Basis_HCURL_HEX_In_FEM::Serial::getValues( output, input, work, this->vinvLine_, this->vinvBubble_ ); + }); + break; + case OPERATOR_CURL: + Kokkos::parallel_for (Kokkos::TeamThreadRange (team_member, numPoints), [=] (ordinal_type& pt) { + auto output = Kokkos::subview( outputValues, Kokkos::ALL(), range_type(pt,pt+1), Kokkos::ALL() ); + const auto input = Kokkos::subview( inputPoints, range_type(pt,pt+1), Kokkos::ALL() ); + WorkViewType work(workView.data() + sizePerPoint*team_member.team_rank(), sizePerPoint); + Impl::Basis_HCURL_HEX_In_FEM::Serial::getValues( output, input, work, this->vinvLine_, this->vinvBubble_ ); + }); + break; + default: { + INTREPID2_TEST_FOR_ABORT( true, + ">>> ERROR (Basis_HCURL_HEX_In_FEM): getValues not implemented for this operator"); + } + } + } + +} // namespace Intrepid2 #endif diff --git a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HCURL_QUAD_I1_FEM.hpp b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HCURL_QUAD_I1_FEM.hpp index 15f266e2db91..24c4b26bf746 100644 --- a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HCURL_QUAD_I1_FEM.hpp +++ b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HCURL_QUAD_I1_FEM.hpp @@ -144,20 +144,21 @@ namespace Intrepid2 { typename pointValueType = double> class Basis_HCURL_QUAD_I1_FEM : public Basis { public: - using OrdinalTypeArray1DHost = typename Basis::OrdinalTypeArray1DHost; - using OrdinalTypeArray2DHost = typename Basis::OrdinalTypeArray2DHost; - using OrdinalTypeArray3DHost = typename Basis::OrdinalTypeArray3DHost; + using BasisBase = Basis; + using OrdinalTypeArray1DHost = typename BasisBase::OrdinalTypeArray1DHost; + using OrdinalTypeArray2DHost = typename BasisBase::OrdinalTypeArray2DHost; + using OrdinalTypeArray3DHost = typename BasisBase::OrdinalTypeArray3DHost; /** \brief Constructor. */ Basis_HCURL_QUAD_I1_FEM(); - using OutputViewType = typename Basis::OutputViewType; - using PointViewType = typename Basis::PointViewType; - using ScalarViewType = typename Basis::ScalarViewType; + using OutputViewType = typename BasisBase::OutputViewType; + using PointViewType = typename BasisBase::PointViewType; + using ScalarViewType = typename BasisBase::ScalarViewType; - using Basis::getValues; + using BasisBase::getValues; virtual void @@ -178,6 +179,23 @@ namespace Intrepid2 { operatorType ); } + virtual void + getScratchSpaceSize( ordinal_type& perTeamSpaceSize, + ordinal_type& perThreadSpaceSize, + const PointViewType inputPointsconst, + const EOperator operatorType = OPERATOR_VALUE) const override; + + KOKKOS_INLINE_FUNCTION + virtual void + getValues( + OutputViewType outputValues, + const PointViewType inputPoints, + const EOperator operatorType, + const typename Kokkos::TeamPolicy::member_type& team_member, + const typename DeviceType::execution_space::scratch_memory_space & scratchStorage, + const ordinal_type subcellDim = -1, + const ordinal_type subcellOrdinal = -1) const override; + virtual void getDofCoords( ScalarViewType dofCoords ) const override { diff --git a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HCURL_QUAD_I1_FEMDef.hpp b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HCURL_QUAD_I1_FEMDef.hpp index 548929fb74cc..8380a4665a05 100644 --- a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HCURL_QUAD_I1_FEMDef.hpp +++ b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HCURL_QUAD_I1_FEMDef.hpp @@ -60,7 +60,7 @@ namespace Intrepid2 { default: { INTREPID2_TEST_FOR_ABORT( opType != OPERATOR_VALUE && opType != OPERATOR_CURL, - ">>> ERROR: (Intrepid2::Basis_HGRAD_QUAD_C1_FEM::Serial::getValues) operator is not supported"); + ">>> ERROR: (Intrepid2::Basis_HCURL_QUAD_I1_FEM::Serial::getValues) operator is not supported"); } } //end switch } @@ -219,7 +219,56 @@ namespace Intrepid2 { } + template + void + Basis_HCURL_QUAD_I1_FEM::getScratchSpaceSize( + ordinal_type& perTeamSpaceSize, + ordinal_type& perThreadSpaceSize, + const PointViewType inputPoints, + const EOperator operatorType) const { + perTeamSpaceSize = 0; + perThreadSpaceSize = 0; + } -}// namespace Intrepid2 + template + KOKKOS_INLINE_FUNCTION + void + Basis_HCURL_QUAD_I1_FEM::getValues( + OutputViewType outputValues, + const PointViewType inputPoints, + const EOperator operatorType, + const typename Kokkos::TeamPolicy::member_type& team_member, + const typename DT::execution_space::scratch_memory_space & scratchStorage, + const ordinal_type subcellDim, + const ordinal_type subcellOrdinal) const { + + INTREPID2_TEST_FOR_ABORT( !((subcellDim == -1) && (subcellOrdinal == -1)), + ">>> ERROR: (Intrepid2::Basis_HCURL_QUAD_I1_FEM::getValues), The capability of selecting subsets of basis functions has not been implemented yet."); + (void) scratchStorage; //avoid unused variable warning + + const int numPoints = inputPoints.extent(0); + + switch(operatorType) { + case OPERATOR_VALUE: + Kokkos::parallel_for (Kokkos::TeamThreadRange (team_member, numPoints), [=] (ordinal_type& pt) { + auto output = Kokkos::subview( outputValues, Kokkos::ALL(), pt, Kokkos::ALL() ); + const auto input = Kokkos::subview( inputPoints, pt, Kokkos::ALL() ); + Impl::Basis_HCURL_QUAD_I1_FEM::Serial::getValues( output, input); + }); + break; + case OPERATOR_CURL: + Kokkos::parallel_for (Kokkos::TeamThreadRange (team_member, numPoints), [=] (ordinal_type& pt) { + auto output = Kokkos::subview( outputValues, Kokkos::ALL(), pt, Kokkos::ALL() ); + const auto input = Kokkos::subview( inputPoints, pt, Kokkos::ALL() ); + Impl::Basis_HCURL_QUAD_I1_FEM::Serial::getValues( output, input); + }); + break; + default: { + INTREPID2_TEST_FOR_ABORT( true, ">>> ERROR: (Intrepid2::Basis_HCURL_QUAD_I1_FEM::getValues), Operator Type not supported."); + } + } + } + +}// namespace Intrepid2 #endif diff --git a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HCURL_QUAD_In_FEM.hpp b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HCURL_QUAD_In_FEM.hpp index 077f6de07afb..13d0c227d421 100644 --- a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HCURL_QUAD_In_FEM.hpp +++ b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HCURL_QUAD_In_FEM.hpp @@ -136,20 +136,21 @@ namespace Intrepid2 { class Basis_HCURL_QUAD_In_FEM : public Basis { public: - using OrdinalTypeArray1DHost = typename Basis::OrdinalTypeArray1DHost; - using OrdinalTypeArray2DHost = typename Basis::OrdinalTypeArray2DHost; - using OrdinalTypeArray3DHost = typename Basis::OrdinalTypeArray3DHost; + using BasisBase = Basis; + using OrdinalTypeArray1DHost = typename BasisBase::OrdinalTypeArray1DHost; + using OrdinalTypeArray2DHost = typename BasisBase::OrdinalTypeArray2DHost; + using OrdinalTypeArray3DHost = typename BasisBase::OrdinalTypeArray3DHost; /** \brief Constructor. */ Basis_HCURL_QUAD_In_FEM(const ordinal_type order, const EPointType pointType = POINTTYPE_EQUISPACED); - using OutputViewType = typename Basis::OutputViewType; - using PointViewType = typename Basis::PointViewType; - using ScalarViewType = typename Basis::ScalarViewType; + using OutputViewType = typename BasisBase::OutputViewType; + using PointViewType = typename BasisBase::PointViewType; + using ScalarViewType = typename BasisBase::ScalarViewType; - using Basis::getValues; + using BasisBase::getValues; virtual void @@ -172,6 +173,23 @@ namespace Intrepid2 { operatorType ); } + virtual void + getScratchSpaceSize( ordinal_type& perTeamSpaceSize, + ordinal_type& perThreadSpaceSize, + const PointViewType inputPointsconst, + const EOperator operatorType = OPERATOR_VALUE) const override; + + KOKKOS_INLINE_FUNCTION + virtual void + getValues( + OutputViewType outputValues, + const PointViewType inputPoints, + const EOperator operatorType, + const typename Kokkos::TeamPolicy::member_type& team_member, + const typename DeviceType::execution_space::scratch_memory_space & scratchStorage, + const ordinal_type subcellDim = -1, + const ordinal_type subcellOrdinal = -1) const override; + virtual void getDofCoords( ScalarViewType dofCoords ) const override { diff --git a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HCURL_QUAD_In_FEMDef.hpp b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HCURL_QUAD_In_FEMDef.hpp index 13a732abb88d..b00248a51fc8 100644 --- a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HCURL_QUAD_In_FEMDef.hpp +++ b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HCURL_QUAD_In_FEMDef.hpp @@ -21,19 +21,19 @@ namespace Intrepid2 { // ------------------------------------------------------------------------------------- namespace Impl { - template + template template + typename InputViewType, + typename WorkViewType, + typename VinvViewType> KOKKOS_INLINE_FUNCTION void - Basis_HCURL_QUAD_In_FEM::Serial:: + Basis_HCURL_QUAD_In_FEM::Serial:: getValues( OutputViewType output, - const inputViewType input, - workViewType work, - const vinvViewType vinvLine, - const vinvViewType vinvBubble) { + const InputViewType input, + WorkViewType work, + const VinvViewType vinvLine, + const VinvViewType vinvBubble) { const ordinal_type cardLine = vinvLine.extent(0); const ordinal_type cardBubble = vinvBubble.extent(0); @@ -43,19 +43,19 @@ namespace Intrepid2 { const auto input_x = Kokkos::subview(input, Kokkos::ALL(), range_type(0,1)); const auto input_y = Kokkos::subview(input, Kokkos::ALL(), range_type(1,2)); - const int dim_s = get_dimension_scalar(work); + const int dim_s = get_dimension_scalar(input); auto ptr0 = work.data(); auto ptr1 = work.data()+cardLine*npts*dim_s; auto ptr2 = work.data()+2*cardLine*npts*dim_s; - typedef typename Kokkos::DynRankView viewType; - auto vcprop = Kokkos::common_view_alloc_prop(work); + typedef typename Kokkos::DynRankView ViewType; + auto vcprop = Kokkos::common_view_alloc_prop(input); - switch (opType) { + switch (OpType) { case OPERATOR_VALUE: { - viewType workLine(Kokkos::view_wrap(ptr0, vcprop), cardLine, npts); - viewType outputLine(Kokkos::view_wrap(ptr1, vcprop), cardLine, npts); - viewType outputBubble(Kokkos::view_wrap(ptr2, vcprop), cardBubble, npts); + ViewType workLine(Kokkos::view_wrap(ptr0, vcprop), cardLine, npts); + ViewType outputLine(Kokkos::view_wrap(ptr1, vcprop), cardLine, npts); + ViewType outputBubble(Kokkos::view_wrap(ptr2, vcprop), cardBubble, npts); // tensor product ordinal_type idx = 0; @@ -101,11 +101,11 @@ namespace Intrepid2 { case OPERATOR_CURL: { ordinal_type idx = 0; { // x - component - viewType workLine(Kokkos::view_wrap(ptr0, vcprop), cardLine, npts); + ViewType workLine(Kokkos::view_wrap(ptr0, vcprop), cardLine, npts); // x bubble value - viewType output_x(Kokkos::view_wrap(ptr2, vcprop), cardBubble, npts); + ViewType output_x(Kokkos::view_wrap(ptr2, vcprop), cardBubble, npts); // y line grad - viewType output_y(Kokkos::view_wrap(ptr1, vcprop), cardLine, npts,1); + ViewType output_y(Kokkos::view_wrap(ptr1, vcprop), cardLine, npts,1); Impl::Basis_HGRAD_LINE_Cn_FEM::Serial:: getValues(output_x, input_x, workLine, vinvBubble); @@ -120,11 +120,11 @@ namespace Intrepid2 { output.access(idx,k) = -output_x.access(i,k)*output_y.access(j,k,0); } { // y - component - viewType workLine(Kokkos::view_wrap(ptr0, vcprop), cardLine, npts); + ViewType workLine(Kokkos::view_wrap(ptr0, vcprop), cardLine, npts); // x line grad - viewType output_x(Kokkos::view_wrap(ptr1, vcprop), cardLine, npts,1); + ViewType output_x(Kokkos::view_wrap(ptr1, vcprop), cardLine, npts,1); // y bubble value - viewType output_y(Kokkos::view_wrap(ptr2, vcprop), cardBubble, npts); + ViewType output_y(Kokkos::view_wrap(ptr2, vcprop), cardBubble, npts); Impl::Basis_HGRAD_LINE_Cn_FEM::Serial:: getValues(output_y, input_y, workLine, vinvBubble); @@ -386,6 +386,63 @@ namespace Intrepid2 { Kokkos::deep_copy(this->dofCoeffs_, dofCoeffsHost); } -} + template + void + Basis_HCURL_QUAD_In_FEM::getScratchSpaceSize( + ordinal_type& perTeamSpaceSize, + ordinal_type& perThreadSpaceSize, + const PointViewType inputPoints, + const EOperator operatorType) const { + perTeamSpaceSize = 0; + perThreadSpaceSize = (2*this->vinvLine_.extent(0)+this->vinvBubble_.extent(0))*get_dimension_scalar(inputPoints)*sizeof(typename BasisBase::scalarType); + } + + template + KOKKOS_INLINE_FUNCTION + void + Basis_HCURL_QUAD_In_FEM::getValues( + OutputViewType outputValues, + const PointViewType inputPoints, + const EOperator operatorType, + const typename Kokkos::TeamPolicy::member_type& team_member, + const typename DT::execution_space::scratch_memory_space & scratchStorage, + const ordinal_type subcellDim, + const ordinal_type subcellOrdinal) const { + + INTREPID2_TEST_FOR_ABORT( !((subcellDim == -1) && (subcellOrdinal == -1)), + ">>> ERROR: (Intrepid2::Basis_HCURL_QUAD_In_FEM::getValues), The capability of selecting subsets of basis functions has not been implemented yet."); + + const int numPoints = inputPoints.extent(0); + using ScalarType = typename ScalarTraits::scalar_type; + using WorkViewType = Kokkos::DynRankView< ScalarType,typename DT::execution_space::scratch_memory_space,Kokkos::MemoryTraits >; + ordinal_type sizePerPoint = (2*this->vinvLine_.extent(0)+this->vinvBubble_.extent(0))*get_dimension_scalar(inputPoints); + WorkViewType workView(scratchStorage, sizePerPoint*team_member.team_size()); + using range_type = Kokkos::pair; + + switch(operatorType) { + case OPERATOR_VALUE: + Kokkos::parallel_for (Kokkos::TeamThreadRange (team_member, numPoints), [=] (ordinal_type& pt) { + auto output = Kokkos::subview( outputValues, Kokkos::ALL(), range_type (pt,pt+1), Kokkos::ALL() ); + const auto input = Kokkos::subview( inputPoints, range_type(pt, pt+1), Kokkos::ALL() ); + WorkViewType work(workView.data() + sizePerPoint*team_member.team_rank(), sizePerPoint); + Impl::Basis_HCURL_QUAD_In_FEM::Serial::getValues( output, input, work, this->vinvLine_, this->vinvBubble_ ); + }); + break; + case OPERATOR_CURL: + Kokkos::parallel_for (Kokkos::TeamThreadRange (team_member, numPoints), [=] (ordinal_type& pt) { + auto output = Kokkos::subview( outputValues, Kokkos::ALL(), range_type(pt,pt+1), Kokkos::ALL() ); + const auto input = Kokkos::subview( inputPoints, range_type(pt,pt+1), Kokkos::ALL() ); + WorkViewType work(workView.data() + sizePerPoint*team_member.team_rank(), sizePerPoint); + Impl::Basis_HCURL_QUAD_In_FEM::Serial::getValues( output, input, work, this->vinvLine_, this->vinvBubble_ ); + }); + break; + default: { + INTREPID2_TEST_FOR_ABORT( true, + ">>> ERROR (Basis_HCURL_QUAD_In_FEM): getValues not implemented for this operator"); + } + } + } + +} // namespace Intrepid2 #endif diff --git a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HCURL_TET_I1_FEM.hpp b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HCURL_TET_I1_FEM.hpp index 6d90318a4961..d293da0e38c0 100644 --- a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HCURL_TET_I1_FEM.hpp +++ b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HCURL_TET_I1_FEM.hpp @@ -184,6 +184,23 @@ namespace Intrepid2 { operatorType); } + virtual void + getScratchSpaceSize( ordinal_type& perTeamSpaceSize, + ordinal_type& perThreadSpaceSize, + const PointViewType inputPointsconst, + const EOperator operatorType = OPERATOR_VALUE) const override; + + KOKKOS_INLINE_FUNCTION + virtual void + getValues( + OutputViewType outputValues, + const PointViewType inputPoints, + const EOperator operatorType, + const typename Kokkos::TeamPolicy::member_type& team_member, + const typename DeviceType::execution_space::scratch_memory_space & scratchStorage, + const ordinal_type subcellDim = -1, + const ordinal_type subcellOrdinal = -1) const override; + virtual void getDofCoords( ScalarViewType dofCoords ) const override { diff --git a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HCURL_TET_I1_FEMDef.hpp b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HCURL_TET_I1_FEMDef.hpp index 9c3d2b2d1c23..4d38583f8e49 100644 --- a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HCURL_TET_I1_FEMDef.hpp +++ b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HCURL_TET_I1_FEMDef.hpp @@ -255,6 +255,57 @@ namespace Intrepid2 { } + template + void + Basis_HCURL_TET_I1_FEM::getScratchSpaceSize( + ordinal_type& perTeamSpaceSize, + ordinal_type& perThreadSpaceSize, + const PointViewType inputPoints, + const EOperator operatorType) const { + perTeamSpaceSize = 0; + perThreadSpaceSize = 0; + } + template + KOKKOS_INLINE_FUNCTION + void + Basis_HCURL_TET_I1_FEM::getValues( + OutputViewType outputValues, + const PointViewType inputPoints, + const EOperator operatorType, + const typename Kokkos::TeamPolicy::member_type& team_member, + const typename DT::execution_space::scratch_memory_space & scratchStorage, + const ordinal_type subcellDim, + const ordinal_type subcellOrdinal) const { + + INTREPID2_TEST_FOR_ABORT( !((subcellDim == -1) && (subcellOrdinal == -1)), + ">>> ERROR: (Intrepid2::Basis_HCURL_TET_I1_FEM::getValues), The capability of selecting subsets of basis functions has not been implemented yet."); + + (void) scratchStorage; //avoid unused variable warning + + const int numPoints = inputPoints.extent(0); + + switch(operatorType) { + case OPERATOR_VALUE: + Kokkos::parallel_for (Kokkos::TeamThreadRange (team_member, numPoints), [=] (ordinal_type& pt) { + auto output = Kokkos::subview( outputValues, Kokkos::ALL(), pt, Kokkos::ALL() ); + const auto input = Kokkos::subview( inputPoints, pt, Kokkos::ALL() ); + Impl::Basis_HCURL_TET_I1_FEM::Serial::getValues( output, input); + }); + break; + case OPERATOR_CURL: + Kokkos::parallel_for (Kokkos::TeamThreadRange (team_member, numPoints), [=] (ordinal_type& pt) { + auto output = Kokkos::subview( outputValues, Kokkos::ALL(), pt, Kokkos::ALL() ); + const auto input = Kokkos::subview( inputPoints, pt, Kokkos::ALL() ); + Impl::Basis_HCURL_TET_I1_FEM::Serial::getValues( output, input); + }); + break; + default: { + INTREPID2_TEST_FOR_ABORT( true, ">>> ERROR: (Intrepid2::Basis_HCURL_TET_I1_FEM::getValues), Operator Type not supported."); + } + } + } + }// namespace Intrepid2 + #endif diff --git a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HCURL_TET_In_FEM.hpp b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HCURL_TET_In_FEM.hpp index cae49e5b09a5..ed253d57ec13 100644 --- a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HCURL_TET_In_FEM.hpp +++ b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HCURL_TET_In_FEM.hpp @@ -217,9 +217,26 @@ class Basis_HCURL_TET_In_FEM operatorType); } - virtual - void - getDofCoords( ScalarViewType dofCoords ) const override { + virtual void + getScratchSpaceSize( ordinal_type& perTeamSpaceSize, + ordinal_type& perThreadSpaceSize, + const PointViewType inputPointsconst, + const EOperator operatorType = OPERATOR_VALUE) const override; + + KOKKOS_INLINE_FUNCTION + virtual void + getValues( + OutputViewType outputValues, + const PointViewType inputPoints, + const EOperator operatorType, + const typename Kokkos::TeamPolicy::member_type& team_member, + const typename DeviceType::execution_space::scratch_memory_space & scratchStorage, + const ordinal_type subcellDim = -1, + const ordinal_type subcellOrdinal = -1) const override; + + virtual + void + getDofCoords( ScalarViewType dofCoords ) const override { #ifdef HAVE_INTREPID2_DEBUG // Verify rank of output array. INTREPID2_TEST_FOR_EXCEPTION( rank(dofCoords) != 2, std::invalid_argument, diff --git a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HCURL_TET_In_FEMDef.hpp b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HCURL_TET_In_FEMDef.hpp index 8bb82254291f..56149a4a1820 100644 --- a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HCURL_TET_In_FEMDef.hpp +++ b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HCURL_TET_In_FEMDef.hpp @@ -26,18 +26,18 @@ namespace Intrepid2 { namespace Impl { -template +template template +typename InputViewType, +typename WorkViewType, +typename VinvViewType> KOKKOS_INLINE_FUNCTION void -Basis_HCURL_TET_In_FEM::Serial:: +Basis_HCURL_TET_In_FEM::Serial:: getValues( OutputViewType output, - const inputViewType input, - workViewType work, - const vinvViewType coeffs ) { + const InputViewType input, + WorkViewType work, + const VinvViewType coeffs ) { constexpr ordinal_type spaceDim = 3; const ordinal_type @@ -54,17 +54,17 @@ getValues( OutputViewType output, } } - typedef typename Kokkos::DynRankView viewType; - auto vcprop = Kokkos::common_view_alloc_prop(work); + typedef typename Kokkos::DynRankView ViewType; + auto vcprop = Kokkos::common_view_alloc_prop(input); auto ptr = work.data(); - switch (opType) { + switch (OpType) { case OPERATOR_VALUE: { - const viewType phis(Kokkos::view_wrap(ptr, vcprop), card, npts); - workViewType dummyView; + const ViewType phis(Kokkos::view_wrap(ptr, vcprop), card, npts); + ViewType dummyView; Impl::Basis_HGRAD_TET_Cn_FEM_ORTH:: - Serial::getValues(phis, input, dummyView, order); + Serial::getValues(phis, input, dummyView, order); for (ordinal_type i=0;i::getValues(phis, input, workView, order); @@ -282,7 +282,7 @@ Basis_HCURL_TET_In_FEM( const ordinal_type order, #ifdef HAVE_INTREPID2_DEBUG ordinal_type num_nonzero_sv = 0; for (int i=0;i tolerence()); + num_nonzero_sv += (S(i,0) > 10*tolerence()); INTREPID2_TEST_FOR_EXCEPTION( num_nonzero_sv != card, std::invalid_argument, ">>> ERROR: (Intrepid2::Basis_HCURL_TET_In_FEM( order, pointType), Matrix V1 should have rank equal to the cardinality of HCURL space"); @@ -562,5 +562,64 @@ Basis_HCURL_TET_In_FEM( const ordinal_type order, posDfOrd); } } + +template +void +Basis_HCURL_TET_In_FEM::getScratchSpaceSize( + ordinal_type& perTeamSpaceSize, + ordinal_type& perThreadSpaceSize, + const PointViewType inputPoints, + const EOperator operatorType) const { + perTeamSpaceSize = 0; + ordinal_type scalarWorkViewExtent = (operatorType == OPERATOR_VALUE) ? this->basisCardinality_ : 7*this->basisCardinality_; + perThreadSpaceSize = scalarWorkViewExtent*get_dimension_scalar(inputPoints)*sizeof(typename BasisBase::scalarType); +} + +template +KOKKOS_INLINE_FUNCTION +void +Basis_HCURL_TET_In_FEM::getValues( + OutputViewType outputValues, + const PointViewType inputPoints, + const EOperator operatorType, + const typename Kokkos::TeamPolicy::member_type& team_member, + const typename DT::execution_space::scratch_memory_space & scratchStorage, + const ordinal_type subcellDim, + const ordinal_type subcellOrdinal) const { + + INTREPID2_TEST_FOR_ABORT( !((subcellDim == -1) && (subcellOrdinal == -1)), + ">>> ERROR: (Intrepid2::Basis_HCURL_TET_In_FEM::getValues), The capability of selecting subsets of basis functions has not been implemented yet."); + + const int numPoints = inputPoints.extent(0); + using ScalarType = typename ScalarTraits::scalar_type; + using WorkViewType = Kokkos::DynRankView< ScalarType,typename DT::execution_space::scratch_memory_space,Kokkos::MemoryTraits >; + ordinal_type scalarSizePerPoint = (operatorType == OPERATOR_VALUE) ? this->basisCardinality_ : 7*this->basisCardinality_; + ordinal_type sizePerPoint = scalarSizePerPoint*get_dimension_scalar(inputPoints); + WorkViewType workView(scratchStorage, sizePerPoint*team_member.team_size()); + using range_type = Kokkos::pair; + + switch(operatorType) { + case OPERATOR_VALUE: + Kokkos::parallel_for (Kokkos::TeamThreadRange (team_member, numPoints), [=] (ordinal_type& pt) { + auto output = Kokkos::subview( outputValues, Kokkos::ALL(), range_type (pt,pt+1), Kokkos::ALL() ); + const auto input = Kokkos::subview( inputPoints, range_type(pt, pt+1), Kokkos::ALL() ); + WorkViewType work(workView.data() + sizePerPoint*team_member.team_rank(), sizePerPoint); + Impl::Basis_HCURL_TET_In_FEM::Serial::getValues( output, input, work, this->coeffs_ ); + }); + break; + case OPERATOR_CURL: + Kokkos::parallel_for (Kokkos::TeamThreadRange (team_member, numPoints), [=] (ordinal_type& pt) { + auto output = Kokkos::subview( outputValues, Kokkos::ALL(), range_type(pt,pt+1), Kokkos::ALL() ); + const auto input = Kokkos::subview( inputPoints, range_type(pt,pt+1), Kokkos::ALL() ); + WorkViewType work(workView.data() + sizePerPoint*team_member.team_rank(), sizePerPoint); + Impl::Basis_HCURL_TET_In_FEM::Serial::getValues( output, input, work, this->coeffs_ ); + }); + break; + default: { + INTREPID2_TEST_FOR_ABORT( true, + ">>> ERROR (Basis_HCURL_TET_In_FEM): getValues not implemented for this operator"); + } + } +} } // namespace Intrepid2 #endif diff --git a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HCURL_TRI_I1_FEM.hpp b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HCURL_TRI_I1_FEM.hpp index 816b999560a6..109c96988649 100644 --- a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HCURL_TRI_I1_FEM.hpp +++ b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HCURL_TRI_I1_FEM.hpp @@ -187,6 +187,23 @@ namespace Intrepid2 { operatorType); } + virtual void + getScratchSpaceSize( ordinal_type& perTeamSpaceSize, + ordinal_type& perThreadSpaceSize, + const PointViewType inputPointsconst, + const EOperator operatorType = OPERATOR_VALUE) const override; + + KOKKOS_INLINE_FUNCTION + virtual void + getValues( + OutputViewType outputValues, + const PointViewType inputPoints, + const EOperator operatorType, + const typename Kokkos::TeamPolicy::member_type& team_member, + const typename DeviceType::execution_space::scratch_memory_space & scratchStorage, + const ordinal_type subcellDim = -1, + const ordinal_type subcellOrdinal = -1) const override; + virtual void getDofCoords( ScalarViewType dofCoords ) const override { diff --git a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HCURL_TRI_I1_FEMDef.hpp b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HCURL_TRI_I1_FEMDef.hpp index 85e639ea8f10..813b764608db 100644 --- a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HCURL_TRI_I1_FEMDef.hpp +++ b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HCURL_TRI_I1_FEMDef.hpp @@ -208,7 +208,56 @@ namespace Intrepid2 { } + template + void + Basis_HCURL_TRI_I1_FEM::getScratchSpaceSize( + ordinal_type& perTeamSpaceSize, + ordinal_type& perThreadSpaceSize, + const PointViewType inputPoints, + const EOperator operatorType) const { + perTeamSpaceSize = 0; + perThreadSpaceSize = 0; + } + + template + KOKKOS_INLINE_FUNCTION + void + Basis_HCURL_TRI_I1_FEM::getValues( + OutputViewType outputValues, + const PointViewType inputPoints, + const EOperator operatorType, + const typename Kokkos::TeamPolicy::member_type& team_member, + const typename DT::execution_space::scratch_memory_space & scratchStorage, + const ordinal_type subcellDim, + const ordinal_type subcellOrdinal) const { + + INTREPID2_TEST_FOR_ABORT( !((subcellDim == -1) && (subcellOrdinal == -1)), + ">>> ERROR: (Intrepid2::Basis_HCURL_TRI_I1_FEM::getValues), The capability of selecting subsets of basis functions has not been implemented yet."); + + (void) scratchStorage; //avoid unused variable warning + + const int numPoints = inputPoints.extent(0); + switch(operatorType) { + case OPERATOR_VALUE: + Kokkos::parallel_for (Kokkos::TeamThreadRange (team_member, numPoints), [=] (ordinal_type& pt) { + auto output = Kokkos::subview( outputValues, Kokkos::ALL(), pt, Kokkos::ALL() ); + const auto input = Kokkos::subview( inputPoints, pt, Kokkos::ALL() ); + Impl::Basis_HCURL_TRI_I1_FEM::Serial::getValues( output, input); + }); + break; + case OPERATOR_CURL: + Kokkos::parallel_for (Kokkos::TeamThreadRange (team_member, numPoints), [=] (ordinal_type& pt) { + auto output = Kokkos::subview( outputValues, Kokkos::ALL(), pt, Kokkos::ALL() ); + const auto input = Kokkos::subview( inputPoints, pt, Kokkos::ALL() ); + Impl::Basis_HCURL_TRI_I1_FEM::Serial::getValues( output, input); + }); + break; + default: { + INTREPID2_TEST_FOR_ABORT( true, ">>> ERROR: (Intrepid2::Basis_HCURL_TRI_!1_FEM::getValues), Operator Type not supported."); + } + } + } + }// namespace Intrepid2 #endif - diff --git a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HCURL_TRI_In_FEM.hpp b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HCURL_TRI_In_FEM.hpp index 3c34d125847a..a030f292fb50 100644 --- a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HCURL_TRI_In_FEM.hpp +++ b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HCURL_TRI_In_FEM.hpp @@ -209,9 +209,26 @@ class Basis_HCURL_TRI_In_FEM operatorType); } - virtual - void - getDofCoords( ScalarViewType dofCoords ) const override { + virtual void + getScratchSpaceSize( ordinal_type& perTeamSpaceSize, + ordinal_type& perThreadSpaceSize, + const PointViewType inputPointsconst, + const EOperator operatorType = OPERATOR_VALUE) const override; + + KOKKOS_INLINE_FUNCTION + virtual void + getValues( + OutputViewType outputValues, + const PointViewType inputPoints, + const EOperator operatorType, + const typename Kokkos::TeamPolicy::member_type& team_member, + const typename DeviceType::execution_space::scratch_memory_space & scratchStorage, + const ordinal_type subcellDim = -1, + const ordinal_type subcellOrdinal = -1) const override; + + virtual + void + getDofCoords( ScalarViewType dofCoords ) const override { #ifdef HAVE_INTREPID2_DEBUG // Verify rank of output array. INTREPID2_TEST_FOR_EXCEPTION( rank(dofCoords) != 2, std::invalid_argument, diff --git a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HCURL_TRI_In_FEMDef.hpp b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HCURL_TRI_In_FEMDef.hpp index 7d10682a5e45..6cb65ab386de 100644 --- a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HCURL_TRI_In_FEMDef.hpp +++ b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HCURL_TRI_In_FEMDef.hpp @@ -25,18 +25,18 @@ namespace Intrepid2 { namespace Impl { - template + template template + typename InputViewType, + typename WorkViewType, + typename VinvViewType> KOKKOS_INLINE_FUNCTION void - Basis_HCURL_TRI_In_FEM::Serial:: + Basis_HCURL_TRI_In_FEM::Serial:: getValues( OutputViewType output, - const inputViewType input, - workViewType work, - const vinvViewType coeffs ) { + const InputViewType input, + WorkViewType work, + const VinvViewType coeffs ) { constexpr ordinal_type spaceDim = 2; const ordinal_type @@ -53,17 +53,16 @@ namespace Intrepid2 { } } - typedef typename Kokkos::DynRankView viewType; - auto vcprop = Kokkos::common_view_alloc_prop(work); + typedef typename Kokkos::DynRankView ViewType; + auto vcprop = Kokkos::common_view_alloc_prop(input); auto ptr = work.data(); - switch (opType) { + switch (OpType) { case OPERATOR_VALUE: { - const viewType phis(Kokkos::view_wrap(ptr, vcprop), card, npts); - workViewType dummyView; + const ViewType phis(Kokkos::view_wrap(ptr, vcprop), card, npts), dummyView; Impl::Basis_HGRAD_TRI_Cn_FEM_ORTH:: - Serial::getValues(phis, input, dummyView, order); + Serial::getValues(phis, input, dummyView, order); for (ordinal_type i=0;i::getValues(phis, input, workView, order); @@ -452,5 +451,66 @@ namespace Intrepid2 { posDfOrd); } } + + template + void + Basis_HCURL_TRI_In_FEM::getScratchSpaceSize( + ordinal_type& perTeamSpaceSize, + ordinal_type& perThreadSpaceSize, + const PointViewType inputPoints, + const EOperator operatorType) const { + perTeamSpaceSize = 0; + ordinal_type scalarWorkViewExtent = (operatorType == OPERATOR_VALUE) ? this->basisCardinality_ : 5*this->basisCardinality_; + perThreadSpaceSize = scalarWorkViewExtent*get_dimension_scalar(inputPoints)*sizeof(typename BasisBase::scalarType); + } + + template + KOKKOS_INLINE_FUNCTION + void + Basis_HCURL_TRI_In_FEM::getValues( + OutputViewType outputValues, + const PointViewType inputPoints, + const EOperator operatorType, + const typename Kokkos::TeamPolicy::member_type& team_member, + const typename DT::execution_space::scratch_memory_space & scratchStorage, + const ordinal_type subcellDim, + const ordinal_type subcellOrdinal) const { + + INTREPID2_TEST_FOR_ABORT( !((subcellDim == -1) && (subcellOrdinal == -1)), + ">>> ERROR: (Intrepid2::Basis_HCURL_TRI_In_FEM::getValues), The capability of selecting subsets of basis functions has not been implemented yet."); + + const int numPoints = inputPoints.extent(0); + using ScalarType = typename ScalarTraits::scalar_type; + using WorkViewType = Kokkos::DynRankView< ScalarType,typename DT::execution_space::scratch_memory_space,Kokkos::MemoryTraits >; + ordinal_type scalarSizePerPoint = (operatorType == OPERATOR_VALUE) ? this->basisCardinality_ : 5*this->basisCardinality_; + ordinal_type sizePerPoint = scalarSizePerPoint*get_dimension_scalar(inputPoints); + WorkViewType workView(scratchStorage, sizePerPoint*team_member.team_size()); + using range_type = Kokkos::pair; + + switch(operatorType) { + case OPERATOR_VALUE: + Kokkos::parallel_for (Kokkos::TeamThreadRange (team_member, numPoints), [=] (ordinal_type& pt) { + auto output = Kokkos::subview( outputValues, Kokkos::ALL(), range_type (pt,pt+1), Kokkos::ALL() ); + const auto input = Kokkos::subview( inputPoints, range_type(pt, pt+1), Kokkos::ALL() ); + WorkViewType work(workView.data() + sizePerPoint*team_member.team_rank(), sizePerPoint); + Impl::Basis_HCURL_TRI_In_FEM::Serial::getValues( output, input, work, this->coeffs_ ); + }); + break; + case OPERATOR_CURL: + Kokkos::parallel_for (Kokkos::TeamThreadRange (team_member, numPoints), [=] (ordinal_type& pt) { + auto output = Kokkos::subview( outputValues, Kokkos::ALL(), range_type(pt,pt+1), Kokkos::ALL() ); + const auto input = Kokkos::subview( inputPoints, range_type(pt,pt+1), Kokkos::ALL() ); + WorkViewType work(workView.data() + sizePerPoint*team_member.team_rank(), sizePerPoint); + Impl::Basis_HCURL_TRI_In_FEM::Serial::getValues( output, input, work, this->coeffs_ ); + }); + break; + default: { + INTREPID2_TEST_FOR_ABORT( true, + ">>> ERROR (Basis_HCURL_TRI_In_FEM): getValues not implemented for this operator"); + } + } + } + } // namespace Intrepid2 + #endif diff --git a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HCURL_WEDGE_I1_FEM.hpp b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HCURL_WEDGE_I1_FEM.hpp index c7587cf3eec1..d2831d0ac47a 100644 --- a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HCURL_WEDGE_I1_FEM.hpp +++ b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HCURL_WEDGE_I1_FEM.hpp @@ -185,6 +185,23 @@ namespace Intrepid2 { operatorType ); } + virtual void + getScratchSpaceSize( ordinal_type& perTeamSpaceSize, + ordinal_type& perThreadSpaceSize, + const PointViewType inputPointsconst, + const EOperator operatorType = OPERATOR_VALUE) const override; + + KOKKOS_INLINE_FUNCTION + virtual void + getValues( + OutputViewType outputValues, + const PointViewType inputPoints, + const EOperator operatorType, + const typename Kokkos::TeamPolicy::member_type& team_member, + const typename DeviceType::execution_space::scratch_memory_space & scratchStorage, + const ordinal_type subcellDim = -1, + const ordinal_type subcellOrdinal = -1) const override; + virtual void getDofCoords( ScalarViewType dofCoords ) const override { diff --git a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HCURL_WEDGE_I1_FEMDef.hpp b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HCURL_WEDGE_I1_FEMDef.hpp index 59ad4da436e8..754355ffbd7d 100644 --- a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HCURL_WEDGE_I1_FEMDef.hpp +++ b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HCURL_WEDGE_I1_FEMDef.hpp @@ -276,5 +276,57 @@ namespace Intrepid2 { } + template + void + Basis_HCURL_WEDGE_I1_FEM::getScratchSpaceSize( + ordinal_type& perTeamSpaceSize, + ordinal_type& perThreadSpaceSize, + const PointViewType inputPoints, + const EOperator operatorType) const { + perTeamSpaceSize = 0; + perThreadSpaceSize = 0; + } + + template + KOKKOS_INLINE_FUNCTION + void + Basis_HCURL_WEDGE_I1_FEM::getValues( + OutputViewType outputValues, + const PointViewType inputPoints, + const EOperator operatorType, + const typename Kokkos::TeamPolicy::member_type& team_member, + const typename DT::execution_space::scratch_memory_space & scratchStorage, + const ordinal_type subcellDim, + const ordinal_type subcellOrdinal) const { + + INTREPID2_TEST_FOR_ABORT( !((subcellDim == -1) && (subcellOrdinal == -1)), + ">>> ERROR: (Intrepid2::Basis_HCURL_WEDGE_I1_FEM::getValues), The capability of selecting subsets of basis functions has not been implemented yet."); + + (void) scratchStorage; //avoid unused variable warning + + const int numPoints = inputPoints.extent(0); + + switch(operatorType) { + case OPERATOR_VALUE: + Kokkos::parallel_for (Kokkos::TeamThreadRange (team_member, numPoints), [=] (ordinal_type& pt) { + auto output = Kokkos::subview( outputValues, Kokkos::ALL(), pt, Kokkos::ALL() ); + const auto input = Kokkos::subview( inputPoints, pt, Kokkos::ALL() ); + Impl::Basis_HCURL_WEDGE_I1_FEM::Serial::getValues( output, input); + }); + break; + case OPERATOR_CURL: + Kokkos::parallel_for (Kokkos::TeamThreadRange (team_member, numPoints), [=] (ordinal_type& pt) { + auto output = Kokkos::subview( outputValues, Kokkos::ALL(), pt, Kokkos::ALL() ); + const auto input = Kokkos::subview( inputPoints, pt, Kokkos::ALL() ); + Impl::Basis_HCURL_WEDGE_I1_FEM::Serial::getValues( output, input); + }); + break; + default: { + INTREPID2_TEST_FOR_ABORT( true, ">>> ERROR: (Intrepid2::Basis_HCURL_WEDGE_I1_FEM::getValues), Operator Type not supported."); + } + } + } + }// namespace Intrepid2 + #endif diff --git a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HDIV_HEX_I1_FEM.hpp b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HDIV_HEX_I1_FEM.hpp index 1de1d7c654c7..66ab525b3aec 100644 --- a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HDIV_HEX_I1_FEM.hpp +++ b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HDIV_HEX_I1_FEM.hpp @@ -190,6 +190,23 @@ namespace Intrepid2 { operatorType ); } + virtual void + getScratchSpaceSize( ordinal_type& perTeamSpaceSize, + ordinal_type& perThreadSpaceSize, + const PointViewType inputPointsconst, + const EOperator operatorType = OPERATOR_VALUE) const override; + + KOKKOS_INLINE_FUNCTION + virtual void + getValues( + OutputViewType outputValues, + const PointViewType inputPoints, + const EOperator operatorType, + const typename Kokkos::TeamPolicy::member_type& team_member, + const typename DeviceType::execution_space::scratch_memory_space & scratchStorage, + const ordinal_type subcellDim = -1, + const ordinal_type subcellOrdinal = -1) const override; + virtual void getDofCoords( ScalarViewType dofCoords ) const override { diff --git a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HDIV_HEX_I1_FEMDef.hpp b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HDIV_HEX_I1_FEMDef.hpp index 79e9aaef60f8..b7e865178e64 100644 --- a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HDIV_HEX_I1_FEMDef.hpp +++ b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HDIV_HEX_I1_FEMDef.hpp @@ -236,5 +236,57 @@ namespace Intrepid2 { } + template + void + Basis_HDIV_HEX_I1_FEM::getScratchSpaceSize( + ordinal_type& perTeamSpaceSize, + ordinal_type& perThreadSpaceSize, + const PointViewType inputPoints, + const EOperator operatorType) const { + perTeamSpaceSize = 0; + perThreadSpaceSize = 0; + } + + template + KOKKOS_INLINE_FUNCTION + void + Basis_HDIV_HEX_I1_FEM::getValues( + OutputViewType outputValues, + const PointViewType inputPoints, + const EOperator operatorType, + const typename Kokkos::TeamPolicy::member_type& team_member, + const typename DT::execution_space::scratch_memory_space & scratchStorage, + const ordinal_type subcellDim, + const ordinal_type subcellOrdinal) const { + + INTREPID2_TEST_FOR_ABORT( !((subcellDim == -1) && (subcellOrdinal == -1)), + ">>> ERROR: (Intrepid2::Basis_HDIV_HEX_I1_FEM::getValues), The capability of selecting subsets of basis functions has not been implemented yet."); + + (void) scratchStorage; //avoid unused variable warning + + const int numPoints = inputPoints.extent(0); + + switch(operatorType) { + case OPERATOR_VALUE: + Kokkos::parallel_for (Kokkos::TeamThreadRange (team_member, numPoints), [=] (ordinal_type& pt) { + auto output = Kokkos::subview( outputValues, Kokkos::ALL(), pt, Kokkos::ALL() ); + const auto input = Kokkos::subview( inputPoints, pt, Kokkos::ALL() ); + Impl::Basis_HDIV_HEX_I1_FEM::Serial::getValues( output, input); + }); + break; + case OPERATOR_DIV: + Kokkos::parallel_for (Kokkos::TeamThreadRange (team_member, numPoints), [=] (ordinal_type& pt) { + auto output = Kokkos::subview( outputValues, Kokkos::ALL(), pt, Kokkos::ALL() ); + const auto input = Kokkos::subview( inputPoints, pt, Kokkos::ALL() ); + Impl::Basis_HDIV_HEX_I1_FEM::Serial::getValues( output, input); + }); + break; + default: { + INTREPID2_TEST_FOR_ABORT( true, ">>> ERROR: (Intrepid2::Basis_HDIV_HEX_I1_FEM::getValues), Operator Type not supported."); + } + } + } + }// namespace Intrepid2 + #endif diff --git a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HDIV_HEX_In_FEM.hpp b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HDIV_HEX_In_FEM.hpp index 4ed98a89967f..f563bd998237 100644 --- a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HDIV_HEX_In_FEM.hpp +++ b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HDIV_HEX_In_FEM.hpp @@ -138,20 +138,21 @@ namespace Intrepid2 { class Basis_HDIV_HEX_In_FEM : public Basis { public: - using OrdinalTypeArray1DHost = typename Basis::OrdinalTypeArray1DHost; - using OrdinalTypeArray2DHost = typename Basis::OrdinalTypeArray2DHost; - using OrdinalTypeArray3DHost = typename Basis::OrdinalTypeArray3DHost; + using BasisBase = Basis; + using OrdinalTypeArray1DHost = typename BasisBase::OrdinalTypeArray1DHost; + using OrdinalTypeArray2DHost = typename BasisBase::OrdinalTypeArray2DHost; + using OrdinalTypeArray3DHost = typename BasisBase::OrdinalTypeArray3DHost; /** \brief Constructor. */ Basis_HDIV_HEX_In_FEM(const ordinal_type order, const EPointType pointType = POINTTYPE_EQUISPACED); - using OutputViewType = typename Basis::OutputViewType; - using PointViewType = typename Basis::PointViewType; - using ScalarViewType = typename Basis::ScalarViewType; + using OutputViewType = typename BasisBase::OutputViewType; + using PointViewType = typename BasisBase::PointViewType; + using ScalarViewType = typename BasisBase::ScalarViewType; - using Basis::getValues; + using BasisBase::getValues; virtual void @@ -174,6 +175,23 @@ namespace Intrepid2 { operatorType ); } + virtual void + getScratchSpaceSize( ordinal_type& perTeamSpaceSize, + ordinal_type& perThreadSpaceSize, + const PointViewType inputPointsconst, + const EOperator operatorType = OPERATOR_VALUE) const override; + + KOKKOS_INLINE_FUNCTION + virtual void + getValues( + OutputViewType outputValues, + const PointViewType inputPoints, + const EOperator operatorType, + const typename Kokkos::TeamPolicy::member_type& team_member, + const typename DeviceType::execution_space::scratch_memory_space & scratchStorage, + const ordinal_type subcellDim = -1, + const ordinal_type subcellOrdinal = -1) const override; + virtual void getDofCoords( ScalarViewType dofCoords ) const override { @@ -254,8 +272,6 @@ namespace Intrepid2 { }// namespace Intrepid2 - - #include "Intrepid2_HDIV_HEX_In_FEMDef.hpp" #endif diff --git a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HDIV_HEX_In_FEMDef.hpp b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HDIV_HEX_In_FEMDef.hpp index 0bae2c8b1b3d..0d5d25113bdb 100644 --- a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HDIV_HEX_In_FEMDef.hpp +++ b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HDIV_HEX_In_FEMDef.hpp @@ -21,19 +21,19 @@ namespace Intrepid2 { // ------------------------------------------------------------------------------------- namespace Impl { - template + template template + typename InputViewType, + typename WorkViewType, + typename VinvViewType> KOKKOS_INLINE_FUNCTION void - Basis_HDIV_HEX_In_FEM::Serial:: + Basis_HDIV_HEX_In_FEM::Serial:: getValues( OutputViewType output, - const inputViewType input, - workViewType work, - const vinvViewType vinvLine, - const vinvViewType vinvBubble) { + const InputViewType input, + WorkViewType work, + const VinvViewType vinvLine, + const VinvViewType vinvBubble) { const ordinal_type cardLine = vinvLine.extent(0); const ordinal_type cardBubble = vinvBubble.extent(0); @@ -44,21 +44,21 @@ namespace Intrepid2 { const auto input_y = Kokkos::subview(input, Kokkos::ALL(), range_type(1,2)); const auto input_z = Kokkos::subview(input, Kokkos::ALL(), range_type(2,3)); - const ordinal_type dim_s = get_dimension_scalar(work); + const ordinal_type dim_s = get_dimension_scalar(input); auto ptr0 = work.data(); auto ptr1 = work.data()+cardLine*npts*dim_s; auto ptr2 = work.data()+2*cardLine*npts*dim_s; auto ptr3 = work.data()+(2*cardLine+cardBubble)*npts*dim_s; - typedef typename Kokkos::DynRankView viewType; - auto vcprop = Kokkos::common_view_alloc_prop(work); + typedef typename Kokkos::DynRankView ViewType; + auto vcprop = Kokkos::common_view_alloc_prop(input); - switch (opType) { + switch (OpType) { case OPERATOR_VALUE: { - viewType workLine(Kokkos::view_wrap(ptr0, vcprop), cardLine, npts); - viewType outputLine(Kokkos::view_wrap(ptr1, vcprop), cardLine, npts); - viewType outputBubble_A(Kokkos::view_wrap(ptr2, vcprop), cardBubble, npts); - viewType outputBubble_B(Kokkos::view_wrap(ptr3, vcprop), cardBubble, npts); + ViewType workLine(Kokkos::view_wrap(ptr0, vcprop), cardLine, npts); + ViewType outputLine(Kokkos::view_wrap(ptr1, vcprop), cardLine, npts); + ViewType outputBubble_A(Kokkos::view_wrap(ptr2, vcprop), cardBubble, npts); + ViewType outputBubble_B(Kokkos::view_wrap(ptr3, vcprop), cardBubble, npts); // tensor product ordinal_type idx = 0; @@ -138,13 +138,13 @@ namespace Intrepid2 { break; } case OPERATOR_DIV: { - viewType workLine(Kokkos::view_wrap(ptr0, vcprop), cardLine, npts); + ViewType workLine(Kokkos::view_wrap(ptr0, vcprop), cardLine, npts); // A line value - viewType outputBubble_A(Kokkos::view_wrap(ptr2, vcprop), cardBubble, npts); + ViewType outputBubble_A(Kokkos::view_wrap(ptr2, vcprop), cardBubble, npts); // B line value - viewType outputBubble_B(Kokkos::view_wrap(ptr3, vcprop), cardBubble, npts); + ViewType outputBubble_B(Kokkos::view_wrap(ptr3, vcprop), cardBubble, npts); // Line grad - viewType outputLine(Kokkos::view_wrap(ptr1, vcprop), cardLine, npts, 1); + ViewType outputLine(Kokkos::view_wrap(ptr1, vcprop), cardLine, npts, 1); // tensor product ordinal_type idx = 0; @@ -508,6 +508,64 @@ namespace Intrepid2 { this->dofCoeffs_ = Kokkos::create_mirror_view(typename DT::memory_space(), dofCoeffsHost); Kokkos::deep_copy(this->dofCoeffs_, dofCoeffsHost); } -} + + template + void + Basis_HDIV_HEX_In_FEM::getScratchSpaceSize( + ordinal_type& perTeamSpaceSize, + ordinal_type& perThreadSpaceSize, + const PointViewType inputPoints, + const EOperator operatorType) const { + perTeamSpaceSize = 0; + perThreadSpaceSize = (2*this->vinvLine_.extent(0)+2*this->vinvBubble_.extent(0))*get_dimension_scalar(inputPoints)*sizeof(typename BasisBase::scalarType); + } + + template + KOKKOS_INLINE_FUNCTION + void + Basis_HDIV_HEX_In_FEM::getValues( + OutputViewType outputValues, + const PointViewType inputPoints, + const EOperator operatorType, + const typename Kokkos::TeamPolicy::member_type& team_member, + const typename DT::execution_space::scratch_memory_space & scratchStorage, + const ordinal_type subcellDim, + const ordinal_type subcellOrdinal) const { + + INTREPID2_TEST_FOR_ABORT( !((subcellDim == -1) && (subcellOrdinal == -1)), + ">>> ERROR: (Intrepid2::Basis_HDIV_HEX_In_FEM::getValues), The capability of selecting subsets of basis functions has not been implemented yet."); + + const int numPoints = inputPoints.extent(0); + using ScalarType = typename ScalarTraits::scalar_type; + using WorkViewType = Kokkos::DynRankView< ScalarType,typename DT::execution_space::scratch_memory_space,Kokkos::MemoryTraits >; + ordinal_type sizePerPoint = (2*this->vinvLine_.extent(0)+2*this->vinvBubble_.extent(0))*get_dimension_scalar(inputPoints); + WorkViewType workView(scratchStorage, sizePerPoint*team_member.team_size()); + using range_type = Kokkos::pair; + + switch(operatorType) { + case OPERATOR_VALUE: + Kokkos::parallel_for (Kokkos::TeamThreadRange (team_member, numPoints), [=] (ordinal_type& pt) { + auto output = Kokkos::subview( outputValues, Kokkos::ALL(), range_type (pt,pt+1), Kokkos::ALL() ); + const auto input = Kokkos::subview( inputPoints, range_type(pt, pt+1), Kokkos::ALL() ); + WorkViewType work(workView.data() + sizePerPoint*team_member.team_rank(), sizePerPoint); + Impl::Basis_HDIV_HEX_In_FEM::Serial::getValues( output, input, work, this->vinvLine_, this->vinvBubble_ ); + }); + break; + case OPERATOR_DIV: + Kokkos::parallel_for (Kokkos::TeamThreadRange (team_member, numPoints), [=] (ordinal_type& pt) { + auto output = Kokkos::subview( outputValues, Kokkos::ALL(), range_type(pt,pt+1), Kokkos::ALL() ); + const auto input = Kokkos::subview( inputPoints, range_type(pt,pt+1), Kokkos::ALL() ); + WorkViewType work(workView.data() + sizePerPoint*team_member.team_rank(), sizePerPoint); + Impl::Basis_HDIV_HEX_In_FEM::Serial::getValues( output, input, work, this->vinvLine_, this->vinvBubble_ ); + }); + break; + default: { + INTREPID2_TEST_FOR_ABORT( true, + ">>> ERROR (Basis_HDIV_HEX_In_FEM): getValues not implemented for this operator"); + } + } + } + +} // namespace Intrepid2 #endif diff --git a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HDIV_QUAD_I1_FEM.hpp b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HDIV_QUAD_I1_FEM.hpp index fab13618142c..66c5843d4da0 100644 --- a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HDIV_QUAD_I1_FEM.hpp +++ b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HDIV_QUAD_I1_FEM.hpp @@ -145,20 +145,21 @@ namespace Intrepid2 { typename pointValueType = double> class Basis_HDIV_QUAD_I1_FEM : public Basis { public: - using OrdinalTypeArray1DHost = typename Basis::OrdinalTypeArray1DHost; - using OrdinalTypeArray2DHost = typename Basis::OrdinalTypeArray2DHost; - using OrdinalTypeArray3DHost = typename Basis::OrdinalTypeArray3DHost; + using BasisBase = Basis; + using OrdinalTypeArray1DHost = typename BasisBase::OrdinalTypeArray1DHost; + using OrdinalTypeArray2DHost = typename BasisBase::OrdinalTypeArray2DHost; + using OrdinalTypeArray3DHost = typename BasisBase::OrdinalTypeArray3DHost; /** \brief Constructor. */ Basis_HDIV_QUAD_I1_FEM(); - using OutputViewType = typename Basis::OutputViewType; - using PointViewType = typename Basis::PointViewType; - using ScalarViewType = typename Basis::ScalarViewType; + using OutputViewType = typename BasisBase::OutputViewType; + using PointViewType = typename BasisBase::PointViewType; + using ScalarViewType = typename BasisBase::ScalarViewType; - using Basis::getValues; + using BasisBase::getValues; virtual void @@ -179,6 +180,23 @@ namespace Intrepid2 { operatorType ); } + virtual void + getScratchSpaceSize( ordinal_type& perTeamSpaceSize, + ordinal_type& perThreadSpaceSize, + const PointViewType inputPointsconst, + const EOperator operatorType = OPERATOR_VALUE) const override; + + KOKKOS_INLINE_FUNCTION + virtual void + getValues( + OutputViewType outputValues, + const PointViewType inputPoints, + const EOperator operatorType, + const typename Kokkos::TeamPolicy::member_type& team_member, + const typename DeviceType::execution_space::scratch_memory_space & scratchStorage, + const ordinal_type subcellDim = -1, + const ordinal_type subcellOrdinal = -1) const override; + virtual void getDofCoords( ScalarViewType dofCoords ) const override { diff --git a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HDIV_QUAD_I1_FEMDef.hpp b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HDIV_QUAD_I1_FEMDef.hpp index 1924df01978b..22eeef61929a 100644 --- a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HDIV_QUAD_I1_FEMDef.hpp +++ b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HDIV_QUAD_I1_FEMDef.hpp @@ -213,10 +213,59 @@ namespace Intrepid2 { this->dofCoeffs_ = Kokkos::create_mirror_view(typename DT::memory_space(), dofCoeffs); Kokkos::deep_copy(this->dofCoeffs_, dofCoeffs); - } + template + void + Basis_HDIV_QUAD_I1_FEM::getScratchSpaceSize( + ordinal_type& perTeamSpaceSize, + ordinal_type& perThreadSpaceSize, + const PointViewType inputPoints, + const EOperator operatorType) const { + perTeamSpaceSize = 0; + perThreadSpaceSize = 0; + } + template + KOKKOS_INLINE_FUNCTION + void + Basis_HDIV_QUAD_I1_FEM::getValues( + OutputViewType outputValues, + const PointViewType inputPoints, + const EOperator operatorType, + const typename Kokkos::TeamPolicy::member_type& team_member, + const typename DT::execution_space::scratch_memory_space & scratchStorage, + const ordinal_type subcellDim, + const ordinal_type subcellOrdinal) const { + + INTREPID2_TEST_FOR_ABORT( !((subcellDim == -1) && (subcellOrdinal == -1)), + ">>> ERROR: (Intrepid2::Basis_HDIV_QUAD_I1_FEM::getValues), The capability of selecting subsets of basis functions has not been implemented yet."); + + (void) scratchStorage; //avoid unused variable warning + + const int numPoints = inputPoints.extent(0); + + switch(operatorType) { + case OPERATOR_VALUE: + Kokkos::parallel_for (Kokkos::TeamThreadRange (team_member, numPoints), [=] (ordinal_type& pt) { + auto output = Kokkos::subview( outputValues, Kokkos::ALL(), pt, Kokkos::ALL() ); + const auto input = Kokkos::subview( inputPoints, pt, Kokkos::ALL() ); + Impl::Basis_HDIV_QUAD_I1_FEM::Serial::getValues( output, input); + }); + break; + case OPERATOR_DIV: + Kokkos::parallel_for (Kokkos::TeamThreadRange (team_member, numPoints), [=] (ordinal_type& pt) { + auto output = Kokkos::subview( outputValues, Kokkos::ALL(), pt, Kokkos::ALL() ); + const auto input = Kokkos::subview( inputPoints, pt, Kokkos::ALL() ); + Impl::Basis_HDIV_QUAD_I1_FEM::Serial::getValues( output, input); + }); + break; + default: { + INTREPID2_TEST_FOR_ABORT( true, ">>> ERROR: (Intrepid2::Basis_HDIV_QUAD_I1_FEM::getValues), Operator Type not supported."); + } + } + } + }// namespace Intrepid2 #endif diff --git a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HDIV_QUAD_In_FEM.hpp b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HDIV_QUAD_In_FEM.hpp index 3db4472991f2..60da55f64220 100644 --- a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HDIV_QUAD_In_FEM.hpp +++ b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HDIV_QUAD_In_FEM.hpp @@ -135,20 +135,21 @@ namespace Intrepid2 { class Basis_HDIV_QUAD_In_FEM : public Basis { public: - using OrdinalTypeArray1DHost = typename Basis::OrdinalTypeArray1DHost; - using OrdinalTypeArray2DHost = typename Basis::OrdinalTypeArray2DHost; - using OrdinalTypeArray3DHost = typename Basis::OrdinalTypeArray3DHost; + using BasisBase = Basis; + using OrdinalTypeArray1DHost = typename BasisBase::OrdinalTypeArray1DHost; + using OrdinalTypeArray2DHost = typename BasisBase::OrdinalTypeArray2DHost; + using OrdinalTypeArray3DHost = typename BasisBase::OrdinalTypeArray3DHost; /** \brief Constructor. */ Basis_HDIV_QUAD_In_FEM(const ordinal_type order, const EPointType pointType = POINTTYPE_EQUISPACED); - using OutputViewType = typename Basis::OutputViewType; - using PointViewType = typename Basis::PointViewType; - using ScalarViewType = typename Basis::ScalarViewType; + using OutputViewType = typename BasisBase::OutputViewType; + using PointViewType = typename BasisBase::PointViewType; + using ScalarViewType = typename BasisBase::ScalarViewType; - using Basis::getValues; + using BasisBase::getValues; virtual void @@ -170,6 +171,24 @@ namespace Intrepid2 { this->vinvBubble_, operatorType ); } + + virtual void + getScratchSpaceSize( ordinal_type& perTeamSpaceSize, + ordinal_type& perThreadSpaceSize, + const PointViewType inputPointsconst, + const EOperator operatorType = OPERATOR_VALUE) const override; + + KOKKOS_INLINE_FUNCTION + virtual void + getValues( + OutputViewType outputValues, + const PointViewType inputPoints, + const EOperator operatorType, + const typename Kokkos::TeamPolicy::member_type& team_member, + const typename DeviceType::execution_space::scratch_memory_space & scratchStorage, + const ordinal_type subcellDim = -1, + const ordinal_type subcellOrdinal = -1) const override; + virtual void getDofCoords( ScalarViewType dofCoords ) const override { diff --git a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HDIV_QUAD_In_FEMDef.hpp b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HDIV_QUAD_In_FEMDef.hpp index f6958e8152c2..ee5bdc9458c4 100644 --- a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HDIV_QUAD_In_FEMDef.hpp +++ b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HDIV_QUAD_In_FEMDef.hpp @@ -21,19 +21,19 @@ namespace Intrepid2 { // ------------------------------------------------------------------------------------- namespace Impl { - template + template template + typename InputViewType, + typename WorkViewType, + typename VinvViewType> KOKKOS_INLINE_FUNCTION void - Basis_HDIV_QUAD_In_FEM::Serial:: + Basis_HDIV_QUAD_In_FEM::Serial:: getValues( OutputViewType output, - const inputViewType input, - workViewType work, - const vinvViewType vinvLine, - const vinvViewType vinvBubble) { + const InputViewType input, + WorkViewType work, + const VinvViewType vinvLine, + const VinvViewType vinvBubble) { const ordinal_type cardLine = vinvLine.extent(0); const ordinal_type cardBubble = vinvBubble.extent(0); @@ -43,20 +43,19 @@ namespace Intrepid2 { const auto input_x = Kokkos::subview(input, Kokkos::ALL(), range_type(0,1)); const auto input_y = Kokkos::subview(input, Kokkos::ALL(), range_type(1,2)); - const int dim_s = get_dimension_scalar(work); + const ordinal_type dim_s = get_dimension_scalar(input); auto ptr0 = work.data(); auto ptr1 = work.data()+cardLine*npts*dim_s; auto ptr2 = work.data()+2*cardLine*npts*dim_s; - - typedef typename Kokkos::DynRankView viewType; - auto vcprop = Kokkos::common_view_alloc_prop(work); + typedef typename Kokkos::DynRankView ViewType; + auto vcprop = Kokkos::common_view_alloc_prop(input); - switch (opType) { + switch (OpType) { case OPERATOR_VALUE: { - viewType workLine(Kokkos::view_wrap(ptr0, vcprop), cardLine, npts); - viewType outputLine(Kokkos::view_wrap(ptr1, vcprop), cardLine, npts); - viewType outputBubble(Kokkos::view_wrap(ptr2, vcprop), cardBubble, npts); + ViewType workLine(Kokkos::view_wrap(ptr0, vcprop), cardLine, npts); + ViewType outputLine(Kokkos::view_wrap(ptr1, vcprop), cardLine, npts); + ViewType outputBubble(Kokkos::view_wrap(ptr2, vcprop), cardBubble, npts); // tensor product ordinal_type idx = 0; @@ -100,11 +99,11 @@ namespace Intrepid2 { case OPERATOR_DIV: { ordinal_type idx = 0; { // x - component - viewType workLine(Kokkos::view_wrap(ptr0, vcprop), cardLine, npts); + ViewType workLine(Kokkos::view_wrap(ptr0, vcprop), cardLine, npts); // x bubble value - viewType output_x(Kokkos::view_wrap(ptr2, vcprop), cardBubble, npts); + ViewType output_x(Kokkos::view_wrap(ptr2, vcprop), cardBubble, npts); // y line grad - viewType output_y(Kokkos::view_wrap(ptr1, vcprop), cardLine, npts,1); + ViewType output_y(Kokkos::view_wrap(ptr1, vcprop), cardLine, npts,1); Impl::Basis_HGRAD_LINE_Cn_FEM::Serial:: getValues(output_x, input_x, workLine, vinvBubble); @@ -119,11 +118,11 @@ namespace Intrepid2 { output.access(idx,k) = output_x.access(i,k)*output_y.access(j,k,0); } { // y - component - viewType workLine(Kokkos::view_wrap(ptr0, vcprop), cardLine, npts); + ViewType workLine(Kokkos::view_wrap(ptr0, vcprop), cardLine, npts); // x line grad - viewType output_x(Kokkos::view_wrap(ptr1, vcprop), cardLine, npts,1); + ViewType output_x(Kokkos::view_wrap(ptr1, vcprop), cardLine, npts,1); // y bubble value - viewType output_y(Kokkos::view_wrap(ptr2, vcprop), cardBubble, npts); + ViewType output_y(Kokkos::view_wrap(ptr2, vcprop), cardBubble, npts); Impl::Basis_HGRAD_LINE_Cn_FEM::Serial:: getValues(output_y, input_y, workLine, vinvBubble); @@ -381,6 +380,63 @@ namespace Intrepid2 { Kokkos::deep_copy(this->dofCoeffs_, dofCoeffsHost); } -} + template + void + Basis_HDIV_QUAD_In_FEM::getScratchSpaceSize( + ordinal_type& perTeamSpaceSize, + ordinal_type& perThreadSpaceSize, + const PointViewType inputPoints, + const EOperator operatorType) const { + perTeamSpaceSize = 0; + perThreadSpaceSize = (2*this->vinvLine_.extent(0)+this->vinvBubble_.extent(0))*get_dimension_scalar(inputPoints)*sizeof(typename BasisBase::scalarType); + } + + template + KOKKOS_INLINE_FUNCTION + void + Basis_HDIV_QUAD_In_FEM::getValues( + OutputViewType outputValues, + const PointViewType inputPoints, + const EOperator operatorType, + const typename Kokkos::TeamPolicy::member_type& team_member, + const typename DT::execution_space::scratch_memory_space & scratchStorage, + const ordinal_type subcellDim, + const ordinal_type subcellOrdinal) const { + + INTREPID2_TEST_FOR_ABORT( !((subcellDim == -1) && (subcellOrdinal == -1)), + ">>> ERROR: (Intrepid2::Basis_HDIV_QUAD_In_FEM::getValues), The capability of selecting subsets of basis functions has not been implemented yet."); + + const int numPoints = inputPoints.extent(0); + using ScalarType = typename ScalarTraits::scalar_type; + using WorkViewType = Kokkos::DynRankView< ScalarType,typename DT::execution_space::scratch_memory_space,Kokkos::MemoryTraits >; + ordinal_type sizePerPoint = (2*this->vinvLine_.extent(0)+this->vinvBubble_.extent(0))*get_dimension_scalar(inputPoints); + WorkViewType workView(scratchStorage, sizePerPoint*team_member.team_size()); + using range_type = Kokkos::pair; + + switch(operatorType) { + case OPERATOR_VALUE: + Kokkos::parallel_for (Kokkos::TeamThreadRange (team_member, numPoints), [=] (ordinal_type& pt) { + auto output = Kokkos::subview( outputValues, Kokkos::ALL(), range_type (pt,pt+1), Kokkos::ALL() ); + const auto input = Kokkos::subview( inputPoints, range_type(pt, pt+1), Kokkos::ALL() ); + WorkViewType work(workView.data() + sizePerPoint*team_member.team_rank(), sizePerPoint); + Impl::Basis_HDIV_QUAD_In_FEM::Serial::getValues( output, input, work, this->vinvLine_, this->vinvBubble_ ); + }); + break; + case OPERATOR_DIV: + Kokkos::parallel_for (Kokkos::TeamThreadRange (team_member, numPoints), [=] (ordinal_type& pt) { + auto output = Kokkos::subview( outputValues, Kokkos::ALL(), range_type(pt,pt+1), Kokkos::ALL() ); + const auto input = Kokkos::subview( inputPoints, range_type(pt,pt+1), Kokkos::ALL() ); + WorkViewType work(workView.data() + sizePerPoint*team_member.team_rank(), sizePerPoint); + Impl::Basis_HDIV_QUAD_In_FEM::Serial::getValues( output, input, work, this->vinvLine_, this->vinvBubble_ ); + }); + break; + default: { + INTREPID2_TEST_FOR_ABORT( true, + ">>> ERROR (Basis_HDIV_QUAD_In_FEM): getValues not implemented for this operator"); + } + } + } + +} // namespace Intrepid2 #endif diff --git a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HDIV_TET_I1_FEM.hpp b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HDIV_TET_I1_FEM.hpp index a5b72c79d540..40b58117d658 100644 --- a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HDIV_TET_I1_FEM.hpp +++ b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HDIV_TET_I1_FEM.hpp @@ -144,19 +144,21 @@ namespace Intrepid2 { typename pointValueType = double> class Basis_HDIV_TET_I1_FEM: public Basis { public: - using OrdinalTypeArray1DHost = typename Basis::OrdinalTypeArray1DHost; - using OrdinalTypeArray2DHost = typename Basis::OrdinalTypeArray2DHost; - using OrdinalTypeArray3DHost = typename Basis::OrdinalTypeArray3DHost; + using BasisBase = Basis; + + using typename BasisBase::OrdinalTypeArray1DHost; + using typename BasisBase::OrdinalTypeArray2DHost; + using typename BasisBase::OrdinalTypeArray3DHost; + + using typename BasisBase::OutputViewType; + using typename BasisBase::PointViewType ; + using typename BasisBase::ScalarViewType; /** \brief Constructor. */ Basis_HDIV_TET_I1_FEM(); - using OutputViewType = typename Basis::OutputViewType; - using PointViewType = typename Basis::PointViewType; - using ScalarViewType = typename Basis::ScalarViewType; - - using Basis::getValues; + using BasisBase::getValues; virtual void @@ -177,6 +179,23 @@ namespace Intrepid2 { operatorType ); } + virtual void + getScratchSpaceSize( ordinal_type& perTeamSpaceSize, + ordinal_type& perThreadSpaceSize, + const PointViewType inputPointsconst, + const EOperator operatorType = OPERATOR_VALUE) const override; + + KOKKOS_INLINE_FUNCTION + virtual void + getValues( + OutputViewType outputValues, + const PointViewType inputPoints, + const EOperator operatorType, + const typename Kokkos::TeamPolicy::member_type& team_member, + const typename DeviceType::execution_space::scratch_memory_space & scratchStorage, + const ordinal_type subcellDim = -1, + const ordinal_type subcellOrdinal = -1) const override; + virtual void getDofCoords( ScalarViewType dofCoords ) const override { diff --git a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HDIV_TET_I1_FEMDef.hpp b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HDIV_TET_I1_FEMDef.hpp index febd2f87333c..7aac987e9439 100644 --- a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HDIV_TET_I1_FEMDef.hpp +++ b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HDIV_TET_I1_FEMDef.hpp @@ -230,6 +230,58 @@ namespace Intrepid2 { Kokkos::deep_copy(this->dofCoeffs_, dofCoeffs); } + template + void + Basis_HDIV_TET_I1_FEM::getScratchSpaceSize( + ordinal_type& perTeamSpaceSize, + ordinal_type& perThreadSpaceSize, + const PointViewType inputPoints, + const EOperator operatorType) const { + perTeamSpaceSize = 0; + perThreadSpaceSize = 0; + } + + template + KOKKOS_INLINE_FUNCTION + void + Basis_HDIV_TET_I1_FEM::getValues( + OutputViewType outputValues, + const PointViewType inputPoints, + const EOperator operatorType, + const typename Kokkos::TeamPolicy::member_type& team_member, + const typename DT::execution_space::scratch_memory_space & scratchStorage, + const ordinal_type subcellDim, + const ordinal_type subcellOrdinal) const { + + INTREPID2_TEST_FOR_ABORT( !((subcellDim == -1) && (subcellOrdinal == -1)), + ">>> ERROR: (Intrepid2::Basis_HDIV_TET_I1_FEM::getValues), The capability of selecting subsets of basis functions has not been implemented yet."); + + (void) scratchStorage; //avoid unused variable warning + + const int numPoints = inputPoints.extent(0); + + switch(operatorType) { + case OPERATOR_VALUE: + Kokkos::parallel_for (Kokkos::TeamThreadRange (team_member, numPoints), [=] (ordinal_type& pt) { + auto output = Kokkos::subview( outputValues, Kokkos::ALL(), pt, Kokkos::ALL() ); + const auto input = Kokkos::subview( inputPoints, pt, Kokkos::ALL() ); + Impl::Basis_HDIV_TET_I1_FEM::Serial::getValues( output, input); + }); + break; + case OPERATOR_DIV: + Kokkos::parallel_for (Kokkos::TeamThreadRange (team_member, numPoints), [=] (ordinal_type& pt) { + auto output = Kokkos::subview( outputValues, Kokkos::ALL(), pt, Kokkos::ALL() ); + const auto input = Kokkos::subview( inputPoints, pt, Kokkos::ALL() ); + Impl::Basis_HDIV_TET_I1_FEM::Serial::getValues( output, input); + }); + break; + default: { + INTREPID2_TEST_FOR_ABORT( true, ">>> ERROR: (Intrepid2::Basis_HDIV_TET_I1_FEM::getValues), Operator Type not supported."); + } + } + } + }// namespace Intrepid2 + #endif diff --git a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HDIV_TET_In_FEM.hpp b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HDIV_TET_In_FEM.hpp index c2f17ac83aef..9224322f9539 100644 --- a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HDIV_TET_In_FEM.hpp +++ b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HDIV_TET_In_FEM.hpp @@ -165,131 +165,144 @@ template class Basis_HDIV_TET_In_FEM : public Basis { - public: - typedef typename Basis::OrdinalTypeArray1DHost OrdinalTypeArray1DHost; - typedef typename Basis::OrdinalTypeArray2DHost OrdinalTypeArray2DHost; - typedef typename Basis::OrdinalTypeArray3DHost OrdinalTypeArray3DHost; - - /** \brief Constructor. - */ - Basis_HDIV_TET_In_FEM(const ordinal_type order, - const EPointType pointType = POINTTYPE_EQUISPACED); - - - using OutputViewType = typename Basis::OutputViewType; - using PointViewType = typename Basis::PointViewType; - using ScalarViewType = typename Basis::ScalarViewType; - - typedef typename Basis::scalarType scalarType; - - using Basis::getValues; - - virtual - void - getValues( /* */ OutputViewType outputValues, - const PointViewType inputPoints, - const EOperator operatorType = OPERATOR_VALUE) const override { + public: + using BasisBase = Basis; + using OrdinalTypeArray1DHost = typename BasisBase::OrdinalTypeArray1DHost; + using OrdinalTypeArray2DHost = typename BasisBase::OrdinalTypeArray2DHost; + using OrdinalTypeArray3DHost = typename BasisBase::OrdinalTypeArray3DHost; + + /** \brief Constructor. + */ + Basis_HDIV_TET_In_FEM(const ordinal_type order, + const EPointType pointType = POINTTYPE_EQUISPACED); + + using OutputViewType = typename BasisBase::OutputViewType; + using PointViewType = typename BasisBase::PointViewType; + using ScalarViewType = typename BasisBase::ScalarViewType; + using scalarType = typename BasisBase::scalarType; + using BasisBase::getValues; + + virtual + void + getValues( /* */ OutputViewType outputValues, + const PointViewType inputPoints, + const EOperator operatorType = OPERATOR_VALUE) const override { #ifdef HAVE_INTREPID2_DEBUG - Intrepid2::getValues_HDIV_Args(outputValues, + Intrepid2::getValues_HDIV_Args(outputValues, inputPoints, operatorType, this->getBaseCellTopology(), this->getCardinality() ); #endif -constexpr ordinal_type numPtsPerEval = Parameters::MaxNumPtsPerBasisEval; -Impl::Basis_HDIV_TET_In_FEM:: -getValues( outputValues, - inputPoints, - this->coeffs_, - operatorType); - } - - virtual - void - getDofCoords( ScalarViewType dofCoords ) const override { + constexpr ordinal_type numPtsPerEval = Parameters::MaxNumPtsPerBasisEval; + Impl::Basis_HDIV_TET_In_FEM:: + getValues( outputValues, + inputPoints, + this->coeffs_, + operatorType); + } + + virtual void + getScratchSpaceSize( ordinal_type& perTeamSpaceSize, + ordinal_type& perThreadSpaceSize, + const PointViewType inputPointsconst, + const EOperator operatorType = OPERATOR_VALUE) const override; + + KOKKOS_INLINE_FUNCTION + virtual void + getValues( + OutputViewType outputValues, + const PointViewType inputPoints, + const EOperator operatorType, + const typename Kokkos::TeamPolicy::member_type& team_member, + const typename DeviceType::execution_space::scratch_memory_space & scratchStorage, + const ordinal_type subcellDim = -1, + const ordinal_type subcellOrdinal = -1) const override; + + virtual + void + getDofCoords( ScalarViewType dofCoords ) const override { #ifdef HAVE_INTREPID2_DEBUG - // Verify rank of output array. - INTREPID2_TEST_FOR_EXCEPTION( dofCoords.rank() != 2, std::invalid_argument, - ">>> ERROR: (Intrepid2::Basis_HDIV_TET_In_FEM::getDofCoords) rank = 2 required for dofCoords array"); - // Verify 0th dimension of output array. - INTREPID2_TEST_FOR_EXCEPTION( static_cast(dofCoords.extent(0)) != this->getCardinality(), std::invalid_argument, - ">>> ERROR: (Intrepid2::Basis_HDIV_TET_In_FEM::getDofCoords) mismatch in number of dof and 0th dimension of dofCoords array"); - // Verify 1st dimension of output array. - INTREPID2_TEST_FOR_EXCEPTION( dofCoords.extent(1) != this->getBaseCellTopology().getDimension(), std::invalid_argument, - ">>> ERROR: (Intrepid2::Basis_HDIV_TET_In_FEM::getDofCoords) incorrect reference cell (1st) dimension in dofCoords array"); + // Verify rank of output array. + INTREPID2_TEST_FOR_EXCEPTION( dofCoords.rank() != 2, std::invalid_argument, + ">>> ERROR: (Intrepid2::Basis_HDIV_TET_In_FEM::getDofCoords) rank = 2 required for dofCoords array"); + // Verify 0th dimension of output array. + INTREPID2_TEST_FOR_EXCEPTION( static_cast(dofCoords.extent(0)) != this->getCardinality(), std::invalid_argument, + ">>> ERROR: (Intrepid2::Basis_HDIV_TET_In_FEM::getDofCoords) mismatch in number of dof and 0th dimension of dofCoords array"); + // Verify 1st dimension of output array. + INTREPID2_TEST_FOR_EXCEPTION( dofCoords.extent(1) != this->getBaseCellTopology().getDimension(), std::invalid_argument, + ">>> ERROR: (Intrepid2::Basis_HDIV_TET_In_FEM::getDofCoords) incorrect reference cell (1st) dimension in dofCoords array"); #endif - Kokkos::deep_copy(dofCoords, this->dofCoords_); - } + Kokkos::deep_copy(dofCoords, this->dofCoords_); + } - virtual - void - getDofCoeffs( ScalarViewType dofCoeffs ) const override { -#ifdef HAVE_INTREPID2_DEBUG - // Verify rank of output array. - INTREPID2_TEST_FOR_EXCEPTION( dofCoeffs.rank() != 2, std::invalid_argument, - ">>> ERROR: (Intrepid2::Basis_HDIV_TET_In_FEM::getDofCoeffs) rank = 2 required for dofCoeffs array"); - // Verify 0th dimension of output array. - INTREPID2_TEST_FOR_EXCEPTION( static_cast(dofCoeffs.extent(0)) != this->getCardinality(), std::invalid_argument, + virtual + void + getDofCoeffs( ScalarViewType dofCoeffs ) const override { + #ifdef HAVE_INTREPID2_DEBUG + // Verify rank of output array. + INTREPID2_TEST_FOR_EXCEPTION( dofCoeffs.rank() != 2, std::invalid_argument, + ">>> ERROR: (Intrepid2::Basis_HDIV_TET_In_FEM::getDofCoeffs) rank = 2 required for dofCoeffs array"); + // Verify 0th dimension of output array. + INTREPID2_TEST_FOR_EXCEPTION( static_cast(dofCoeffs.extent(0)) != this->getCardinality(), std::invalid_argument, ">>> ERROR: (Intrepid2::Basis_HDIV_TET_In_FEM::getDofCoeffs) mismatch in number of dof and 0th dimension of dofCoeffs array"); - // Verify 1st dimension of output array. - INTREPID2_TEST_FOR_EXCEPTION( dofCoeffs.extent(1) != this->getBaseCellTopology().getDimension(), std::invalid_argument, + // Verify 1st dimension of output array. + INTREPID2_TEST_FOR_EXCEPTION( dofCoeffs.extent(1) != this->getBaseCellTopology().getDimension(), std::invalid_argument, ">>> ERROR: (Intrepid2::Basis_HDIV_TET_In_FEM::getDofCoeffs) incorrect reference cell (1st) dimension in dofCoeffs array"); #endif - Kokkos::deep_copy(dofCoeffs, this->dofCoeffs_); - } - - void - getExpansionCoeffs( ScalarViewType coeffs ) const { - // has to be same rank and dimensions - Kokkos::deep_copy(coeffs, this->coeffs_); - } - - virtual - const char* - getName() const override { - return "Intrepid2_HDIV_TET_In_FEM"; - } - - virtual - bool - requireOrientation() const override { - return true; - } - - /** \brief returns the basis associated to a subCell. - - The bases of the subCell are the restriction to the subCell of the bases of the parent cell, - projected along normal to the subCell. - - \param [in] subCellDim - dimension of subCell - \param [in] subCellOrd - position of the subCell among of the subCells having the same dimension - \return pointer to the subCell basis of dimension subCellDim and position subCellOrd - */ - BasisPtr - getSubCellRefBasis(const ordinal_type subCellDim, const ordinal_type subCellOrd) const override{ + Kokkos::deep_copy(dofCoeffs, this->dofCoeffs_); + } - if(subCellDim == 2) { - return Teuchos::rcp(new - Basis_HVOL_TRI_Cn_FEM - (this->basisDegree_-1, pointType_)); + void + getExpansionCoeffs( ScalarViewType coeffs ) const { + // has to be same rank and dimensions + Kokkos::deep_copy(coeffs, this->coeffs_); } - INTREPID2_TEST_FOR_EXCEPTION(true,std::invalid_argument,"Input parameters out of bounds"); - } - BasisPtr - getHostBasis() const override{ - return Teuchos::rcp(new Basis_HDIV_TET_In_FEM(this->basisDegree_, pointType_)); - } - private: + virtual + const char* + getName() const override { + return "Intrepid2_HDIV_TET_In_FEM"; + } - /** \brief expansion coefficients of the nodal basis in terms of the - orthgonal one */ - Kokkos::DynRankView coeffs_; + virtual + bool + requireOrientation() const override { + return true; + } - /** \brief type of lattice used for creating the DoF coordinates */ - EPointType pointType_; + /** \brief returns the basis associated to a subCell. -}; + The bases of the subCell are the restriction to the subCell of the bases of the parent cell, + projected along normal to the subCell. + + \param [in] subCellDim - dimension of subCell + \param [in] subCellOrd - position of the subCell among of the subCells having the same dimension + \return pointer to the subCell basis of dimension subCellDim and position subCellOrd + */ + BasisPtr + getSubCellRefBasis(const ordinal_type subCellDim, const ordinal_type subCellOrd) const override{ + + if(subCellDim == 2) { + return Teuchos::rcp(new + Basis_HVOL_TRI_Cn_FEM + (this->basisDegree_-1, pointType_)); + } + INTREPID2_TEST_FOR_EXCEPTION(true,std::invalid_argument,"Input parameters out of bounds"); + } + + BasisPtr + getHostBasis() const override{ + return Teuchos::rcp(new Basis_HDIV_TET_In_FEM(this->basisDegree_, pointType_)); + } + private: + + /** \brief expansion coefficients of the nodal basis in terms of the orthgonal one */ + Kokkos::DynRankView coeffs_; + + /** \brief type of lattice used for creating the DoF coordinates */ + EPointType pointType_; + }; }// namespace Intrepid2 diff --git a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HDIV_TET_In_FEMDef.hpp b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HDIV_TET_In_FEMDef.hpp index e8c97199198f..96e0e7cf2267 100644 --- a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HDIV_TET_In_FEMDef.hpp +++ b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HDIV_TET_In_FEMDef.hpp @@ -25,18 +25,18 @@ namespace Intrepid2 { namespace Impl { -template +template template +typename InputViewType, +typename WorkViewType, +typename VinvViewType> KOKKOS_INLINE_FUNCTION void -Basis_HDIV_TET_In_FEM::Serial:: +Basis_HDIV_TET_In_FEM::Serial:: getValues( OutputViewType output, - const inputViewType input, - workViewType work, - const vinvViewType coeffs ) { + const InputViewType input, + WorkViewType work, + const VinvViewType coeffs ) { constexpr ordinal_type spaceDim = 3; const ordinal_type @@ -53,17 +53,17 @@ getValues( OutputViewType output, } } - typedef typename Kokkos::DynRankView viewType; - auto vcprop = Kokkos::common_view_alloc_prop(work); + typedef typename Kokkos::DynRankView ViewType; + auto vcprop = Kokkos::common_view_alloc_prop(input); auto ptr = work.data(); - switch (opType) { + switch (OpType) { case OPERATOR_VALUE: { - const viewType phis(Kokkos::view_wrap(ptr, vcprop), card, npts); - workViewType dummyView; + const ViewType phis(Kokkos::view_wrap(ptr, vcprop), card, npts); + ViewType dummyView; Impl::Basis_HGRAD_TET_Cn_FEM_ORTH:: - Serial::getValues(phis, input, dummyView, order); + Serial::getValues(phis, input, dummyView, order); for (ordinal_type i=0;i::getValues(phis, input, workView, order); @@ -104,10 +104,10 @@ typename inputPointValueType, class ...inputPointProperties, typename vinvValueType, class ...vinvProperties> void Basis_HDIV_TET_In_FEM:: -getValues( /* */ Kokkos::DynRankView outputValues, - const Kokkos::DynRankView inputPoints, - const Kokkos::DynRankView coeffs, - const EOperator operatorType) { +getValues( Kokkos::DynRankView outputValues, + const Kokkos::DynRankView inputPoints, + const Kokkos::DynRankView coeffs, + const EOperator operatorType) { typedef Kokkos::DynRankView outputValueViewType; typedef Kokkos::DynRankView inputPointViewType; typedef Kokkos::DynRankView vinvViewType; @@ -450,5 +450,64 @@ Basis_HDIV_TET_In_FEM( const ordinal_type order, posDfOrd); } } + +template +void +Basis_HDIV_TET_In_FEM::getScratchSpaceSize( + ordinal_type& perTeamSpaceSize, + ordinal_type& perThreadSpaceSize, + const PointViewType inputPoints, + const EOperator operatorType) const { + perTeamSpaceSize = 0; + ordinal_type scalarWorkViewExtent = (operatorType == OPERATOR_VALUE) ? this->basisCardinality_ : 7*this->basisCardinality_; + perThreadSpaceSize = scalarWorkViewExtent*get_dimension_scalar(inputPoints)*sizeof(typename BasisBase::scalarType); +} + +template +KOKKOS_INLINE_FUNCTION +void +Basis_HDIV_TET_In_FEM::getValues( + OutputViewType outputValues, + const PointViewType inputPoints, + const EOperator operatorType, + const typename Kokkos::TeamPolicy::member_type& team_member, + const typename DT::execution_space::scratch_memory_space & scratchStorage, + const ordinal_type subcellDim, + const ordinal_type subcellOrdinal) const { + + INTREPID2_TEST_FOR_ABORT( !((subcellDim == -1) && (subcellOrdinal == -1)), + ">>> ERROR: (Intrepid2::Basis_HDIV_TET_In_FEM::getValues), The capability of selecting subsets of basis functions has not been implemented yet."); + + const int numPoints = inputPoints.extent(0); + using ScalarType = typename ScalarTraits::scalar_type; + using WorkViewType = Kokkos::DynRankView< ScalarType,typename DT::execution_space::scratch_memory_space,Kokkos::MemoryTraits >; + ordinal_type scalarSizePerPoint = (operatorType == OPERATOR_VALUE) ? this->basisCardinality_ : 7*this->basisCardinality_; + ordinal_type sizePerPoint = scalarSizePerPoint*get_dimension_scalar(inputPoints); + WorkViewType workView(scratchStorage, sizePerPoint*team_member.team_size()); + using range_type = Kokkos::pair; + + switch(operatorType) { + case OPERATOR_VALUE: + Kokkos::parallel_for (Kokkos::TeamThreadRange (team_member, numPoints), [=] (ordinal_type& pt) { + auto output = Kokkos::subview( outputValues, Kokkos::ALL(), range_type (pt,pt+1), Kokkos::ALL() ); + const auto input = Kokkos::subview( inputPoints, range_type(pt, pt+1), Kokkos::ALL() ); + WorkViewType work(workView.data() + sizePerPoint*team_member.team_rank(), sizePerPoint); + Impl::Basis_HDIV_TET_In_FEM::Serial::getValues( output, input, work, this->coeffs_ ); + }); + break; + case OPERATOR_DIV: + Kokkos::parallel_for (Kokkos::TeamThreadRange (team_member, numPoints), [=] (ordinal_type& pt) { + auto output = Kokkos::subview( outputValues, Kokkos::ALL(), range_type(pt,pt+1), Kokkos::ALL() ); + const auto input = Kokkos::subview( inputPoints, range_type(pt,pt+1), Kokkos::ALL() ); + WorkViewType work(workView.data() + sizePerPoint*team_member.team_rank(), sizePerPoint); + Impl::Basis_HDIV_TET_In_FEM::Serial::getValues( output, input, work, this->coeffs_ ); + }); + break; + default: { + INTREPID2_TEST_FOR_ABORT( true, + ">>> ERROR (Basis_HDIV_TET_In_FEM): getValues not implemented for this operator"); + } + } +} } // namespace Intrepid2 #endif diff --git a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HDIV_TRI_I1_FEM.hpp b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HDIV_TRI_I1_FEM.hpp index 6f6596778567..8315ac027c92 100644 --- a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HDIV_TRI_I1_FEM.hpp +++ b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HDIV_TRI_I1_FEM.hpp @@ -142,19 +142,21 @@ namespace Intrepid2 { typename pointValueType = double> class Basis_HDIV_TRI_I1_FEM: public Basis { public: - using OrdinalTypeArray1DHost = typename Basis::OrdinalTypeArray1DHost; - using OrdinalTypeArray2DHost = typename Basis::OrdinalTypeArray2DHost; - using OrdinalTypeArray3DHost = typename Basis::OrdinalTypeArray3DHost; + using BasisBase = Basis; + + using typename BasisBase::OrdinalTypeArray1DHost; + using typename BasisBase::OrdinalTypeArray2DHost; + using typename BasisBase::OrdinalTypeArray3DHost; + + using typename BasisBase::OutputViewType; + using typename BasisBase::PointViewType ; + using typename BasisBase::ScalarViewType; /** \brief Constructor. */ Basis_HDIV_TRI_I1_FEM(); - using OutputViewType = typename Basis::OutputViewType; - using PointViewType = typename Basis::PointViewType; - using ScalarViewType = typename Basis::ScalarViewType; - - using Basis::getValues; + using BasisBase::getValues; virtual void @@ -175,6 +177,23 @@ namespace Intrepid2 { operatorType ); } + virtual void + getScratchSpaceSize( ordinal_type& perTeamSpaceSize, + ordinal_type& perThreadSpaceSize, + const PointViewType inputPointsconst, + const EOperator operatorType = OPERATOR_VALUE) const override; + + KOKKOS_INLINE_FUNCTION + virtual void + getValues( + OutputViewType outputValues, + const PointViewType inputPoints, + const EOperator operatorType, + const typename Kokkos::TeamPolicy::member_type& team_member, + const typename DeviceType::execution_space::scratch_memory_space & scratchStorage, + const ordinal_type subcellDim = -1, + const ordinal_type subcellOrdinal = -1) const override; + virtual void getDofCoords( ScalarViewType dofCoords ) const override { diff --git a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HDIV_TRI_I1_FEMDef.hpp b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HDIV_TRI_I1_FEMDef.hpp index a7c13864b3a2..ef00a009fdc7 100644 --- a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HDIV_TRI_I1_FEMDef.hpp +++ b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HDIV_TRI_I1_FEMDef.hpp @@ -72,6 +72,7 @@ namespace Intrepid2 { typedef Kokkos::DynRankView inputPointViewType; typedef typename ExecSpace::ExecSpaceType ExecSpaceType; + // Number of evaluation points = dim 0 of inputPoints const auto loopSize = inputPoints.extent(0); Kokkos::RangePolicy > policy(0, loopSize); @@ -215,5 +216,56 @@ namespace Intrepid2 { } + template + void + Basis_HDIV_TRI_I1_FEM::getScratchSpaceSize( + ordinal_type& perTeamSpaceSize, + ordinal_type& perThreadSpaceSize, + const PointViewType inputPoints, + const EOperator operatorType) const { + perTeamSpaceSize = 0; + perThreadSpaceSize = 0; + } + + template + KOKKOS_INLINE_FUNCTION + void + Basis_HDIV_TRI_I1_FEM::getValues( + OutputViewType outputValues, + const PointViewType inputPoints, + const EOperator operatorType, + const typename Kokkos::TeamPolicy::member_type& team_member, + const typename DT::execution_space::scratch_memory_space & scratchStorage, + const ordinal_type subcellDim, + const ordinal_type subcellOrdinal) const { + + INTREPID2_TEST_FOR_ABORT( !((subcellDim == -1) && (subcellOrdinal == -1)), + ">>> ERROR: (Intrepid2::Basis_HDIV_TRI_I1_FEM::getValues), The capability of selecting subsets of basis functions has not been implemented yet."); + + (void) scratchStorage; //avoid unused variable warning + + const int numPoints = inputPoints.extent(0); + + switch(operatorType) { + case OPERATOR_VALUE: + Kokkos::parallel_for (Kokkos::TeamThreadRange (team_member, numPoints), [=] (ordinal_type& pt) { + auto output = Kokkos::subview( outputValues, Kokkos::ALL(), pt, Kokkos::ALL() ); + const auto input = Kokkos::subview( inputPoints, pt, Kokkos::ALL() ); + Impl::Basis_HDIV_TRI_I1_FEM::Serial::getValues( output, input); + }); + break; + case OPERATOR_DIV: + Kokkos::parallel_for (Kokkos::TeamThreadRange (team_member, numPoints), [=] (ordinal_type& pt) { + auto output = Kokkos::subview( outputValues, Kokkos::ALL(), pt, Kokkos::ALL() ); + const auto input = Kokkos::subview( inputPoints, pt, Kokkos::ALL() ); + Impl::Basis_HDIV_TRI_I1_FEM::Serial::getValues( output, input); + }); + break; + default: { + INTREPID2_TEST_FOR_ABORT( true, ">>> ERROR: (Intrepid2::Basis_HDIV_TRI_!1_FEM::getValues), Operator Type not supported."); + } + } + } + }// namespace Intrepid2 #endif diff --git a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HDIV_TRI_In_FEM.hpp b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HDIV_TRI_In_FEM.hpp index 71fd4f8ae99d..1ca324c938ef 100644 --- a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HDIV_TRI_In_FEM.hpp +++ b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HDIV_TRI_In_FEM.hpp @@ -169,31 +169,30 @@ template class Basis_HDIV_TRI_In_FEM : public Basis { - public: - typedef typename Basis::OrdinalTypeArray1DHost OrdinalTypeArray1DHost; - typedef typename Basis::OrdinalTypeArray2DHost OrdinalTypeArray2DHost; - typedef typename Basis::OrdinalTypeArray3DHost OrdinalTypeArray3DHost; - - /** \brief Constructor. - */ - Basis_HDIV_TRI_In_FEM(const ordinal_type order, + public: + using BasisBase = Basis; + using OrdinalTypeArray1DHost = typename BasisBase::OrdinalTypeArray1DHost; + using OrdinalTypeArray2DHost = typename BasisBase::OrdinalTypeArray2DHost; + using OrdinalTypeArray3DHost = typename BasisBase::OrdinalTypeArray3DHost; + + /** \brief Constructor. + */ + Basis_HDIV_TRI_In_FEM(const ordinal_type order, const EPointType pointType = POINTTYPE_EQUISPACED); - using HostBasis = Basis_HDIV_TRI_In_FEM; + using HostBasis = Basis_HDIV_TRI_In_FEM; - using OutputViewType = typename Basis::OutputViewType; - using PointViewType = typename Basis::PointViewType; - using ScalarViewType = typename Basis::ScalarViewType; - - typedef typename Basis::scalarType scalarType; - - using Basis::getValues; + using OutputViewType = typename BasisBase::OutputViewType; + using PointViewType = typename BasisBase::PointViewType; + using ScalarViewType = typename BasisBase::ScalarViewType; + using scalarType = typename BasisBase::scalarType; + using BasisBase::getValues; virtual void - getValues( /* */ OutputViewType outputValues, - const PointViewType inputPoints, - const EOperator operatorType = OPERATOR_VALUE) const override { + getValues( OutputViewType outputValues, + const PointViewType inputPoints, + const EOperator operatorType = OPERATOR_VALUE) const override { #ifdef HAVE_INTREPID2_DEBUG Intrepid2::getValues_HDIV_Args(outputValues, inputPoints, @@ -209,9 +208,26 @@ class Basis_HDIV_TRI_In_FEM operatorType); } - virtual - void - getDofCoords( ScalarViewType dofCoords ) const override { + virtual void + getScratchSpaceSize( ordinal_type& perTeamSpaceSize, + ordinal_type& perThreadSpaceSize, + const PointViewType inputPointsconst, + const EOperator operatorType = OPERATOR_VALUE) const override; + + KOKKOS_INLINE_FUNCTION + virtual void + getValues( + OutputViewType outputValues, + const PointViewType inputPoints, + const EOperator operatorType, + const typename Kokkos::TeamPolicy::member_type& team_member, + const typename DeviceType::execution_space::scratch_memory_space & scratchStorage, + const ordinal_type subcellDim = -1, + const ordinal_type subcellOrdinal = -1) const override; + + virtual + void + getDofCoords( ScalarViewType dofCoords ) const override { #ifdef HAVE_INTREPID2_DEBUG // Verify rank of output array. INTREPID2_TEST_FOR_EXCEPTION( dofCoords.rank() != 2, std::invalid_argument, diff --git a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HDIV_TRI_In_FEMDef.hpp b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HDIV_TRI_In_FEMDef.hpp index e412989caa56..89c86f5274e9 100644 --- a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HDIV_TRI_In_FEMDef.hpp +++ b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HDIV_TRI_In_FEMDef.hpp @@ -24,18 +24,18 @@ namespace Intrepid2 { // ------------------------------------------------------------------------------------- namespace Impl { -template +template template +typename InputViewType, +typename WorkViewType, +typename VinvViewType> KOKKOS_INLINE_FUNCTION void -Basis_HDIV_TRI_In_FEM::Serial:: -getValues( /* */ OutputViewType output, - const inputViewType input, - /* */ workViewType work, - const vinvViewType coeffs ) { +Basis_HDIV_TRI_In_FEM::Serial:: +getValues( OutputViewType output, + const InputViewType input, + WorkViewType work, + const VinvViewType coeffs ) { constexpr ordinal_type spaceDim = 2; const ordinal_type @@ -52,17 +52,17 @@ getValues( /* */ OutputViewType output, } } - typedef typename Kokkos::DynRankView viewType; - auto vcprop = Kokkos::common_view_alloc_prop(work); + typedef typename Kokkos::DynRankView ViewType; + auto vcprop = Kokkos::common_view_alloc_prop(input); auto ptr = work.data(); - switch (opType) { + switch (OpType) { case OPERATOR_VALUE: { - const viewType phis(Kokkos::view_wrap(ptr, vcprop), card, npts); - workViewType dummyView; + const ViewType phis(Kokkos::view_wrap(ptr, vcprop), card, npts); + ViewType dummyView; Impl::Basis_HGRAD_TRI_Cn_FEM_ORTH:: - Serial::getValues(phis, input, dummyView, order); + Serial::getValues(phis, input, dummyView, order); for (ordinal_type i=0;i::getValues(phis, input, workView, order); @@ -447,5 +447,65 @@ Basis_HDIV_TRI_In_FEM( const ordinal_type order, posDfOrd); } } + + template + void + Basis_HDIV_TRI_In_FEM::getScratchSpaceSize( + ordinal_type& perTeamSpaceSize, + ordinal_type& perThreadSpaceSize, + const PointViewType inputPoints, + const EOperator operatorType) const { + perTeamSpaceSize = 0; + ordinal_type scalarWorkViewExtent = (operatorType == OPERATOR_VALUE) ? this->basisCardinality_ : 5*this->basisCardinality_; + perThreadSpaceSize = scalarWorkViewExtent*get_dimension_scalar(inputPoints)*sizeof(scalarType); + } + + template + KOKKOS_INLINE_FUNCTION + void + Basis_HDIV_TRI_In_FEM::getValues( + OutputViewType outputValues, + const PointViewType inputPoints, + const EOperator operatorType, + const typename Kokkos::TeamPolicy::member_type& team_member, + const typename DT::execution_space::scratch_memory_space & scratchStorage, + const ordinal_type subcellDim, + const ordinal_type subcellOrdinal) const { + + INTREPID2_TEST_FOR_ABORT( !((subcellDim == -1) && (subcellOrdinal == -1)), + ">>> ERROR: (Intrepid2::Basis_HDIV_TRI_In_FEM::getValues), The capability of selecting subsets of basis functions has not been implemented yet."); + + const int numPoints = inputPoints.extent(0); + using WorkViewType = Kokkos::DynRankView< scalarType, typename DT::execution_space::scratch_memory_space,Kokkos::MemoryTraits >; + ordinal_type scalarSizePerPoint = (operatorType == OPERATOR_VALUE) ? this->basisCardinality_ : 5*this->basisCardinality_; + ordinal_type sizePerPoint = scalarSizePerPoint*get_dimension_scalar(inputPoints); + WorkViewType workView(scratchStorage, sizePerPoint*team_member.team_size()); + using range_type = Kokkos::pair; + + switch(operatorType) { + case OPERATOR_VALUE: + Kokkos::parallel_for (Kokkos::TeamThreadRange (team_member, numPoints), [=] (ordinal_type& pt) { + auto output = Kokkos::subview( outputValues, Kokkos::ALL(), range_type (pt,pt+1), Kokkos::ALL() ); + const auto input = Kokkos::subview( inputPoints, range_type(pt, pt+1), Kokkos::ALL() ); + WorkViewType work(workView.data() + sizePerPoint*team_member.team_rank(), sizePerPoint); + Impl::Basis_HDIV_TRI_In_FEM::Serial::getValues( output, input, work, this->coeffs_ ); + }); + break; + case OPERATOR_DIV: + Kokkos::parallel_for (Kokkos::TeamThreadRange (team_member, numPoints), [=] (ordinal_type& pt) { + auto output = Kokkos::subview( outputValues, Kokkos::ALL(), range_type(pt,pt+1), Kokkos::ALL() ); + const auto input = Kokkos::subview( inputPoints, range_type(pt,pt+1), Kokkos::ALL() ); + WorkViewType work(workView.data() + sizePerPoint*team_member.team_rank(), sizePerPoint); + Impl::Basis_HDIV_TRI_In_FEM::Serial::getValues( output, input, work, this->coeffs_ ); + }); + break; + default: { + INTREPID2_TEST_FOR_ABORT( true, + ">>> ERROR (Basis_HDIV_TRI_In_FEM): getValues not implemented for this operator"); + } + } + } + } // namespace Intrepid2 + #endif diff --git a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HDIV_WEDGE_I1_FEM.hpp b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HDIV_WEDGE_I1_FEM.hpp index d30c7d1ee4a3..56a257b9ce54 100644 --- a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HDIV_WEDGE_I1_FEM.hpp +++ b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HDIV_WEDGE_I1_FEM.hpp @@ -159,6 +159,23 @@ namespace Intrepid2 { operatorType ); } + virtual void + getScratchSpaceSize( ordinal_type& perTeamSpaceSize, + ordinal_type& perThreadSpaceSize, + const PointViewType inputPointsconst, + const EOperator operatorType = OPERATOR_VALUE) const override; + + KOKKOS_INLINE_FUNCTION + virtual void + getValues( + OutputViewType outputValues, + const PointViewType inputPoints, + const EOperator operatorType, + const typename Kokkos::TeamPolicy::member_type& team_member, + const typename DeviceType::execution_space::scratch_memory_space & scratchStorage, + const ordinal_type subcellDim = -1, + const ordinal_type subcellOrdinal = -1) const override; + virtual void getDofCoords( ScalarViewType dofCoords ) const override { diff --git a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HDIV_WEDGE_I1_FEMDef.hpp b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HDIV_WEDGE_I1_FEMDef.hpp index 79dabbc6bfa6..ceefba8ac59e 100644 --- a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HDIV_WEDGE_I1_FEMDef.hpp +++ b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HDIV_WEDGE_I1_FEMDef.hpp @@ -183,7 +183,60 @@ namespace Intrepid2 { this->dofCoeffs_ = Kokkos::create_mirror_view(typename DT::memory_space(), dofCoeffs); Kokkos::deep_copy(this->dofCoeffs_, dofCoeffs); + + } + + template + void + Basis_HDIV_WEDGE_I1_FEM::getScratchSpaceSize( + ordinal_type& perTeamSpaceSize, + ordinal_type& perThreadSpaceSize, + const PointViewType inputPoints, + const EOperator operatorType) const { + perTeamSpaceSize = 0; + perThreadSpaceSize = 0; } + template + KOKKOS_INLINE_FUNCTION + void + Basis_HDIV_WEDGE_I1_FEM::getValues( + OutputViewType outputValues, + const PointViewType inputPoints, + const EOperator operatorType, + const typename Kokkos::TeamPolicy::member_type& team_member, + const typename DT::execution_space::scratch_memory_space & scratchStorage, + const ordinal_type subcellDim, + const ordinal_type subcellOrdinal) const { + + INTREPID2_TEST_FOR_ABORT( !((subcellDim == -1) && (subcellOrdinal == -1)), + ">>> ERROR: (Intrepid2::Basis_HDIV_WEDGE_I1_FEM::getValues), The capability of selecting subsets of basis functions has not been implemented yet."); + + (void) scratchStorage; //avoid unused variable warning + + const int numPoints = inputPoints.extent(0); + + switch(operatorType) { + case OPERATOR_VALUE: + Kokkos::parallel_for (Kokkos::TeamThreadRange (team_member, numPoints), [=] (ordinal_type& pt) { + auto output = Kokkos::subview( outputValues, Kokkos::ALL(), pt, Kokkos::ALL() ); + const auto input = Kokkos::subview( inputPoints, pt, Kokkos::ALL() ); + Impl::Basis_HDIV_WEDGE_I1_FEM::Serial::getValues( output, input); + }); + break; + case OPERATOR_DIV: + Kokkos::parallel_for (Kokkos::TeamThreadRange (team_member, numPoints), [=] (ordinal_type& pt) { + auto output = Kokkos::subview( outputValues, Kokkos::ALL(), pt, Kokkos::ALL() ); + const auto input = Kokkos::subview( inputPoints, pt, Kokkos::ALL() ); + Impl::Basis_HDIV_WEDGE_I1_FEM::Serial::getValues( output, input); + }); + break; + default: { + INTREPID2_TEST_FOR_ABORT( true, ">>> ERROR: (Intrepid2::Basis_HDIV_WEDGE_I1_FEM::getValues), Operator Type not supported."); + } + } + } + }// namespace Intrepid2 + #endif diff --git a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_HEX_C1_FEM.hpp b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_HEX_C1_FEM.hpp index 2ea99d81a411..59dfdfff0451 100644 --- a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_HEX_C1_FEM.hpp +++ b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_HEX_C1_FEM.hpp @@ -177,6 +177,23 @@ namespace Intrepid2 { operatorType); } + virtual void + getScratchSpaceSize( ordinal_type& perTeamSpaceSize, + ordinal_type& perThreadSpaceSize, + const PointViewType inputPointsconst, + const EOperator operatorType = OPERATOR_VALUE) const override; + + KOKKOS_INLINE_FUNCTION + virtual void + getValues( + OutputViewType outputValues, + const PointViewType inputPoints, + const EOperator operatorType, + const typename Kokkos::TeamPolicy::member_type& team_member, + const typename DeviceType::execution_space::scratch_memory_space & scratchStorage, + const ordinal_type subcellDim = -1, + const ordinal_type subcellOrdinal = -1) const override; + virtual void getDofCoords( ScalarViewType dofCoords ) const override { diff --git a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_HEX_C1_FEMDef.hpp b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_HEX_C1_FEMDef.hpp index 96a5fcf39429..3c2813faa81e 100644 --- a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_HEX_C1_FEMDef.hpp +++ b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_HEX_C1_FEMDef.hpp @@ -413,6 +413,55 @@ namespace Intrepid2 { Kokkos::deep_copy(this->dofCoords_, dofCoords); } + template + void + Basis_HGRAD_HEX_C1_FEM::getScratchSpaceSize( + ordinal_type& perTeamSpaceSize, + ordinal_type& perThreadSpaceSize, + const PointViewType inputPoints, + const EOperator operatorType) const { + perTeamSpaceSize = 0; + perThreadSpaceSize = 0; + } + + template + KOKKOS_INLINE_FUNCTION + void + Basis_HGRAD_HEX_C1_FEM::getValues( + OutputViewType outputValues, + const PointViewType inputPoints, + const EOperator operatorType, + const typename Kokkos::TeamPolicy::member_type& team_member, + const typename DT::execution_space::scratch_memory_space & scratchStorage, + const ordinal_type subcellDim, + const ordinal_type subcellOrdinal) const { + + INTREPID2_TEST_FOR_ABORT( !((subcellDim <= 0) && (subcellOrdinal == -1)), + ">>> ERROR: (Intrepid2::Basis_HGRAD_HEX_C1_FEM::getValues), The capability of selecting subsets of basis functions has not been implemented yet."); + + (void) scratchStorage; //avoid unused variable warning + + const int numPoints = inputPoints.extent(0); + + switch(operatorType) { + case OPERATOR_VALUE: + Kokkos::parallel_for (Kokkos::TeamThreadRange (team_member, numPoints), [=] (ordinal_type& pt) { + auto output = Kokkos::subview( outputValues, Kokkos::ALL(), pt, Kokkos::ALL() ); + const auto input = Kokkos::subview( inputPoints, pt, Kokkos::ALL() ); + Impl::Basis_HGRAD_HEX_C1_FEM::Serial::getValues( output, input); + }); + break; + case OPERATOR_GRAD: + Kokkos::parallel_for (Kokkos::TeamThreadRange (team_member, numPoints), [=] (ordinal_type& pt) { + auto output = Kokkos::subview( outputValues, Kokkos::ALL(), pt, Kokkos::ALL() ); + const auto input = Kokkos::subview( inputPoints, pt, Kokkos::ALL() ); + Impl::Basis_HGRAD_HEX_C1_FEM::Serial::getValues( output, input); + }); + break; + default: {} + } + } + }// namespace Intrepid2 #endif diff --git a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_HEX_C2_FEM.hpp b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_HEX_C2_FEM.hpp index 9823b1fe23bd..1af419c4300e 100644 --- a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_HEX_C2_FEM.hpp +++ b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_HEX_C2_FEM.hpp @@ -245,6 +245,23 @@ namespace Intrepid2 { operatorType); } + virtual void + getScratchSpaceSize( ordinal_type& perTeamSpaceSize, + ordinal_type& perThreadSpaceSize, + const PointViewType inputPointsconst, + const EOperator operatorType = OPERATOR_VALUE) const override; + + KOKKOS_INLINE_FUNCTION + virtual void + getValues( + OutputViewType outputValues, + const PointViewType inputPoints, + const EOperator operatorType, + const typename Kokkos::TeamPolicy::member_type& team_member, + const typename DeviceType::execution_space::scratch_memory_space & scratchStorage, + const ordinal_type subcellDim = -1, + const ordinal_type subcellOrdinal = -1) const override; + virtual void getDofCoords( ScalarViewType dofCoords ) const override { diff --git a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_HEX_C2_FEMDef.hpp b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_HEX_C2_FEMDef.hpp index 22e1a54b74b4..c5a5ec102087 100644 --- a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_HEX_C2_FEMDef.hpp +++ b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_HEX_C2_FEMDef.hpp @@ -1626,8 +1626,57 @@ namespace Intrepid2 { this->dofCoords_ = Kokkos::create_mirror_view(typename DT::memory_space(), dofCoords); Kokkos::deep_copy(this->dofCoords_, dofCoords); + } + template + void + Basis_HGRAD_HEX_DEG2_FEM::getScratchSpaceSize( + ordinal_type& perTeamSpaceSize, + ordinal_type& perThreadSpaceSize, + const PointViewType inputPoints, + const EOperator operatorType) const { + perTeamSpaceSize = 0; + perThreadSpaceSize = 0; } + template + KOKKOS_INLINE_FUNCTION + void + Basis_HGRAD_HEX_DEG2_FEM::getValues( + OutputViewType outputValues, + const PointViewType inputPoints, + const EOperator operatorType, + const typename Kokkos::TeamPolicy::member_type& team_member, + const typename DT::execution_space::scratch_memory_space & scratchStorage, + const ordinal_type subcellDim, + const ordinal_type subcellOrdinal) const { + + INTREPID2_TEST_FOR_ABORT( !((subcellDim <= 0) && (subcellOrdinal == -1)), + ">>> ERROR: (Intrepid2::Basis_HGRAD_HEX_DEG2_FEM::getValues), The capability of selecting subsets of basis functions has not been implemented yet."); + + (void) scratchStorage; //avoid unused variable warning + + const int numPoints = inputPoints.extent(0); + + switch(operatorType) { + case OPERATOR_VALUE: + Kokkos::parallel_for (Kokkos::TeamThreadRange (team_member, numPoints), [=] (ordinal_type& pt) { + auto output = Kokkos::subview( outputValues, Kokkos::ALL(), pt, Kokkos::ALL() ); + const auto input = Kokkos::subview( inputPoints, pt, Kokkos::ALL() ); + using SerialValue = typename Impl::Basis_HGRAD_HEX_DEG2_FEM::template Serial; + SerialValue::getValues( output, input); + }); + break; + case OPERATOR_GRAD: + Kokkos::parallel_for (Kokkos::TeamThreadRange (team_member, numPoints), [=] (ordinal_type& pt) { + auto output = Kokkos::subview( outputValues, Kokkos::ALL(), pt, Kokkos::ALL() ); + const auto input = Kokkos::subview( inputPoints, pt, Kokkos::ALL() ); + using SerialGrad = typename Impl::Basis_HGRAD_HEX_DEG2_FEM::template Serial; + SerialGrad::getValues( output, input); + }); + break; + default: {} + } + } }// namespace Intrepid2 #endif diff --git a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_HEX_Cn_FEM.hpp b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_HEX_Cn_FEM.hpp index 4bcefb52d286..987206b0a1e0 100644 --- a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_HEX_Cn_FEM.hpp +++ b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_HEX_Cn_FEM.hpp @@ -184,6 +184,23 @@ namespace Intrepid2 { operatorType); } + virtual void + getScratchSpaceSize( ordinal_type& perTeamSpaceSize, + ordinal_type& perThreadSpaceSize, + const PointViewType inputPoints, + const EOperator operatorType = OPERATOR_VALUE) const override; + + KOKKOS_INLINE_FUNCTION + virtual void + getValues( + OutputViewType outputValues, + const PointViewType inputPoints, + const EOperator operatorType, + const typename Kokkos::TeamPolicy::member_type& team_member, + const typename DeviceType::execution_space::scratch_memory_space & scratchStorage, + const ordinal_type subcellDim = -1, + const ordinal_type subcellOrdinal = -1) const override; + virtual void diff --git a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_HEX_Cn_FEMDef.hpp b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_HEX_Cn_FEMDef.hpp index ac50cde72fb3..36139dfb95f4 100644 --- a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_HEX_Cn_FEMDef.hpp +++ b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_HEX_Cn_FEMDef.hpp @@ -44,14 +44,14 @@ namespace Intrepid2 { const auto input_y = Kokkos::subview(input, Kokkos::ALL(), range_type(1,2)); const auto input_z = Kokkos::subview(input, Kokkos::ALL(), range_type(2,3)); - const ordinal_type dim_s = get_dimension_scalar(work); + const ordinal_type dim_s = get_dimension_scalar(input); auto ptr0 = work.data(); auto ptr1 = work.data()+cardLine*npts*dim_s; auto ptr2 = work.data()+2*cardLine*npts*dim_s; auto ptr3 = work.data()+3*cardLine*npts*dim_s; - typedef typename Kokkos::DynRankView viewType; - auto vcprop = Kokkos::common_view_alloc_prop(work); + typedef typename Kokkos::DynRankView viewType; + auto vcprop = Kokkos::common_view_alloc_prop(input); switch (opType) { case OPERATOR_VALUE: { @@ -382,7 +382,64 @@ namespace Intrepid2 { this->dofCoords_ = Kokkos::create_mirror_view(typename DT::memory_space(), dofCoordsHost); Kokkos::deep_copy(this->dofCoords_, dofCoordsHost); } - + + template + void + Basis_HGRAD_HEX_Cn_FEM::getScratchSpaceSize( + ordinal_type& perTeamSpaceSize, + ordinal_type& perThreadSpaceSize, + const PointViewType inputPoints, + const EOperator operatorType) const { + (void) operatorType; //avoid warning for unused variable + perTeamSpaceSize = 0; + perThreadSpaceSize = 4*this->vinv_.extent(0)*get_dimension_scalar(inputPoints)*sizeof(typename BasisBase::scalarType); + } + + template + KOKKOS_INLINE_FUNCTION + void + Basis_HGRAD_HEX_Cn_FEM::getValues( + OutputViewType outputValues, + const PointViewType inputPoints, + const EOperator operatorType, + const typename Kokkos::TeamPolicy::member_type& team_member, + const typename DT::execution_space::scratch_memory_space & scratchStorage, + const ordinal_type subcellDim, + const ordinal_type subcellOrdinal) const { + + INTREPID2_TEST_FOR_ABORT( !((subcellDim == -1) && (subcellOrdinal == -1)), + ">>> ERROR: (Intrepid2::Basis_HGRAD_HEX_Cn_FEM::getValues), The capability of selecting subsets of basis functions has not been implemented yet."); + + const int numPoints = inputPoints.extent(0); + using ScalarType = typename ScalarTraits::scalar_type; + using WorkViewType = Kokkos::DynRankView< ScalarType,typename DT::execution_space::scratch_memory_space,Kokkos::MemoryTraits >; + ordinal_type sizePerPoint = 4*this->vinv_.extent(0)*get_dimension_scalar(inputPoints); + WorkViewType workView(scratchStorage, sizePerPoint*team_member.team_size()); + using range_type = Kokkos::pair; + + switch(operatorType) { + case OPERATOR_VALUE: + Kokkos::parallel_for (Kokkos::TeamThreadRange (team_member, numPoints), [=] (ordinal_type& pt) { + auto output = Kokkos::subview( outputValues, Kokkos::ALL(), range_type (pt,pt+1), Kokkos::ALL() ); + const auto input = Kokkos::subview( inputPoints, range_type(pt, pt+1), Kokkos::ALL() ); + WorkViewType work(workView.data() + sizePerPoint*team_member.team_rank(), sizePerPoint); + Impl::Basis_HGRAD_HEX_Cn_FEM::Serial::getValues( output, input, work, this->vinv_ ); + }); + break; + case OPERATOR_GRAD: + Kokkos::parallel_for (Kokkos::TeamThreadRange (team_member, numPoints), [=] (ordinal_type& pt) { + auto output = Kokkos::subview( outputValues, Kokkos::ALL(), range_type(pt,pt+1), Kokkos::ALL() ); + const auto input = Kokkos::subview( inputPoints, range_type(pt,pt+1), Kokkos::ALL() ); + WorkViewType work(workView.data() + sizePerPoint*team_member.team_rank(), sizePerPoint); + Impl::Basis_HGRAD_HEX_Cn_FEM::Serial::getValues( output, input, work, this->vinv_ ); + }); + break; + default: { + INTREPID2_TEST_FOR_ABORT( true, + ">>> ERROR (Basis_HGRAD_TET_Cn_FEM): getValues not implemented for this operator"); + } + } + } }// namespace Intrepid2 #endif diff --git a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_LINE_C1_FEM.hpp b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_LINE_C1_FEM.hpp index c07fdfd71f04..71ee77e7d55a 100644 --- a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_LINE_C1_FEM.hpp +++ b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_LINE_C1_FEM.hpp @@ -161,6 +161,23 @@ namespace Intrepid2 { operatorType ); } + virtual void + getScratchSpaceSize( ordinal_type& perTeamSpaceSize, + ordinal_type& perThreadSpaceSize, + const PointViewType inputPointsconst, + const EOperator operatorType = OPERATOR_VALUE) const override; + + KOKKOS_INLINE_FUNCTION + virtual void + getValues( + OutputViewType outputValues, + const PointViewType inputPoints, + const EOperator operatorType, + const typename Kokkos::TeamPolicy::member_type& team_member, + const typename DeviceType::execution_space::scratch_memory_space & scratchStorage, + const ordinal_type subcellDim = -1, + const ordinal_type subcellOrdinal = -1) const override; + virtual void getDofCoords( ScalarViewType dofCoords ) const override { diff --git a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_LINE_C1_FEMDef.hpp b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_LINE_C1_FEMDef.hpp index 4572b5b5c899..05291e830a3d 100644 --- a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_LINE_C1_FEMDef.hpp +++ b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_LINE_C1_FEMDef.hpp @@ -177,6 +177,55 @@ namespace Intrepid2 { Kokkos::deep_copy(this->dofCoords_, dofCoords); } -} + template + void + Basis_HGRAD_LINE_C1_FEM::getScratchSpaceSize( + ordinal_type& perTeamSpaceSize, + ordinal_type& perThreadSpaceSize, + const PointViewType inputPoints, + const EOperator operatorType) const { + perTeamSpaceSize = 0; + perThreadSpaceSize = 0; + } + + template + KOKKOS_INLINE_FUNCTION + void + Basis_HGRAD_LINE_C1_FEM::getValues( + OutputViewType outputValues, + const PointViewType inputPoints, + const EOperator operatorType, + const typename Kokkos::TeamPolicy::member_type& team_member, + const typename DT::execution_space::scratch_memory_space & scratchStorage, + const ordinal_type subcellDim, + const ordinal_type subcellOrdinal) const { + + INTREPID2_TEST_FOR_ABORT( !((subcellDim <= 0) && (subcellOrdinal == -1)), + ">>> ERROR: (Intrepid2::Basis_HGRAD_LINE_C1_FEM::getValues), The capability of selecting subsets of basis functions has not been implemented yet."); + + (void) scratchStorage; //avoid unused variable warning + + const int numPoints = inputPoints.extent(0); + + switch(operatorType) { + case OPERATOR_VALUE: + Kokkos::parallel_for (Kokkos::TeamThreadRange (team_member, numPoints), [=] (ordinal_type& pt) { + auto output = Kokkos::subview( outputValues, Kokkos::ALL(), pt, Kokkos::ALL() ); + const auto input = Kokkos::subview( inputPoints, pt, Kokkos::ALL() ); + Impl::Basis_HGRAD_LINE_C1_FEM::Serial::getValues( output, input); + }); + break; + case OPERATOR_GRAD: + Kokkos::parallel_for (Kokkos::TeamThreadRange (team_member, numPoints), [=] (ordinal_type& pt) { + auto output = Kokkos::subview( outputValues, Kokkos::ALL(), pt, Kokkos::ALL() ); + const auto input = Kokkos::subview( inputPoints, pt, Kokkos::ALL() ); + Impl::Basis_HGRAD_LINE_C1_FEM::Serial::getValues( output, input); + }); + break; + default: {} + } + } + +}// namespace Intrepid2 #endif diff --git a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_LINE_C2_FEM.hpp b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_LINE_C2_FEM.hpp index 595cc815e9be..4e141fc5ad41 100644 --- a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_LINE_C2_FEM.hpp +++ b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_LINE_C2_FEM.hpp @@ -161,6 +161,23 @@ namespace Intrepid2 { operatorType); } + virtual void + getScratchSpaceSize( ordinal_type& perTeamSpaceSize, + ordinal_type& perThreadSpaceSize, + const PointViewType inputPointsconst, + const EOperator operatorType = OPERATOR_VALUE) const override; + + KOKKOS_INLINE_FUNCTION + virtual void + getValues( + OutputViewType outputValues, + const PointViewType inputPoints, + const EOperator operatorType, + const typename Kokkos::TeamPolicy::member_type& team_member, + const typename DeviceType::execution_space::scratch_memory_space & scratchStorage, + const ordinal_type subcellDim = -1, + const ordinal_type subcellOrdinal = -1) const override; + virtual void getDofCoords( ScalarViewType dofCoords ) const override { diff --git a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_LINE_C2_FEMDef.hpp b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_LINE_C2_FEMDef.hpp index c08bd3692a27..cb3157028b0e 100644 --- a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_LINE_C2_FEMDef.hpp +++ b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_LINE_C2_FEMDef.hpp @@ -173,6 +173,55 @@ namespace Intrepid2 { Kokkos::deep_copy(this->dofCoords_, dofCoords); } -} + template + void + Basis_HGRAD_LINE_C2_FEM::getScratchSpaceSize( + ordinal_type& perTeamSpaceSize, + ordinal_type& perThreadSpaceSize, + const PointViewType inputPoints, + const EOperator operatorType) const { + perTeamSpaceSize = 0; + perThreadSpaceSize = 0; + } + + template + KOKKOS_INLINE_FUNCTION + void + Basis_HGRAD_LINE_C2_FEM::getValues( + OutputViewType outputValues, + const PointViewType inputPoints, + const EOperator operatorType, + const typename Kokkos::TeamPolicy::member_type& team_member, + const typename DT::execution_space::scratch_memory_space & scratchStorage, + const ordinal_type subcellDim, + const ordinal_type subcellOrdinal) const { + + INTREPID2_TEST_FOR_ABORT( !((subcellDim == -1) && (subcellOrdinal == -1)), + ">>> ERROR: (Intrepid2::Basis_HGRAD_LINE_C2_FEM::getValues), The capability of selecting subsets of basis functions has not been implemented yet."); + + (void) scratchStorage; //avoid unused variable warning + + const int numPoints = inputPoints.extent(0); + + switch(operatorType) { + case OPERATOR_VALUE: + Kokkos::parallel_for (Kokkos::TeamThreadRange (team_member, numPoints), [=] (ordinal_type& pt) { + auto output = Kokkos::subview( outputValues, Kokkos::ALL(), pt, Kokkos::ALL() ); + const auto input = Kokkos::subview( inputPoints, pt, Kokkos::ALL() ); + Impl::Basis_HGRAD_LINE_C2_FEM::Serial::getValues( output, input); + }); + break; + case OPERATOR_GRAD: + Kokkos::parallel_for (Kokkos::TeamThreadRange (team_member, numPoints), [=] (ordinal_type& pt) { + auto output = Kokkos::subview( outputValues, Kokkos::ALL(), pt, Kokkos::ALL() ); + const auto input = Kokkos::subview( inputPoints, pt, Kokkos::ALL() ); + Impl::Basis_HGRAD_LINE_C2_FEM::Serial::getValues( output, input); + }); + break; + default: {} + } + } + +}// namespace Intrepid2 #endif diff --git a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_LINE_Cn_FEM.hpp b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_LINE_Cn_FEM.hpp index c5e0e2308545..ac2bfdbcae0b 100644 --- a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_LINE_Cn_FEM.hpp +++ b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_LINE_Cn_FEM.hpp @@ -192,6 +192,23 @@ namespace Intrepid2 { operatorType); } + virtual void + getScratchSpaceSize( ordinal_type& perTeamSpaceSize, + ordinal_type& perThreadSpaceSize, + const PointViewType inputPointsconst, + const EOperator operatorType = OPERATOR_VALUE) const override; + + KOKKOS_INLINE_FUNCTION + virtual void + getValues( + OutputViewType outputValues, + const PointViewType inputPoints, + const EOperator operatorType, + const typename Kokkos::TeamPolicy::member_type& team_member, + const typename DeviceType::execution_space::scratch_memory_space & scratchStorage, + const ordinal_type subcellDim = -1, + const ordinal_type subcellOrdinal = -1) const override; + virtual void getDofCoords( ScalarViewType dofCoords ) const override { diff --git a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_LINE_Cn_FEMDef.hpp b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_LINE_Cn_FEMDef.hpp index fc116eb32ebe..6140c13821cb 100644 --- a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_LINE_Cn_FEMDef.hpp +++ b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_LINE_Cn_FEMDef.hpp @@ -23,16 +23,16 @@ namespace Intrepid2 { template template + typename InputViewType, + typename WorkViewType, + typename VinvViewType> KOKKOS_INLINE_FUNCTION void Basis_HGRAD_LINE_Cn_FEM::Serial:: getValues( OutputViewType output, - const inputViewType input, - workViewType work, - const vinvViewType vinv, + const InputViewType input, + WorkViewType work, + const VinvViewType vinv, const ordinal_type operatorDn ) { ordinal_type opDn = operatorDn; @@ -42,12 +42,12 @@ namespace Intrepid2 { const ordinal_type order = card - 1; const double alpha = 0.0, beta = 0.0; - typedef typename Kokkos::DynRankView viewType; - auto vcprop = Kokkos::common_view_alloc_prop(work); + typedef typename Kokkos::DynRankView ViewType; + auto vcprop = Kokkos::common_view_alloc_prop(input); switch (opType) { case OPERATOR_VALUE: { - viewType phis(Kokkos::view_wrap(work.data(), vcprop), card, npts); + ViewType phis(Kokkos::view_wrap(work.data(), vcprop), card, npts); Impl::Basis_HGRAD_LINE_Cn_FEM_JACOBI:: Serial::getValues(phis, input, order, alpha, beta); @@ -75,7 +75,7 @@ namespace Intrepid2 { case OPERATOR_Dn: { // dkcard is always 1 for 1D element const ordinal_type dkcard = 1; - viewType phis(Kokkos::view_wrap(work.data(), vcprop), card, npts, dkcard); + ViewType phis(Kokkos::view_wrap(work.data(), vcprop), card, npts, dkcard); Impl::Basis_HGRAD_LINE_Cn_FEM_JACOBI:: Serial::getValues(phis, input, order, alpha, beta, opDn); @@ -326,22 +326,64 @@ namespace Intrepid2 { posDfOrd); } } + + template + void + Basis_HGRAD_LINE_Cn_FEM::getScratchSpaceSize( + ordinal_type& perTeamSpaceSize, + ordinal_type& perThreadSpaceSize, + const PointViewType inputPoints, + const EOperator operatorType) const { + perTeamSpaceSize = 0; + perThreadSpaceSize = this->vinv_.extent(0)*get_dimension_scalar(inputPoints)*sizeof(typename BasisBase::scalarType); + } + + template + KOKKOS_INLINE_FUNCTION + void + Basis_HGRAD_LINE_Cn_FEM::getValues( + OutputViewType outputValues, + const PointViewType inputPoints, + const EOperator operatorType, + const typename Kokkos::TeamPolicy::member_type& team_member, + const typename DT::execution_space::scratch_memory_space & scratchStorage, + const ordinal_type subcellDim, + const ordinal_type subcellOrdinal) const { + + INTREPID2_TEST_FOR_ABORT( !((subcellDim == -1) && (subcellOrdinal == -1)), + ">>> ERROR: (Intrepid2::Basis_HGRAD_LINE_Cn_FEM::getValues), The capability of selecting subsets of basis functions has not been implemented yet."); + + const int numPoints = inputPoints.extent(0); + using ScalarType = typename ScalarTraits::scalar_type; + using WorkViewType = Kokkos::DynRankView< ScalarType,typename DT::execution_space::scratch_memory_space,Kokkos::MemoryTraits >; + ordinal_type sizePerPoint = this->vinv_.extent(0)*get_dimension_scalar(inputPoints); + WorkViewType workView(scratchStorage, sizePerPoint*team_member.team_size()); + using range_type = Kokkos::pair; + + switch(operatorType) { + case OPERATOR_VALUE: + Kokkos::parallel_for (Kokkos::TeamThreadRange (team_member, numPoints), [=] (ordinal_type& pt) { + auto output = Kokkos::subview( outputValues, Kokkos::ALL(), range_type (pt,pt+1), Kokkos::ALL() ); + const auto input = Kokkos::subview( inputPoints, range_type(pt, pt+1), Kokkos::ALL() ); + WorkViewType work(workView.data() + sizePerPoint*team_member.team_rank(), sizePerPoint); + Impl::Basis_HGRAD_LINE_Cn_FEM::Serial::getValues( output, input, work, this->vinv_ ); + }); + break; + case OPERATOR_GRAD: + Kokkos::parallel_for (Kokkos::TeamThreadRange (team_member, numPoints), [=] (ordinal_type& pt) { + auto output = Kokkos::subview( outputValues, Kokkos::ALL(), range_type(pt,pt+1), Kokkos::ALL() ); + const auto input = Kokkos::subview( inputPoints, range_type(pt,pt+1), Kokkos::ALL() ); + WorkViewType work(workView.data() + sizePerPoint*team_member.team_rank(), sizePerPoint); + Impl::Basis_HGRAD_LINE_Cn_FEM::Serial::getValues( output, input, work, this->vinv_ ); + }); + break; + default: { + INTREPID2_TEST_FOR_ABORT( true, + ">>> ERROR (Basis_HGRAD_LINE_Cn_FEM): getValues not implemented for this operator"); + } + } + } }// namespace Intrepid2 #endif - - - - - - - - - - - - - - - diff --git a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_PYR_C1_FEM.hpp b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_PYR_C1_FEM.hpp index 36463fc8baec..7f00c2a90a2d 100644 --- a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_PYR_C1_FEM.hpp +++ b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_PYR_C1_FEM.hpp @@ -163,6 +163,23 @@ namespace Intrepid2 { operatorType ); } + virtual void + getScratchSpaceSize( ordinal_type& perTeamSpaceSize, + ordinal_type& perThreadSpaceSize, + const PointViewType inputPointsconst, + const EOperator operatorType = OPERATOR_VALUE) const override; + + KOKKOS_INLINE_FUNCTION + virtual void + getValues( + OutputViewType outputValues, + const PointViewType inputPoints, + const EOperator operatorType, + const typename Kokkos::TeamPolicy::member_type& team_member, + const typename DeviceType::execution_space::scratch_memory_space & scratchStorage, + const ordinal_type subcellDim = -1, + const ordinal_type subcellOrdinal = -1) const override; + virtual void getDofCoords( ScalarViewType dofCoords ) const override { diff --git a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_PYR_C1_FEMDef.hpp b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_PYR_C1_FEMDef.hpp index e25212499fbd..078ad0e97178 100644 --- a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_PYR_C1_FEMDef.hpp +++ b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_PYR_C1_FEMDef.hpp @@ -256,6 +256,54 @@ namespace Intrepid2 { Kokkos::deep_copy(this->dofCoords_, dofCoords); } -} + template + void + Basis_HGRAD_PYR_C1_FEM::getScratchSpaceSize( + ordinal_type& perTeamSpaceSize, + ordinal_type& perThreadSpaceSize, + const PointViewType inputPoints, + const EOperator operatorType) const { + perTeamSpaceSize = 0; + perThreadSpaceSize = 0; + } + template + KOKKOS_INLINE_FUNCTION + void + Basis_HGRAD_PYR_C1_FEM::getValues( + OutputViewType outputValues, + const PointViewType inputPoints, + const EOperator operatorType, + const typename Kokkos::TeamPolicy::member_type& team_member, + const typename DT::execution_space::scratch_memory_space & scratchStorage, + const ordinal_type subcellDim, + const ordinal_type subcellOrdinal) const { + + INTREPID2_TEST_FOR_ABORT( !((subcellDim <= 0) && (subcellOrdinal == -1)), + ">>> ERROR: (Intrepid2::Basis_HGRAD_PYR_C1_FEM::getValues), The capability of selecting subsets of basis functions has not been implemented yet."); + + (void) scratchStorage; //avoid unused variable warning + + const int numPoints = inputPoints.extent(0); + + switch(operatorType) { + case OPERATOR_VALUE: + Kokkos::parallel_for (Kokkos::TeamThreadRange (team_member, numPoints), [=] (ordinal_type& pt) { + auto output = Kokkos::subview( outputValues, Kokkos::ALL(), pt, Kokkos::ALL() ); + const auto input = Kokkos::subview( inputPoints, pt, Kokkos::ALL() ); + Impl::Basis_HGRAD_PYR_C1_FEM::Serial::getValues( output, input); + }); + break; + case OPERATOR_GRAD: + Kokkos::parallel_for (Kokkos::TeamThreadRange (team_member, numPoints), [=] (ordinal_type& pt) { + auto output = Kokkos::subview( outputValues, Kokkos::ALL(), pt, Kokkos::ALL() ); + const auto input = Kokkos::subview( inputPoints, pt, Kokkos::ALL() ); + Impl::Basis_HGRAD_PYR_C1_FEM::Serial::getValues( output, input); + }); + break; + default: {} + } + } + +}// namespace Intrepid2 #endif diff --git a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_PYR_I2_FEM.hpp b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_PYR_I2_FEM.hpp index aad5bae97d00..81a09cc56c91 100644 --- a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_PYR_I2_FEM.hpp +++ b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_PYR_I2_FEM.hpp @@ -180,6 +180,23 @@ namespace Intrepid2 { operatorType ); } + virtual void + getScratchSpaceSize( ordinal_type& perTeamSpaceSize, + ordinal_type& perThreadSpaceSize, + const PointViewType inputPointsconst, + const EOperator operatorType = OPERATOR_VALUE) const override; + + KOKKOS_INLINE_FUNCTION + virtual void + getValues( + OutputViewType outputValues, + const PointViewType inputPoints, + const EOperator operatorType, + const typename Kokkos::TeamPolicy::member_type& team_member, + const typename DeviceType::execution_space::scratch_memory_space & scratchStorage, + const ordinal_type subcellDim = -1, + const ordinal_type subcellOrdinal = -1) const override; + virtual void getDofCoords( ScalarViewType dofCoords ) const override { diff --git a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_PYR_I2_FEMDef.hpp b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_PYR_I2_FEMDef.hpp index 3247c5aaa0b7..a6ce124d1c2b 100644 --- a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_PYR_I2_FEMDef.hpp +++ b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_PYR_I2_FEMDef.hpp @@ -371,6 +371,54 @@ namespace Intrepid2 { Kokkos::deep_copy(this->dofCoords_, dofCoords); } -} + template + void + Basis_HGRAD_PYR_I2_FEM::getScratchSpaceSize( + ordinal_type& perTeamSpaceSize, + ordinal_type& perThreadSpaceSize, + const PointViewType inputPoints, + const EOperator operatorType) const { + perTeamSpaceSize = 0; + perThreadSpaceSize = 0; + } + template + KOKKOS_INLINE_FUNCTION + void + Basis_HGRAD_PYR_I2_FEM::getValues( + OutputViewType outputValues, + const PointViewType inputPoints, + const EOperator operatorType, + const typename Kokkos::TeamPolicy::member_type& team_member, + const typename DT::execution_space::scratch_memory_space & scratchStorage, + const ordinal_type subcellDim, + const ordinal_type subcellOrdinal) const { + + INTREPID2_TEST_FOR_ABORT( !((subcellDim <= 0) && (subcellOrdinal == -1)), + ">>> ERROR: (Intrepid2::Basis_HGRAD_PYR_I2_FEM::getValues), The capability of selecting subsets of basis functions has not been implemented yet."); + + (void) scratchStorage; //avoid unused variable warning + + const int numPoints = inputPoints.extent(0); + + switch(operatorType) { + case OPERATOR_VALUE: + Kokkos::parallel_for (Kokkos::TeamThreadRange (team_member, numPoints), [=] (ordinal_type& pt) { + auto output = Kokkos::subview( outputValues, Kokkos::ALL(), pt, Kokkos::ALL() ); + const auto input = Kokkos::subview( inputPoints, pt, Kokkos::ALL() ); + Impl::Basis_HGRAD_PYR_I2_FEM::Serial::getValues( output, input); + }); + break; + case OPERATOR_GRAD: + Kokkos::parallel_for (Kokkos::TeamThreadRange (team_member, numPoints), [=] (ordinal_type& pt) { + auto output = Kokkos::subview( outputValues, Kokkos::ALL(), pt, Kokkos::ALL() ); + const auto input = Kokkos::subview( inputPoints, pt, Kokkos::ALL() ); + Impl::Basis_HGRAD_PYR_I2_FEM::Serial::getValues( output, input); + }); + break; + default: {} + } + } + +}// namespace Intrepid2 #endif diff --git a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_QUAD_C1_FEM.hpp b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_QUAD_C1_FEM.hpp index 17af8c1c8685..e6b9d7b10c44 100644 --- a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_QUAD_C1_FEM.hpp +++ b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_QUAD_C1_FEM.hpp @@ -167,6 +167,23 @@ namespace Intrepid2 { operatorType); } + virtual void + getScratchSpaceSize( ordinal_type& perTeamSpaceSize, + ordinal_type& perThreadSpaceSize, + const PointViewType inputPointsconst, + const EOperator operatorType = OPERATOR_VALUE) const override; + + KOKKOS_INLINE_FUNCTION + virtual void + getValues( + OutputViewType outputValues, + const PointViewType inputPoints, + const EOperator operatorType, + const typename Kokkos::TeamPolicy::member_type& team_member, + const typename DeviceType::execution_space::scratch_memory_space & scratchStorage, + const ordinal_type subcellDim = -1, + const ordinal_type subcellOrdinal = -1) const override; + virtual void getDofCoords( ScalarViewType dofCoords ) const override { diff --git a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_QUAD_C1_FEMDef.hpp b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_QUAD_C1_FEMDef.hpp index 39504493f063..246a92ac44d5 100644 --- a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_QUAD_C1_FEMDef.hpp +++ b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_QUAD_C1_FEMDef.hpp @@ -245,5 +245,63 @@ namespace Intrepid2 { Kokkos::deep_copy(this->dofCoords_, dofCoords); } + template + void + Basis_HGRAD_QUAD_C1_FEM::getScratchSpaceSize( + ordinal_type& perTeamSpaceSize, + ordinal_type& perThreadSpaceSize, + const PointViewType inputPoints, + const EOperator operatorType) const { + perTeamSpaceSize = 0; + perThreadSpaceSize = 0; + } + + template + KOKKOS_INLINE_FUNCTION + void + Basis_HGRAD_QUAD_C1_FEM::getValues( + OutputViewType outputValues, + const PointViewType inputPoints, + const EOperator operatorType, + const typename Kokkos::TeamPolicy::member_type& team_member, + const typename DT::execution_space::scratch_memory_space & scratchStorage, + const ordinal_type subcellDim, + const ordinal_type subcellOrdinal) const { + + INTREPID2_TEST_FOR_ABORT( !((subcellDim <= 0) && (subcellOrdinal == -1)), + ">>> ERROR: (Intrepid2::Basis_HGRAD_QUAD_C1_FEM::getValues), The capability of selecting subsets of basis functions has not been implemented yet."); + + (void) scratchStorage; //avoid unused variable warning + + const int numPoints = inputPoints.extent(0); + + switch(operatorType) { + case OPERATOR_VALUE: + Kokkos::parallel_for (Kokkos::TeamThreadRange (team_member, numPoints), [=] (ordinal_type& pt) { + auto output = Kokkos::subview( outputValues, Kokkos::ALL(), pt, Kokkos::ALL() ); + const auto input = Kokkos::subview( inputPoints, pt, Kokkos::ALL() ); + Impl::Basis_HGRAD_QUAD_C1_FEM::Serial::getValues( output, input); + }); + break; + case OPERATOR_GRAD: + Kokkos::parallel_for (Kokkos::TeamThreadRange (team_member, numPoints), [=] (ordinal_type& pt) { + auto output = Kokkos::subview( outputValues, Kokkos::ALL(), pt, Kokkos::ALL() ); + const auto input = Kokkos::subview( inputPoints, pt, Kokkos::ALL() ); + Impl::Basis_HGRAD_QUAD_C1_FEM::Serial::getValues( output, input); + }); + break; + case OPERATOR_CURL: + Kokkos::parallel_for (Kokkos::TeamThreadRange (team_member, numPoints), [=] (ordinal_type& pt) { + auto output = Kokkos::subview( outputValues, Kokkos::ALL(), pt, Kokkos::ALL() ); + const auto input = Kokkos::subview( inputPoints, pt, Kokkos::ALL() ); + Impl::Basis_HGRAD_QUAD_C1_FEM::Serial::getValues( output, input); + }); + break; + default: { + INTREPID2_TEST_FOR_ABORT( true, ">>> ERROR: (Intrepid2::Basis_HGRAD_QUAD_C1_FEM::getValues), Operator Type not supported."); + } + } + } + }// namespace Intrepid2 #endif diff --git a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_QUAD_C2_FEM.hpp b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_QUAD_C2_FEM.hpp index d82127eb1ead..038214825966 100644 --- a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_QUAD_C2_FEM.hpp +++ b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_QUAD_C2_FEM.hpp @@ -194,6 +194,23 @@ namespace Intrepid2 { operatorType); } + virtual void + getScratchSpaceSize( ordinal_type& perTeamSpaceSize, + ordinal_type& perThreadSpaceSize, + const PointViewType inputPointsconst, + const EOperator operatorType = OPERATOR_VALUE) const override; + + KOKKOS_INLINE_FUNCTION + virtual void + getValues( + OutputViewType outputValues, + const PointViewType inputPoints, + const EOperator operatorType, + const typename Kokkos::TeamPolicy::member_type& team_member, + const typename DeviceType::execution_space::scratch_memory_space & scratchStorage, + const ordinal_type subcellDim = -1, + const ordinal_type subcellOrdinal = -1) const override; + virtual void getDofCoords( ScalarViewType dofCoords ) const override { diff --git a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_QUAD_C2_FEMDef.hpp b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_QUAD_C2_FEMDef.hpp index 4ec411a0ffc1..36ae4378091c 100644 --- a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_QUAD_C2_FEMDef.hpp +++ b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_QUAD_C2_FEMDef.hpp @@ -557,5 +557,66 @@ namespace Intrepid2 { Kokkos::deep_copy(this->dofCoords_, dofCoords); } + template + void + Basis_HGRAD_QUAD_DEG2_FEM::getScratchSpaceSize( + ordinal_type& perTeamSpaceSize, + ordinal_type& perThreadSpaceSize, + const PointViewType inputPoints, + const EOperator operatorType) const { + perTeamSpaceSize = 0; + perThreadSpaceSize = 0; + } + + template + KOKKOS_INLINE_FUNCTION + void + Basis_HGRAD_QUAD_DEG2_FEM::getValues( + OutputViewType outputValues, + const PointViewType inputPoints, + const EOperator operatorType, + const typename Kokkos::TeamPolicy::member_type& team_member, + const typename DT::execution_space::scratch_memory_space & scratchStorage, + const ordinal_type subcellDim, + const ordinal_type subcellOrdinal) const { + + INTREPID2_TEST_FOR_ABORT( !((subcellDim <= 0) && (subcellOrdinal == -1)), + ">>> ERROR: (Intrepid2::Basis_HGRAD_QUAD_DEG2_FEM::getValues), The capability of selecting subsets of basis functions has not been implemented yet."); + + (void) scratchStorage; //avoid unused variable warning + + const int numPoints = inputPoints.extent(0); + + switch(operatorType) { + case OPERATOR_VALUE: + Kokkos::parallel_for (Kokkos::TeamThreadRange (team_member, numPoints), [=] (ordinal_type& pt) { + auto output = Kokkos::subview( outputValues, Kokkos::ALL(), pt, Kokkos::ALL() ); + const auto input = Kokkos::subview( inputPoints, pt, Kokkos::ALL() ); + using SerialValue = typename Impl::Basis_HGRAD_QUAD_DEG2_FEM::template Serial; + SerialValue::getValues( output, input); + }); + break; + case OPERATOR_GRAD: + Kokkos::parallel_for (Kokkos::TeamThreadRange (team_member, numPoints), [=] (ordinal_type& pt) { + auto output = Kokkos::subview( outputValues, Kokkos::ALL(), pt, Kokkos::ALL() ); + const auto input = Kokkos::subview( inputPoints, pt, Kokkos::ALL() ); + using SerialGrad = typename Impl::Basis_HGRAD_QUAD_DEG2_FEM::template Serial; + SerialGrad::getValues( output, input); + }); + break; + case OPERATOR_CURL: + Kokkos::parallel_for (Kokkos::TeamThreadRange (team_member, numPoints), [=] (ordinal_type& pt) { + auto output = Kokkos::subview( outputValues, Kokkos::ALL(), pt, Kokkos::ALL() ); + const auto input = Kokkos::subview( inputPoints, pt, Kokkos::ALL() ); + using SerialCurl = typename Impl::Basis_HGRAD_QUAD_DEG2_FEM::template Serial; + SerialCurl::getValues( output, input); + }); + break; + default: { + INTREPID2_TEST_FOR_ABORT( true, ">>> ERROR: (Intrepid2::Basis_HGRAD_QUAD_DEG2_FEM::getValues), Operator Type not supported."); + } + } + } + }// namespace Intrepid2 #endif diff --git a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_QUAD_Cn_FEM.hpp b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_QUAD_Cn_FEM.hpp index d07b46cafb28..00a206c12ec8 100644 --- a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_QUAD_Cn_FEM.hpp +++ b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_QUAD_Cn_FEM.hpp @@ -181,6 +181,23 @@ namespace Intrepid2 { operatorType); } + virtual void + getScratchSpaceSize( ordinal_type& perTeamSpaceSize, + ordinal_type& perThreadSpaceSize, + const PointViewType inputPointsconst, + const EOperator operatorType = OPERATOR_VALUE) const override; + + KOKKOS_INLINE_FUNCTION + virtual void + getValues( + OutputViewType outputValues, + const PointViewType inputPoints, + const EOperator operatorType, + const typename Kokkos::TeamPolicy::member_type& team_member, + const typename DeviceType::execution_space::scratch_memory_space & scratchStorage, + const ordinal_type subcellDim = -1, + const ordinal_type subcellOrdinal = -1) const override; + virtual void getDofCoords( ScalarViewType dofCoords ) const override { diff --git a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_QUAD_Cn_FEMDef.hpp b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_QUAD_Cn_FEMDef.hpp index 582b465a6c57..9e232352285e 100644 --- a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_QUAD_Cn_FEMDef.hpp +++ b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_QUAD_Cn_FEMDef.hpp @@ -21,18 +21,18 @@ namespace Intrepid2 { // ------------------------------------------------------------------------------------- namespace Impl { - template + template template + typename InputViewType, + typename WorkViewType, + typename VinvViewType> KOKKOS_INLINE_FUNCTION void - Basis_HGRAD_QUAD_Cn_FEM::Serial:: + Basis_HGRAD_QUAD_Cn_FEM::Serial:: getValues( OutputViewType output, - const inputViewType input, - workViewType work, - const vinvViewType vinv, + const InputViewType input, + WorkViewType work, + const VinvViewType vinv, const ordinal_type operatorDn ) { ordinal_type opDn = operatorDn; @@ -43,19 +43,19 @@ namespace Intrepid2 { const auto input_x = Kokkos::subview(input, Kokkos::ALL(), range_type(0,1)); const auto input_y = Kokkos::subview(input, Kokkos::ALL(), range_type(1,2)); - const int dim_s = get_dimension_scalar(work); + const int dim_s = get_dimension_scalar(input); auto ptr0 = work.data(); auto ptr1 = work.data()+cardLine*npts*dim_s; auto ptr2 = work.data()+2*cardLine*npts*dim_s; - typedef typename Kokkos::DynRankView viewType; - auto vcprop = Kokkos::common_view_alloc_prop(work); + typedef typename Kokkos::DynRankView ViewType; + auto vcprop = Kokkos::common_view_alloc_prop(input); - switch (opType) { + switch (OpType) { case OPERATOR_VALUE: { - viewType work_line(Kokkos::view_wrap(ptr0, vcprop), cardLine, npts); - viewType output_x(Kokkos::view_wrap(ptr1, vcprop), cardLine, npts); - viewType output_y(Kokkos::view_wrap(ptr2, vcprop), cardLine, npts); + ViewType work_line(Kokkos::view_wrap(ptr0, vcprop), cardLine, npts); + ViewType output_x(Kokkos::view_wrap(ptr1, vcprop), cardLine, npts); + ViewType output_y(Kokkos::view_wrap(ptr2, vcprop), cardLine, npts); Impl::Basis_HGRAD_LINE_Cn_FEM::Serial:: getValues(output_x, input_x, work_line, vinv); @@ -73,29 +73,29 @@ namespace Intrepid2 { } case OPERATOR_CURL: { for (auto l=0;l<2;++l) { - viewType work_line(Kokkos::view_wrap(ptr0, vcprop), cardLine, npts); + ViewType work_line(Kokkos::view_wrap(ptr0, vcprop), cardLine, npts); - viewType output_x, output_y; + ViewType output_x, output_y; - typename workViewType::value_type s = 0.0; + typename WorkViewType::value_type s = 0.0; if (l) { // l = 1 - output_x = viewType(Kokkos::view_wrap(ptr1, vcprop), cardLine, npts, 1); + output_x = ViewType(Kokkos::view_wrap(ptr1, vcprop), cardLine, npts, 1); Impl::Basis_HGRAD_LINE_Cn_FEM::Serial:: getValues(output_x, input_x, work_line, vinv, 1); - output_y = viewType(Kokkos::view_wrap(ptr2, vcprop), cardLine, npts); + output_y = ViewType(Kokkos::view_wrap(ptr2, vcprop), cardLine, npts); Impl::Basis_HGRAD_LINE_Cn_FEM::Serial:: getValues(output_y, input_y, work_line, vinv); s = -1.0; } else { // l = 0 - output_x = viewType(Kokkos::view_wrap(ptr1, vcprop), cardLine, npts); + output_x = ViewType(Kokkos::view_wrap(ptr1, vcprop), cardLine, npts); Impl::Basis_HGRAD_LINE_Cn_FEM::Serial:: getValues(output_x, input_x, work_line, vinv); - output_y = viewType(Kokkos::view_wrap(ptr2, vcprop), cardLine, npts, 1); + output_y = ViewType(Kokkos::view_wrap(ptr2, vcprop), cardLine, npts, 1); Impl::Basis_HGRAD_LINE_Cn_FEM::Serial:: getValues(output_y, input_y, work_line, vinv, 1); @@ -122,33 +122,33 @@ namespace Intrepid2 { case OPERATOR_D8: case OPERATOR_D9: case OPERATOR_D10: - opDn = getOperatorOrder(opType); + opDn = getOperatorOrder(OpType); case OPERATOR_Dn: { const auto dkcard = opDn + 1; for (auto l=0;l:: getValues(output_x, input_x, work_line, vinv, mult_x); } else { - output_x = viewType(Kokkos::view_wrap(ptr1, vcprop), cardLine, npts); + output_x = ViewType(Kokkos::view_wrap(ptr1, vcprop), cardLine, npts); Impl::Basis_HGRAD_LINE_Cn_FEM::Serial:: getValues(output_x, input_x, work_line, vinv); } if (mult_y) { - output_y = viewType(Kokkos::view_wrap(ptr2, vcprop), cardLine, npts, 1); + output_y = ViewType(Kokkos::view_wrap(ptr2, vcprop), cardLine, npts, 1); Impl::Basis_HGRAD_LINE_Cn_FEM::Serial:: getValues(output_y, input_y, work_line, vinv, mult_y); } else { - output_y = viewType(Kokkos::view_wrap(ptr2, vcprop), cardLine, npts); + output_y = ViewType(Kokkos::view_wrap(ptr2, vcprop), cardLine, npts); Impl::Basis_HGRAD_LINE_Cn_FEM::Serial:: getValues(output_y, input_y, work_line, vinv); } @@ -357,7 +357,72 @@ namespace Intrepid2 { this->dofCoords_ = Kokkos::create_mirror_view(typename DT::memory_space(), dofCoordsHost); Kokkos::deep_copy(this->dofCoords_, dofCoordsHost); } - -}// namespace Intrepid2 + + template + void + Basis_HGRAD_QUAD_Cn_FEM::getScratchSpaceSize( + ordinal_type& perTeamSpaceSize, + ordinal_type& perThreadSpaceSize, + const PointViewType inputPoints, + const EOperator operatorType) const { + perTeamSpaceSize = 0; + perThreadSpaceSize = 3*this->vinv_.extent(0)*get_dimension_scalar(inputPoints)*sizeof(typename BasisBase::scalarType); + } + + template + KOKKOS_INLINE_FUNCTION + void + Basis_HGRAD_QUAD_Cn_FEM::getValues( + OutputViewType outputValues, + const PointViewType inputPoints, + const EOperator operatorType, + const typename Kokkos::TeamPolicy::member_type& team_member, + const typename DT::execution_space::scratch_memory_space & scratchStorage, + const ordinal_type subcellDim, + const ordinal_type subcellOrdinal) const { + + INTREPID2_TEST_FOR_ABORT( !((subcellDim == -1) && (subcellOrdinal == -1)), + ">>> ERROR: (Intrepid2::Basis_HGRAD_QUAD_Cn_FEM::getValues), The capability of selecting subsets of basis functions has not been implemented yet."); + + const int numPoints = inputPoints.extent(0); + using ScalarType = typename ScalarTraits::scalar_type; + using WorkViewType = Kokkos::DynRankView< ScalarType,typename DT::execution_space::scratch_memory_space,Kokkos::MemoryTraits >; + ordinal_type sizePerPoint = 3*this->vinv_.extent(0)*get_dimension_scalar(inputPoints); + WorkViewType workView(scratchStorage, sizePerPoint*team_member.team_size()); + using range_type = Kokkos::pair; + + switch(operatorType) { + case OPERATOR_VALUE: + Kokkos::parallel_for (Kokkos::TeamThreadRange (team_member, numPoints), [=] (ordinal_type& pt) { + auto output = Kokkos::subview( outputValues, Kokkos::ALL(), range_type (pt,pt+1), Kokkos::ALL() ); + const auto input = Kokkos::subview( inputPoints, range_type(pt, pt+1), Kokkos::ALL() ); + WorkViewType work(workView.data() + sizePerPoint*team_member.team_rank(), sizePerPoint); + Impl::Basis_HGRAD_QUAD_Cn_FEM::Serial::getValues( output, input, work, this->vinv_ ); + }); + break; + case OPERATOR_GRAD: + Kokkos::parallel_for (Kokkos::TeamThreadRange (team_member, numPoints), [=] (ordinal_type& pt) { + auto output = Kokkos::subview( outputValues, Kokkos::ALL(), range_type(pt,pt+1), Kokkos::ALL() ); + const auto input = Kokkos::subview( inputPoints, range_type(pt,pt+1), Kokkos::ALL() ); + WorkViewType work(workView.data() + sizePerPoint*team_member.team_rank(), sizePerPoint); + Impl::Basis_HGRAD_QUAD_Cn_FEM::Serial::getValues( output, input, work, this->vinv_ ); + }); + break; + case OPERATOR_CURL: + Kokkos::parallel_for (Kokkos::TeamThreadRange (team_member, numPoints), [=] (ordinal_type& pt) { + auto output = Kokkos::subview( outputValues, Kokkos::ALL(), range_type(pt,pt+1), Kokkos::ALL() ); + const auto input = Kokkos::subview( inputPoints, range_type(pt,pt+1), Kokkos::ALL() ); + WorkViewType work(workView.data() + sizePerPoint*team_member.team_rank(), sizePerPoint); + Impl::Basis_HGRAD_QUAD_Cn_FEM::Serial::getValues( output, input, work, this->vinv_ ); + }); + break; + default: { + INTREPID2_TEST_FOR_ABORT( true, + ">>> ERROR (Basis_HGRAD_QUAD_Cn_FEM): getValues not implemented for this operator"); + } + } + } + +} // namespace Intrepid2 #endif diff --git a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_TET_C1_FEM.hpp b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_TET_C1_FEM.hpp index a2bd5cce665e..d8ed43bad7c7 100644 --- a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_TET_C1_FEM.hpp +++ b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_TET_C1_FEM.hpp @@ -164,6 +164,23 @@ namespace Intrepid2 { operatorType); } + virtual void + getScratchSpaceSize( ordinal_type& perTeamSpaceSize, + ordinal_type& perThreadSpaceSize, + const PointViewType inputPointsconst, + const EOperator operatorType = OPERATOR_VALUE) const override; + + KOKKOS_INLINE_FUNCTION + virtual void + getValues( + OutputViewType outputValues, + const PointViewType inputPoints, + const EOperator operatorType, + const typename Kokkos::TeamPolicy::member_type& team_member, + const typename DeviceType::execution_space::scratch_memory_space & scratchStorage, + const ordinal_type subcellDim = -1, + const ordinal_type subcellOrdinal = -1) const override; + virtual void getDofCoords( ScalarViewType dofCoords ) const override { diff --git a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_TET_C1_FEMDef.hpp b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_TET_C1_FEMDef.hpp index 65d632b1b578..c8e0cc996c65 100644 --- a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_TET_C1_FEMDef.hpp +++ b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_TET_C1_FEMDef.hpp @@ -202,5 +202,54 @@ namespace Intrepid2 { Kokkos::deep_copy(this->dofCoords_, dofCoords); } + template + void + Basis_HGRAD_TET_C1_FEM::getScratchSpaceSize( + ordinal_type& perTeamSpaceSize, + ordinal_type& perThreadSpaceSize, + const PointViewType inputPoints, + const EOperator operatorType) const { + perTeamSpaceSize = 0; + perThreadSpaceSize = 0; + } + + template + KOKKOS_INLINE_FUNCTION + void + Basis_HGRAD_TET_C1_FEM::getValues( + OutputViewType outputValues, + const PointViewType inputPoints, + const EOperator operatorType, + const typename Kokkos::TeamPolicy::member_type& team_member, + const typename DT::execution_space::scratch_memory_space & scratchStorage, + const ordinal_type subcellDim, + const ordinal_type subcellOrdinal) const { + + INTREPID2_TEST_FOR_ABORT( !((subcellDim <= 0) && (subcellOrdinal == -1)), + ">>> ERROR: (Intrepid2::Basis_HGRAD_TET_C1_FEM::getValues), The capability of selecting subsets of basis functions has not been implemented yet."); + + (void) scratchStorage; //avoid unused variable warning + + const int numPoints = inputPoints.extent(0); + + switch(operatorType) { + case OPERATOR_VALUE: + Kokkos::parallel_for (Kokkos::TeamThreadRange (team_member, numPoints), [=] (ordinal_type& pt) { + auto output = Kokkos::subview( outputValues, Kokkos::ALL(), pt, Kokkos::ALL() ); + const auto input = Kokkos::subview( inputPoints, pt, Kokkos::ALL() ); + Impl::Basis_HGRAD_TET_C1_FEM::Serial::getValues( output, input); + }); + break; + case OPERATOR_GRAD: + Kokkos::parallel_for (Kokkos::TeamThreadRange (team_member, numPoints), [=] (ordinal_type& pt) { + auto output = Kokkos::subview( outputValues, Kokkos::ALL(), pt, Kokkos::ALL() ); + const auto input = Kokkos::subview( inputPoints, pt, Kokkos::ALL() ); + Impl::Basis_HGRAD_TET_C1_FEM::Serial::getValues( output, input); + }); + break; + default: {} + } + } + }// namespace Intrepid2 #endif diff --git a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_TET_C2_FEM.hpp b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_TET_C2_FEM.hpp index 3b544a29b8b9..703eef86b224 100644 --- a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_TET_C2_FEM.hpp +++ b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_TET_C2_FEM.hpp @@ -183,6 +183,23 @@ namespace Intrepid2 { operatorType); } + virtual void + getScratchSpaceSize( ordinal_type& perTeamSpaceSize, + ordinal_type& perThreadSpaceSize, + const PointViewType inputPointsconst, + const EOperator operatorType = OPERATOR_VALUE) const override; + + KOKKOS_INLINE_FUNCTION + virtual void + getValues( + OutputViewType outputValues, + const PointViewType inputPoints, + const EOperator operatorType, + const typename Kokkos::TeamPolicy::member_type& team_member, + const typename DeviceType::execution_space::scratch_memory_space & scratchStorage, + const ordinal_type subcellDim = -1, + const ordinal_type subcellOrdinal = -1) const override; + virtual void getDofCoords( ScalarViewType dofCoords ) const override { diff --git a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_TET_C2_FEMDef.hpp b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_TET_C2_FEMDef.hpp index 36aa3d7df7b8..7f4f39634cd0 100644 --- a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_TET_C2_FEMDef.hpp +++ b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_TET_C2_FEMDef.hpp @@ -323,5 +323,54 @@ namespace Intrepid2 { Kokkos::deep_copy(this->dofCoords_, dofCoords); } + template + void + Basis_HGRAD_TET_C2_FEM::getScratchSpaceSize( + ordinal_type& perTeamSpaceSize, + ordinal_type& perThreadSpaceSize, + const PointViewType inputPoints, + const EOperator operatorType) const { + perTeamSpaceSize = 0; + perThreadSpaceSize = 0; + } + + template + KOKKOS_INLINE_FUNCTION + void + Basis_HGRAD_TET_C2_FEM::getValues( + OutputViewType outputValues, + const PointViewType inputPoints, + const EOperator operatorType, + const typename Kokkos::TeamPolicy::member_type& team_member, + const typename DT::execution_space::scratch_memory_space & scratchStorage, + const ordinal_type subcellDim, + const ordinal_type subcellOrdinal) const { + + INTREPID2_TEST_FOR_ABORT( !((subcellDim <= 0) && (subcellOrdinal == -1)), + ">>> ERROR: (Intrepid2::Basis_HGRAD_TET_C2_FEM::getValues), The capability of selecting subsets of basis functions has not been implemented yet."); + + (void) scratchStorage; //avoid unused variable warning + + const int numPoints = inputPoints.extent(0); + + switch(operatorType) { + case OPERATOR_VALUE: + Kokkos::parallel_for (Kokkos::TeamThreadRange (team_member, numPoints), [=] (ordinal_type& pt) { + auto output = Kokkos::subview( outputValues, Kokkos::ALL(), pt, Kokkos::ALL() ); + const auto input = Kokkos::subview( inputPoints, pt, Kokkos::ALL() ); + Impl::Basis_HGRAD_TET_C2_FEM::Serial::getValues( output, input); + }); + break; + case OPERATOR_GRAD: + Kokkos::parallel_for (Kokkos::TeamThreadRange (team_member, numPoints), [=] (ordinal_type& pt) { + auto output = Kokkos::subview( outputValues, Kokkos::ALL(), pt, Kokkos::ALL() ); + const auto input = Kokkos::subview( inputPoints, pt, Kokkos::ALL() ); + Impl::Basis_HGRAD_TET_C2_FEM::Serial::getValues( output, input); + }); + break; + default: {} + } + } + }// namespace Intrepid2 #endif diff --git a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_TET_COMP12_FEM.hpp b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_TET_COMP12_FEM.hpp index 2bd2814a2d6e..6cb9802be376 100644 --- a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_TET_COMP12_FEM.hpp +++ b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_TET_COMP12_FEM.hpp @@ -203,12 +203,23 @@ namespace Intrepid2 { operatorType); } - /** \brief Returns spatial locations (coordinates) of degrees of freedom on a - reference Tetrahedron. + virtual void + getScratchSpaceSize( ordinal_type& perTeamSpaceSize, + ordinal_type& perThreadSpaceSize, + const PointViewType inputPointsconst, + const EOperator operatorType = OPERATOR_VALUE) const override; + + KOKKOS_INLINE_FUNCTION + virtual void + getValues( + OutputViewType outputValues, + const PointViewType inputPoints, + const EOperator operatorType, + const typename Kokkos::TeamPolicy::member_type& team_member, + const typename DeviceType::execution_space::scratch_memory_space & scratchStorage, + const ordinal_type subcellDim = -1, + const ordinal_type subcellOrdinal = -1) const override; - \param DofCoords [out] - array with the coordinates of degrees of freedom, - dimensioned (F,D) - */ virtual void getDofCoords( ScalarViewType dofCoords ) const override { diff --git a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_TET_COMP12_FEMDef.hpp b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_TET_COMP12_FEMDef.hpp index ca7c10d67005..09888eddc924 100644 --- a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_TET_COMP12_FEMDef.hpp +++ b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_TET_COMP12_FEMDef.hpp @@ -408,6 +408,55 @@ namespace Intrepid2 { this->dofCoords_ = Kokkos::create_mirror_view(typename DT::memory_space(), dofCoords); Kokkos::deep_copy(this->dofCoords_, dofCoords); } -} + template + void + Basis_HGRAD_TET_COMP12_FEM::getScratchSpaceSize( + ordinal_type& perTeamSpaceSize, + ordinal_type& perThreadSpaceSize, + const PointViewType inputPoints, + const EOperator operatorType) const { + perTeamSpaceSize = 0; + perThreadSpaceSize = 0; + } + + template + KOKKOS_INLINE_FUNCTION + void + Basis_HGRAD_TET_COMP12_FEM::getValues( + OutputViewType outputValues, + const PointViewType inputPoints, + const EOperator operatorType, + const typename Kokkos::TeamPolicy::member_type& team_member, + const typename DT::execution_space::scratch_memory_space & scratchStorage, + const ordinal_type subcellDim, + const ordinal_type subcellOrdinal) const { + + INTREPID2_TEST_FOR_ABORT( !((subcellDim <= 0) && (subcellOrdinal == -1)), + ">>> ERROR: (Intrepid2::Basis_HGRAD_TET_COMP12_FEM::getValues), The capability of selecting subsets of basis functions has not been implemented yet."); + + (void) scratchStorage; //avoid unused variable warning + + const int numPoints = inputPoints.extent(0); + + switch(operatorType) { + case OPERATOR_VALUE: + Kokkos::parallel_for (Kokkos::TeamThreadRange (team_member, numPoints), [=] (ordinal_type& pt) { + auto output = Kokkos::subview( outputValues, Kokkos::ALL(), pt, Kokkos::ALL() ); + const auto input = Kokkos::subview( inputPoints, pt, Kokkos::ALL() ); + Impl::Basis_HGRAD_TET_COMP12_FEM::Serial::getValues( output, input); + }); + break; + case OPERATOR_GRAD: + Kokkos::parallel_for (Kokkos::TeamThreadRange (team_member, numPoints), [=] (ordinal_type& pt) { + auto output = Kokkos::subview( outputValues, Kokkos::ALL(), pt, Kokkos::ALL() ); + const auto input = Kokkos::subview( inputPoints, pt, Kokkos::ALL() ); + Impl::Basis_HGRAD_TET_COMP12_FEM::Serial::getValues( output, input); + }); + break; + default: {} + } + } + +}// namespace Intrepid2 #endif diff --git a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_TET_Cn_FEM.hpp b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_TET_Cn_FEM.hpp index 39b8900291f4..d23d95594bdb 100644 --- a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_TET_Cn_FEM.hpp +++ b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_TET_Cn_FEM.hpp @@ -62,53 +62,57 @@ namespace Intrepid2 { /** \brief See Intrepid2::Basis_HGRAD_TET_Cn_FEM */ - template + template struct Serial { - template + template KOKKOS_INLINE_FUNCTION static void - getValues( outputValueViewType outputValues, - const inputPointViewType inputPoints, - workViewType work, - const vinvViewType vinv ); + getValues( OutputValueViewType outputValues, + const InputPointViewType inputPoints, + WorkViewType work, + const VinvViewType vinv, + const ordinal_type order); }; template + typename OutputValueValueType, class ...OutputValueProperties, + typename InputPointValueType, class ...InputPointProperties, + typename VinvValueType, class ...VinvProperties> static void getValues( const typename DeviceType::execution_space& space, - Kokkos::DynRankView outputValues, - const Kokkos::DynRankView inputPoints, - const Kokkos::DynRankView vinv, + Kokkos::DynRankView outputValues, + const Kokkos::DynRankView inputPoints, + const Kokkos::DynRankView vinv, + const ordinal_type order, const EOperator operatorType); /** \brief See Intrepid2::Basis_HGRAD_TET_Cn_FEM */ - template struct Functor { - outputValueViewType _outputValues; - const inputPointViewType _inputPoints; - const vinvViewType _vinv; - workViewType _work; + OutputValueViewType _outputValues; + const InputPointViewType _inputPoints; + const VinvViewType _vinv; + WorkViewType _work; + const ordinal_type _order; KOKKOS_INLINE_FUNCTION - Functor( outputValueViewType outputValues_, - inputPointViewType inputPoints_, - vinvViewType vinv_, - workViewType work_) + Functor( OutputValueViewType outputValues_, + InputPointViewType inputPoints_, + VinvViewType vinv_, + WorkViewType work_, + ordinal_type order_) : _outputValues(outputValues_), _inputPoints(inputPoints_), - _vinv(vinv_), _work(work_) {} + _vinv(vinv_), _work(work_), _order(order_) {} KOKKOS_INLINE_FUNCTION void operator()(const size_type iter) const { @@ -118,15 +122,15 @@ namespace Intrepid2 { const auto ptRange = Kokkos::pair(ptBegin, ptEnd); const auto input = Kokkos::subview( _inputPoints, ptRange, Kokkos::ALL() ); - typename workViewType::pointer_type ptr = _work.data() + _work.extent(0)*ptBegin*get_dimension_scalar(_work); + typename WorkViewType::pointer_type ptr = _work.data() + _work.extent(0)*ptBegin*get_dimension_scalar(_work); auto vcprop = Kokkos::common_view_alloc_prop(_work); - workViewType work(Kokkos::view_wrap(ptr,vcprop), (ptEnd-ptBegin)*_work.extent(0)); + WorkViewType work(Kokkos::view_wrap(ptr,vcprop), (ptEnd-ptBegin)*_work.extent(0)); - switch (opType) { + switch (OpType) { case OPERATOR_VALUE : { auto output = Kokkos::subview( _outputValues, Kokkos::ALL(), ptRange ); - Serial::getValues( output, input, work, _vinv ); + Serial::getValues( output, input, work, _vinv, _order ); break; } case OPERATOR_GRAD : @@ -135,7 +139,7 @@ namespace Intrepid2 { //case OPERATOR_D3 : { auto output = Kokkos::subview( _outputValues, Kokkos::ALL(), ptRange, Kokkos::ALL() ); - Serial::getValues( output, input, work, _vinv ); + Serial::getValues( output, input, work, _vinv, _order ); break; } default: { @@ -204,9 +208,29 @@ namespace Intrepid2 { outputValues, inputPoints, this->vinv_, + this->basisDegree_, operatorType); } + virtual void + getScratchSpaceSize( ordinal_type& perTeamSpaceSize, + ordinal_type& perThreadSpaceSize, + const PointViewType inputPoints, + const EOperator operatorType = OPERATOR_VALUE) const override; + + KOKKOS_INLINE_FUNCTION + virtual void + getValues( + OutputViewType outputValues, + const PointViewType inputPoints, + const EOperator operatorType, + const typename Kokkos::TeamPolicy::member_type& team_member, + const typename DeviceType::execution_space::scratch_memory_space & scratchStorage, + const ordinal_type subcellDim = -1, + const ordinal_type subcellOrdinal = -1) const override; + + + virtual void getDofCoords( ScalarViewType dofCoords ) const override { diff --git a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_TET_Cn_FEMDef.hpp b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_TET_Cn_FEMDef.hpp index c2c5aaf6cbe3..1c8715525bc0 100644 --- a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_TET_Cn_FEMDef.hpp +++ b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_TET_Cn_FEMDef.hpp @@ -24,44 +24,36 @@ namespace Intrepid2 { // ------------------------------------------------------------------------------------- namespace Impl { -template +template template +typename InputViewType, +typename WorkViewType, +typename VinvViewType> KOKKOS_INLINE_FUNCTION void -Basis_HGRAD_TET_Cn_FEM::Serial:: +Basis_HGRAD_TET_Cn_FEM::Serial:: getValues( OutputViewType output, - const inputViewType input, - workViewType work, - const vinvViewType vinv ) { + const InputViewType input, + WorkViewType work, + const VinvViewType vinv, + const ordinal_type order ) { constexpr ordinal_type spaceDim = 3; const ordinal_type card = vinv.extent(0), npts = input.extent(0); - // compute order - ordinal_type order = 0; - for (ordinal_type p=0;p<=Parameters::MaxOrder;++p) { - if (card == Intrepid2::getPnCardinality(p)) { - order = p; - break; - } - } - - typedef typename Kokkos::DynRankView viewType; - auto vcprop = Kokkos::common_view_alloc_prop(work); + typedef typename Kokkos::DynRankView ViewType; + auto vcprop = Kokkos::common_view_alloc_prop(input); auto ptr = work.data(); - switch (opType) { + switch (OpType) { case OPERATOR_VALUE: { - const viewType phis(Kokkos::view_wrap(ptr, vcprop), card, npts); - viewType dummyView; + const ViewType phis(Kokkos::view_wrap(ptr, vcprop), card, npts); + ViewType dummyView; Impl::Basis_HGRAD_TET_Cn_FEM_ORTH:: - Serial::getValues(phis, input, dummyView, order); + Serial::getValues(phis, input, dummyView, order); for (ordinal_type i=0;i::getValues(phis, input, workView, order); + Serial::getValues(phis, input, workView, order); for (ordinal_type i=0;i(); //(orDn + 1); - const viewType phis(Kokkos::view_wrap(ptr, vcprop), card, npts, dkcard); - viewType dummyView; + const ordinal_type dkcard = getDkCardinality(); //(orDn + 1); + const ViewType phis(Kokkos::view_wrap(ptr, vcprop), card, npts, dkcard); + ViewType dummyView; Impl::Basis_HGRAD_TET_Cn_FEM_ORTH:: - Serial::getValues(phis, input, dummyView, order); + Serial::getValues(phis, input, dummyView, order); for (ordinal_type i=0;i outputValues, const Kokkos::DynRankView inputPoints, const Kokkos::DynRankView vinv, + const ordinal_type order, const EOperator operatorType) { typedef Kokkos::DynRankView outputValueViewType; typedef Kokkos::DynRankView inputPointViewType; @@ -156,7 +149,7 @@ getValues( workViewType work(Kokkos::view_alloc(space, "Basis_HGRAD_TET_Cn_FEM::getValues::work", vcprop), cardinality, inputPoints.extent(0)); typedef Functor FunctorType; - Kokkos::parallel_for( policy, FunctorType(outputValues, inputPoints, vinv, work) ); + Kokkos::parallel_for( policy, FunctorType(outputValues, inputPoints, vinv, work, order) ); break; } case OPERATOR_GRAD: @@ -164,23 +157,16 @@ getValues( workViewType work(Kokkos::view_alloc(space, "Basis_HGRAD_TET_Cn_FEM::getValues::work", vcprop), cardinality*(2*spaceDim+1), inputPoints.extent(0)); typedef Functor FunctorType; - Kokkos::parallel_for( policy, FunctorType(outputValues, inputPoints, vinv, work) ); + Kokkos::parallel_for( policy, FunctorType(outputValues, inputPoints, vinv, work, order) ); break; } case OPERATOR_D2: { typedef Functor FunctorType; workViewType work(Kokkos::view_alloc(space, "Basis_HGRAD_TET_Cn_FEM::getValues::work", vcprop), cardinality*outputValues.extent(2), inputPoints.extent(0)); - Kokkos::parallel_for( policy, FunctorType(outputValues, inputPoints, vinv, work) ); + Kokkos::parallel_for( policy, FunctorType(outputValues, inputPoints, vinv, work, order) ); break; } - /* case OPERATOR_D3: { - typedef Functor FunctorType; - workViewType work(Kokkos::view_alloc("Basis_HGRAD_TET_Cn_FEM::getValues::work", vcprop), cardinality, inputPoints.extent(0), outputValues.extent(2)); - Kokkos::parallel_for( policy, FunctorType(outputValues, inputPoints, vinv, work) ); - break; - }*/ default: { INTREPID2_TEST_FOR_EXCEPTION( true , std::invalid_argument, ">>> ERROR (Basis_HGRAD_TET_Cn_FEM): Operator type not implemented" ); @@ -431,5 +417,65 @@ Basis_HGRAD_TET_Cn_FEM( const ordinal_type order, posDfOrd); } } + + template + void + Basis_HGRAD_TET_Cn_FEM::getScratchSpaceSize( + ordinal_type& perTeamSpaceSize, + ordinal_type& perThreadSpaceSize, + const PointViewType inputPoints, + const EOperator operatorType) const { + perTeamSpaceSize = 0; + perThreadSpaceSize = getWorkSizePerPoint(operatorType)*get_dimension_scalar(inputPoints)*sizeof(typename BasisBase::scalarType); + } + + template + KOKKOS_INLINE_FUNCTION + void + Basis_HGRAD_TET_Cn_FEM::getValues( + OutputViewType outputValues, + const PointViewType inputPoints, + const EOperator operatorType, + const typename Kokkos::TeamPolicy::member_type& team_member, + const typename DT::execution_space::scratch_memory_space & scratchStorage, + const ordinal_type subcellDim, + const ordinal_type subcellOrdinal) const { + + INTREPID2_TEST_FOR_ABORT( !((subcellDim == -1) && (subcellOrdinal == -1)), + ">>> ERROR: (Intrepid2::Basis_HGRAD_TET_Cn_FEM::getValues), The capability of selecting subsets of basis functions has not been implemented yet."); + + const int numPoints = inputPoints.extent(0); + using ScalarType = typename ScalarTraits::scalar_type; + using WorkViewType = Kokkos::DynRankView< ScalarType,typename DT::execution_space::scratch_memory_space,Kokkos::MemoryTraits >; + constexpr ordinal_type spaceDim = 3; + auto sizePerPoint = (operatorType==OPERATOR_VALUE) ? + this->vinv_.extent(0)*get_dimension_scalar(inputPoints) : + (2*spaceDim+1)*this->vinv_.extent(0)*get_dimension_scalar(inputPoints); + WorkViewType workView(scratchStorage, sizePerPoint*team_member.team_size()); + using range_type = Kokkos::pair; + switch(operatorType) { + case OPERATOR_VALUE: + Kokkos::parallel_for (Kokkos::TeamThreadRange (team_member, numPoints), [=] (ordinal_type& pt) { + auto output = Kokkos::subview( outputValues, Kokkos::ALL(), range_type (pt,pt+1), Kokkos::ALL() ); + const auto input = Kokkos::subview( inputPoints, range_type(pt, pt+1), Kokkos::ALL() ); + WorkViewType work(workView.data() + sizePerPoint*team_member.team_rank(), sizePerPoint); + Impl::Basis_HGRAD_TET_Cn_FEM::Serial::getValues( output, input, work, this->vinv_, this->basisDegree_); + }); + break; + case OPERATOR_GRAD: + Kokkos::parallel_for (Kokkos::TeamThreadRange (team_member, numPoints), [=] (ordinal_type& pt) { + auto output = Kokkos::subview( outputValues, Kokkos::ALL(), range_type(pt,pt+1), Kokkos::ALL() ); + const auto input = Kokkos::subview( inputPoints, range_type(pt,pt+1), Kokkos::ALL() ); + WorkViewType work(workView.data() + sizePerPoint*team_member.team_rank(), sizePerPoint); + Impl::Basis_HGRAD_TET_Cn_FEM::Serial::getValues( output, input, work, this->vinv_, this->basisDegree_); + }); + break; + default: { + INTREPID2_TEST_FOR_ABORT( true, + ">>> ERROR (Basis_HGRAD_TET_Cn_FEM): getValues not implemented for this operator"); + } + } + } + } // namespace Intrepid2 #endif diff --git a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_TRI_C1_FEM.hpp b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_TRI_C1_FEM.hpp index 46349310b210..81439bdf3f50 100644 --- a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_TRI_C1_FEM.hpp +++ b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_TRI_C1_FEM.hpp @@ -162,6 +162,23 @@ namespace Intrepid2 { operatorType); } + virtual void + getScratchSpaceSize( ordinal_type& perTeamSpaceSize, + ordinal_type& perThreadSpaceSize, + const PointViewType inputPointsconst, + const EOperator operatorType = OPERATOR_VALUE) const override; + + KOKKOS_INLINE_FUNCTION + virtual void + getValues( + OutputViewType outputValues, + const PointViewType inputPoints, + const EOperator operatorType, + const typename Kokkos::TeamPolicy::member_type& team_member, + const typename DeviceType::execution_space::scratch_memory_space & scratchStorage, + const ordinal_type subcellDim = -1, + const ordinal_type subcellOrdinal = -1) const override; + virtual void getDofCoords( ScalarViewType dofCoords ) const override { diff --git a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_TRI_C1_FEMDef.hpp b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_TRI_C1_FEMDef.hpp index e771ae7a3ee0..bc926788c290 100644 --- a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_TRI_C1_FEMDef.hpp +++ b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_TRI_C1_FEMDef.hpp @@ -204,5 +204,63 @@ namespace Intrepid2 { Kokkos::deep_copy(this->dofCoords_, dofCoords); } + template + void + Basis_HGRAD_TRI_C1_FEM::getScratchSpaceSize( + ordinal_type& perTeamSpaceSize, + ordinal_type& perThreadSpaceSize, + const PointViewType inputPoints, + const EOperator operatorType) const { + perTeamSpaceSize = 0; + perThreadSpaceSize = 0; + } + + template + KOKKOS_INLINE_FUNCTION + void + Basis_HGRAD_TRI_C1_FEM::getValues( + OutputViewType outputValues, + const PointViewType inputPoints, + const EOperator operatorType, + const typename Kokkos::TeamPolicy::member_type& team_member, + const typename DT::execution_space::scratch_memory_space & scratchStorage, + const ordinal_type subcellDim, + const ordinal_type subcellOrdinal) const { + + INTREPID2_TEST_FOR_ABORT( !((subcellDim <= 0) && (subcellOrdinal == -1)), + ">>> ERROR: (Intrepid2::Basis_HGRAD_TRI_C1_FEM::getValues), The capability of selecting subsets of basis functions has not been implemented yet."); + + (void) scratchStorage; //avoid unused variable warning + + const int numPoints = inputPoints.extent(0); + + switch(operatorType) { + case OPERATOR_VALUE: + Kokkos::parallel_for (Kokkos::TeamThreadRange (team_member, numPoints), [=] (ordinal_type& pt) { + auto output = Kokkos::subview( outputValues, Kokkos::ALL(), pt, Kokkos::ALL() ); + const auto input = Kokkos::subview( inputPoints, pt, Kokkos::ALL() ); + Impl::Basis_HGRAD_TRI_C1_FEM::Serial::getValues( output, input); + }); + break; + case OPERATOR_GRAD: + Kokkos::parallel_for (Kokkos::TeamThreadRange (team_member, numPoints), [=] (ordinal_type& pt) { + auto output = Kokkos::subview( outputValues, Kokkos::ALL(), pt, Kokkos::ALL() ); + const auto input = Kokkos::subview( inputPoints, pt, Kokkos::ALL() ); + Impl::Basis_HGRAD_TRI_C1_FEM::Serial::getValues( output, input); + }); + break; + case OPERATOR_CURL: + Kokkos::parallel_for (Kokkos::TeamThreadRange (team_member, numPoints), [=] (ordinal_type& pt) { + auto output = Kokkos::subview( outputValues, Kokkos::ALL(), pt, Kokkos::ALL() ); + const auto input = Kokkos::subview( inputPoints, pt, Kokkos::ALL() ); + Impl::Basis_HGRAD_TRI_C1_FEM::Serial::getValues( output, input); + }); + break; + default: { + INTREPID2_TEST_FOR_ABORT( true, ">>> ERROR: (Intrepid2::Basis_HGRAD_TRI_C1_FEM::getValues), Operator Type not supported."); + } + } + } + }// namespace Intrepid2 #endif diff --git a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_TRI_C2_FEM.hpp b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_TRI_C2_FEM.hpp index 9eb45f9c2716..627fa113720e 100644 --- a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_TRI_C2_FEM.hpp +++ b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_TRI_C2_FEM.hpp @@ -173,6 +173,23 @@ namespace Intrepid2 { operatorType); } + virtual void + getScratchSpaceSize( ordinal_type& perTeamSpaceSize, + ordinal_type& perThreadSpaceSize, + const PointViewType inputPointsconst, + const EOperator operatorType = OPERATOR_VALUE) const override; + + KOKKOS_INLINE_FUNCTION + virtual void + getValues( + OutputViewType outputValues, + const PointViewType inputPoints, + const EOperator operatorType, + const typename Kokkos::TeamPolicy::member_type& team_member, + const typename DeviceType::execution_space::scratch_memory_space & scratchStorage, + const ordinal_type subcellDim = -1, + const ordinal_type subcellOrdinal = -1) const override; + virtual void getDofCoords( ScalarViewType dofCoords ) const override { diff --git a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_TRI_C2_FEMDef.hpp b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_TRI_C2_FEMDef.hpp index 87bb96e2bbe0..86df77f41a27 100644 --- a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_TRI_C2_FEMDef.hpp +++ b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_TRI_C2_FEMDef.hpp @@ -263,5 +263,63 @@ namespace Intrepid2 { Kokkos::deep_copy(this->dofCoords_, dofCoords); } + template + void + Basis_HGRAD_TRI_C2_FEM::getScratchSpaceSize( + ordinal_type& perTeamSpaceSize, + ordinal_type& perThreadSpaceSize, + const PointViewType inputPoints, + const EOperator operatorType) const { + perTeamSpaceSize = 0; + perThreadSpaceSize = 0; + } + + template + KOKKOS_INLINE_FUNCTION + void + Basis_HGRAD_TRI_C2_FEM::getValues( + OutputViewType outputValues, + const PointViewType inputPoints, + const EOperator operatorType, + const typename Kokkos::TeamPolicy::member_type& team_member, + const typename DT::execution_space::scratch_memory_space & scratchStorage, + const ordinal_type subcellDim, + const ordinal_type subcellOrdinal) const { + + INTREPID2_TEST_FOR_ABORT( !((subcellDim <= 0) && (subcellOrdinal == -1)), + ">>> ERROR: (Intrepid2::Basis_HGRAD_TRI_C2_FEM::getValues), The capability of selecting subsets of basis functions has not been implemented yet."); + + (void) scratchStorage; //avoid unused variable warning + + const int numPoints = inputPoints.extent(0); + + switch(operatorType) { + case OPERATOR_VALUE: + Kokkos::parallel_for (Kokkos::TeamThreadRange (team_member, numPoints), [=] (ordinal_type& pt) { + auto output = Kokkos::subview( outputValues, Kokkos::ALL(), pt, Kokkos::ALL() ); + const auto input = Kokkos::subview( inputPoints, pt, Kokkos::ALL() ); + Impl::Basis_HGRAD_TRI_C2_FEM::Serial::getValues( output, input); + }); + break; + case OPERATOR_GRAD: + Kokkos::parallel_for (Kokkos::TeamThreadRange (team_member, numPoints), [=] (ordinal_type& pt) { + auto output = Kokkos::subview( outputValues, Kokkos::ALL(), pt, Kokkos::ALL() ); + const auto input = Kokkos::subview( inputPoints, pt, Kokkos::ALL() ); + Impl::Basis_HGRAD_TRI_C2_FEM::Serial::getValues( output, input); + }); + break; + case OPERATOR_CURL: + Kokkos::parallel_for (Kokkos::TeamThreadRange (team_member, numPoints), [=] (ordinal_type& pt) { + auto output = Kokkos::subview( outputValues, Kokkos::ALL(), pt, Kokkos::ALL() ); + const auto input = Kokkos::subview( inputPoints, pt, Kokkos::ALL() ); + Impl::Basis_HGRAD_TRI_C2_FEM::Serial::getValues( output, input); + }); + break; + default: { + INTREPID2_TEST_FOR_ABORT( true, ">>> ERROR: (Intrepid2::Basis_HGRAD_TRI_C2_FEM::getValues), Operator Type not supported."); + } + } + } + }// namespace Intrepid2 #endif diff --git a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_TRI_Cn_FEM.hpp b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_TRI_Cn_FEM.hpp index c8bc97c3fb76..17ada895efe0 100644 --- a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_TRI_Cn_FEM.hpp +++ b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_TRI_Cn_FEM.hpp @@ -60,53 +60,57 @@ namespace Intrepid2 { work is a rank 1 view having the same value_type of inputPoints and having size equal to getWorkSizePerPoint()*inputPoints.extent(0); */ - template + template struct Serial { - template + template KOKKOS_INLINE_FUNCTION static void - getValues( outputValueViewType outputValues, - const inputPointViewType inputPoints, - workViewType work, - const vinvViewType vinv ); + getValues( OutputValueViewType outputValues, + const InputPointViewType inputPoints, + WorkViewType work, + const VinvViewType vinv, + const ordinal_type order); }; template + typename OutputValueValueType, class ...OutputValueProperties, + typename InputPointValueType, class ...InputPointProperties, + typename VinvValueType, class ...VinvProperties> static void - getValues(const typename DeviceType::execution_space& space, - Kokkos::DynRankView outputValues, - const Kokkos::DynRankView inputPoints, - const Kokkos::DynRankView vinv, - const EOperator operatorType); + getValues( const typename DeviceType::execution_space& space, + Kokkos::DynRankView outputValues, + const Kokkos::DynRankView inputPoints, + const Kokkos::DynRankView vinv, + const ordinal_type order, + const EOperator operatorType); /** \brief See Intrepid2::Basis_HGRAD_TRI_Cn_FEM */ - template struct Functor { - outputValueViewType _outputValues; - const inputPointViewType _inputPoints; - const vinvViewType _vinv; - workViewType _work; + OutputValueViewType _outputValues; + const InputPointViewType _inputPoints; + const VinvViewType _vinv; + WorkViewType _work; + const ordinal_type _order; KOKKOS_INLINE_FUNCTION - Functor( outputValueViewType outputValues_, - inputPointViewType inputPoints_, - vinvViewType vinv_, - workViewType work_) + Functor( OutputValueViewType outputValues_, + InputPointViewType inputPoints_, + VinvViewType vinv_, + WorkViewType work_, + ordinal_type order_) : _outputValues(outputValues_), _inputPoints(inputPoints_), - _vinv(vinv_), _work(work_) {} + _vinv(vinv_), _work(work_), _order(order_) {} KOKKOS_INLINE_FUNCTION void operator()(const size_type iter) const { @@ -116,22 +120,22 @@ namespace Intrepid2 { const auto ptRange = Kokkos::pair(ptBegin, ptEnd); const auto input = Kokkos::subview( _inputPoints, ptRange, Kokkos::ALL() ); - typename workViewType::pointer_type ptr = _work.data() + _work.extent(0)*ptBegin*get_dimension_scalar(_work); + typename WorkViewType::pointer_type ptr = _work.data() + _work.extent(0)*ptBegin*get_dimension_scalar(_work); auto vcprop = Kokkos::common_view_alloc_prop(_work); - workViewType work(Kokkos::view_wrap(ptr,vcprop), (ptEnd-ptBegin)*_work.extent(0)); + WorkViewType work(Kokkos::view_wrap(ptr,vcprop), (ptEnd-ptBegin)*_work.extent(0)); - switch (opType) { + switch (OpType) { case OPERATOR_VALUE : { auto output = Kokkos::subview( _outputValues, Kokkos::ALL(), ptRange ); - Serial::getValues( output, input, work, _vinv ); + Serial::getValues( output, input, work, _vinv, _order ); break; } case OPERATOR_CURL: case OPERATOR_D1: case OPERATOR_D2: { auto output = Kokkos::subview( _outputValues, Kokkos::ALL(), ptRange, Kokkos::ALL() ); - Serial::getValues( output, input, work, _vinv ); + Serial::getValues( output, input, work, _vinv, _order ); break; } default: { @@ -200,9 +204,29 @@ namespace Intrepid2 { outputValues, inputPoints, this->vinv_, + this->basisDegree_, operatorType); } + virtual void + getScratchSpaceSize( ordinal_type& perTeamSpaceSize, + ordinal_type& perThreadSpaceSize, + const PointViewType inputPoints, + const EOperator operatorType = OPERATOR_VALUE) const override; + + KOKKOS_INLINE_FUNCTION + virtual void + getValues( + OutputViewType outputValues, + const PointViewType inputPoints, + const EOperator operatorType, + const typename Kokkos::TeamPolicy::member_type& team_member, + const typename DeviceType::execution_space::scratch_memory_space & scratchStorage, + const ordinal_type subcellDim = -1, + const ordinal_type subcellOrdinal = -1) const override; + + + virtual void getDofCoords( ScalarViewType dofCoords ) const override { diff --git a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_TRI_Cn_FEMDef.hpp b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_TRI_Cn_FEMDef.hpp index 681148713a06..c7b7a40cfa7b 100644 --- a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_TRI_Cn_FEMDef.hpp +++ b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_TRI_Cn_FEMDef.hpp @@ -23,44 +23,36 @@ namespace Intrepid2 { // ------------------------------------------------------------------------------------- namespace Impl { -template +template template +typename InputViewType, +typename WorkViewType, +typename VinvViewType> KOKKOS_INLINE_FUNCTION void -Basis_HGRAD_TRI_Cn_FEM::Serial:: +Basis_HGRAD_TRI_Cn_FEM::Serial:: getValues( OutputViewType output, - const inputViewType input, - workViewType work, - const vinvViewType vinv ) { + const InputViewType input, + WorkViewType work, + const VinvViewType vinv, + const ordinal_type order ) { constexpr ordinal_type spaceDim = 2; const ordinal_type card = vinv.extent(0), npts = input.extent(0); - // compute order - ordinal_type order = 0; - for (ordinal_type p=0;p<=Parameters::MaxOrder;++p) { - if (card == Intrepid2::getPnCardinality(p) ) { - order = p; - break; - } - } - - typedef typename Kokkos::DynRankView viewType; - auto vcprop = Kokkos::common_view_alloc_prop(work); + typedef typename Kokkos::DynRankView ViewType; + auto vcprop = Kokkos::common_view_alloc_prop(input); auto ptr = work.data(); - switch (opType) { + switch (OpType) { case OPERATOR_VALUE: { - const viewType phis(Kokkos::view_wrap(ptr, vcprop), card, npts); - viewType dummyView; + const ViewType phis(Kokkos::view_wrap(ptr, vcprop), card, npts); + ViewType dummyView; Impl::Basis_HGRAD_TRI_Cn_FEM_ORTH:: - Serial::getValues(phis, input, dummyView, order); + Serial::getValues(phis, input, dummyView, order); for (ordinal_type i=0;i::getValues(phis, input, workView, order); + Serial::getValues(phis, input, workView, order); for (ordinal_type i=0;i(); //(orDn + 1); - const viewType phis(Kokkos::view_wrap(ptr, vcprop), card, npts, dkcard); - viewType dummyView; + const ordinal_type dkcard = getDkCardinality(); //(orDn + 1); + const ViewType phis(Kokkos::view_wrap(ptr, vcprop), card, npts, dkcard); + ViewType dummyView; Impl::Basis_HGRAD_TRI_Cn_FEM_ORTH:: - Serial::getValues(phis, input, dummyView, order); + Serial::getValues(phis, input, dummyView, order); for (ordinal_type i=0;i outputValues, const Kokkos::DynRankView inputPoints, const Kokkos::DynRankView vinv, + const ordinal_type order, const EOperator operatorType) { typedef Kokkos::DynRankView outputValueViewType; typedef Kokkos::DynRankView inputPointViewType; @@ -175,7 +168,7 @@ getValues( workViewType work(Kokkos::view_alloc(space, "Basis_HGRAD_TRI_Cn_FEM::getValues::work", vcprop), cardinality, inputPoints.extent(0)); typedef Functor FunctorType; - Kokkos::parallel_for( policy, FunctorType(outputValues, inputPoints, vinv, work) ); + Kokkos::parallel_for( policy, FunctorType(outputValues, inputPoints, vinv, work, order) ); break; } case OPERATOR_GRAD: @@ -183,30 +176,23 @@ getValues( workViewType work(Kokkos::view_alloc(space, "Basis_HGRAD_TRI_Cn_FEM::getValues::work", vcprop), cardinality*(2*spaceDim+1), inputPoints.extent(0)); typedef Functor FunctorType; - Kokkos::parallel_for( policy, FunctorType(outputValues, inputPoints, vinv, work) ); + Kokkos::parallel_for( policy, FunctorType(outputValues, inputPoints, vinv, work, order) ); break; } case OPERATOR_CURL: { workViewType work(Kokkos::view_alloc(space, "Basis_HGRAD_TRI_Cn_FEM::getValues::work", vcprop), cardinality*(2*spaceDim+1), inputPoints.extent(0)); typedef Functor FunctorType; - Kokkos::parallel_for( policy, FunctorType(outputValues, inputPoints, vinv, work) ); + Kokkos::parallel_for( policy, FunctorType(outputValues, inputPoints, vinv, work, order) ); break; } case OPERATOR_D2: { typedef Functor FunctorType; workViewType work(Kokkos::view_alloc(space, "Basis_HGRAD_TRI_Cn_FEM::getValues::work", vcprop), cardinality*outputValues.extent(2), inputPoints.extent(0)); - Kokkos::parallel_for( policy, FunctorType(outputValues, inputPoints, vinv, work) ); + Kokkos::parallel_for( policy, FunctorType(outputValues, inputPoints, vinv, work, order) ); break; } - /* case OPERATOR_D3: { - typedef Functor FunctorType; - workViewType work(Kokkos::view_alloc("Basis_HGRAD_TRI_Cn_FEM::getValues::work", vcprop), cardinality, inputPoints.extent(0), outputValues.extent(2)); - Kokkos::parallel_for( policy, FunctorType(outputValues, inputPoints, vinv, work) ); - break; - }*/ default: { INTREPID2_TEST_FOR_EXCEPTION( true , std::invalid_argument, ">>> ERROR (Basis_HGRAD_TRI_Cn_FEM): Operator type not implemented" ); @@ -242,7 +228,7 @@ Basis_HGRAD_TRI_Cn_FEM( const ordinal_type order, PointTools::getLattice( dofCoords, cellTopo, order, offset, - pointType_ ); + this->pointType_ ); this->dofCoords_ = Kokkos::create_mirror_view(typename DT::memory_space(), dofCoords); Kokkos::deep_copy(this->dofCoords_, dofCoords); @@ -384,5 +370,74 @@ Basis_HGRAD_TRI_Cn_FEM( const ordinal_type order, posDfOrd); } } + + template + void + Basis_HGRAD_TRI_Cn_FEM::getScratchSpaceSize( + ordinal_type& perTeamSpaceSize, + ordinal_type& perThreadSpaceSize, + const PointViewType inputPoints, + const EOperator operatorType) const { + perTeamSpaceSize = 0; + perThreadSpaceSize = getWorkSizePerPoint(operatorType)*get_dimension_scalar(inputPoints)*sizeof(typename BasisBase::scalarType); + } + + template + KOKKOS_INLINE_FUNCTION + void + Basis_HGRAD_TRI_Cn_FEM::getValues( + OutputViewType outputValues, + const PointViewType inputPoints, + const EOperator operatorType, + const typename Kokkos::TeamPolicy::member_type& team_member, + const typename DT::execution_space::scratch_memory_space & scratchStorage, + const ordinal_type subcellDim, + const ordinal_type subcellOrdinal) const { + + INTREPID2_TEST_FOR_ABORT( !((subcellDim == -1) && (subcellOrdinal == -1)), + ">>> ERROR: (Intrepid2::Basis_HGRAD_TRI_Cn_FEM::getValues), The capability of selecting subsets of basis functions has not been implemented yet."); + + const int numPoints = inputPoints.extent(0); + using ScalarType = typename ScalarTraits::scalar_type; + using WorkViewType = Kokkos::DynRankView< ScalarType,typename DT::execution_space::scratch_memory_space,Kokkos::MemoryTraits >; + constexpr ordinal_type spaceDim = 2; + auto sizePerPoint = (operatorType==OPERATOR_VALUE) ? + this->vinv_.extent(0)*get_dimension_scalar(inputPoints) : + (2*spaceDim+1)*this->vinv_.extent(0)*get_dimension_scalar(inputPoints); + WorkViewType workView(scratchStorage, sizePerPoint*team_member.team_size()); + using range_type = Kokkos::pair; + switch(operatorType) { + case OPERATOR_VALUE: + Kokkos::parallel_for (Kokkos::TeamThreadRange (team_member, numPoints), [=] (ordinal_type& pt) { + auto output = Kokkos::subview( outputValues, Kokkos::ALL(), range_type (pt,pt+1), Kokkos::ALL() ); + const auto input = Kokkos::subview( inputPoints, range_type(pt, pt+1), Kokkos::ALL() ); + WorkViewType work(workView.data() + sizePerPoint*team_member.team_rank(), sizePerPoint); + Impl::Basis_HGRAD_TRI_Cn_FEM::Serial::getValues( output, input, work, this->vinv_, this->basisDegree_); + }); + break; + case OPERATOR_GRAD: + Kokkos::parallel_for (Kokkos::TeamThreadRange (team_member, numPoints), [=] (ordinal_type& pt) { + auto output = Kokkos::subview( outputValues, Kokkos::ALL(), range_type(pt,pt+1), Kokkos::ALL() ); + const auto input = Kokkos::subview( inputPoints, range_type(pt,pt+1), Kokkos::ALL() ); + WorkViewType work(workView.data() + sizePerPoint*team_member.team_rank(), sizePerPoint); + Impl::Basis_HGRAD_TRI_Cn_FEM::Serial::getValues( output, input, work, this->vinv_, this->basisDegree_); + }); + break; + case OPERATOR_CURL: + Kokkos::parallel_for (Kokkos::TeamThreadRange (team_member, numPoints), [=] (ordinal_type& pt) { + auto output = Kokkos::subview( outputValues, Kokkos::ALL(), range_type(pt,pt+1), Kokkos::ALL() ); + const auto input = Kokkos::subview( inputPoints, range_type(pt,pt+1), Kokkos::ALL() ); + WorkViewType work(workView.data() + sizePerPoint*team_member.team_rank(), sizePerPoint); + Impl::Basis_HGRAD_TRI_Cn_FEM::Serial::getValues( output, input, work, this->vinv_, this->basisDegree_); + }); + break; + default: { + INTREPID2_TEST_FOR_ABORT( true, + ">>> ERROR (Basis_HGRAD_TRI_Cn_FEM): getValues not implemented for this operator"); + } + } + } + } // namespace Intrepid2 + #endif diff --git a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_TRI_Cn_FEM_ORTHDef.hpp b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_TRI_Cn_FEM_ORTHDef.hpp index 6f5e5abb1dd0..a2b4271518ba 100644 --- a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_TRI_Cn_FEM_ORTHDef.hpp +++ b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_TRI_Cn_FEM_ORTHDef.hpp @@ -198,69 +198,8 @@ void OrthPolynomialTri::ge const inputViewType /* input */, workViewType /* work */, const ordinal_type /* order */ ) { -#if 0 //#ifdef HAVE_INTREPID2_SACADO - -constexpr ordinal_type spaceDim = 2; -constexpr ordinal_type maxCard = Intrepid2::getPnCardinality(); - -typedef typename OutputViewType::value_type value_type; -typedef Sacado::Fad::SFad fad_type; - -const ordinal_type -npts = input.extent(0), -card = output.extent(0); - -// use stack buffer -fad_type inBuf[Parameters::MaxNumPtsPerBasisEval][spaceDim], -outBuf[maxCard][Parameters::MaxNumPtsPerBasisEval][n]; - -typedef typename inputViewType::memory_space memory_space; -typedef typename Kokkos::View outViewType; -typedef typename Kokkos::View inViewType; -auto vcprop = Kokkos::common_view_alloc_prop(input); - -inViewType in(Kokkos::view_wrap((value_type*)&inBuf[0][0], vcprop), npts, spaceDim); -outViewType out(Kokkos::view_wrap((value_type*)&outBuf[0][0][0], vcprop), card, npts, n); - -for (ordinal_type i=0;i outViewType_; -outViewType_ workView; -if (n==2) { - //char outBuf[bufSize*sizeof(typename inViewType::value_type)]; - fad_type outBuf[maxCard][Parameters::MaxNumPtsPerBasisEval][spaceDim+1]; - auto vcprop = Kokkos::common_view_alloc_prop(in); - workView = outViewType_( Kokkos::view_wrap((value_type*)&outBuf[0][0][0], vcprop), card, npts, spaceDim+1); -} -OrthPolynomialTri::generate(out, in, workView, order); - -for (ordinal_type i=0;i 0) { - //n=2: (f_x)_x, (f_y)_x - //n=3: (f_xx)_x, (f_xy)_x, (f_yy)_x - ordinal_type i_Dnm1 = i_dy; - output.access(i,j,i_Dn) = out(i,j,i_Dnm1).dx(0); - } - else { - //n=2: (f_y)_y, (f_z)_y - //n=3: (f_yy)_y - ordinal_type i_Dnm1 = i_dy-1; - output.access(i,j,i_Dn) = out(i,j,i_Dnm1).dx(1); - } - } - } -#else INTREPID2_TEST_FOR_ABORT( true, ">>> ERROR: (Intrepid2::Basis_HGRAD_TRI_Cn_FEM_ORTH::OrthPolynomialTri) Computing of second and higher-order derivatives is not currently supported"); -#endif } diff --git a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_WEDGE_C1_FEM.hpp b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_WEDGE_C1_FEM.hpp index 15daedfbfe49..5b8b73634bb4 100644 --- a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_WEDGE_C1_FEM.hpp +++ b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_WEDGE_C1_FEM.hpp @@ -166,6 +166,23 @@ namespace Intrepid2 { operatorType ); } + virtual void + getScratchSpaceSize( ordinal_type& perTeamSpaceSize, + ordinal_type& perThreadSpaceSize, + const PointViewType inputPointsconst, + const EOperator operatorType = OPERATOR_VALUE) const override; + + KOKKOS_INLINE_FUNCTION + virtual void + getValues( + OutputViewType outputValues, + const PointViewType inputPoints, + const EOperator operatorType, + const typename Kokkos::TeamPolicy::member_type& team_member, + const typename DeviceType::execution_space::scratch_memory_space & scratchStorage, + const ordinal_type subcellDim = -1, + const ordinal_type subcellOrdinal = -1) const override; + virtual void getDofCoords( ScalarViewType dofCoords ) const override { diff --git a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_WEDGE_C1_FEMDef.hpp b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_WEDGE_C1_FEMDef.hpp index 9d2c461edca2..8d76318a49e0 100644 --- a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_WEDGE_C1_FEMDef.hpp +++ b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_WEDGE_C1_FEMDef.hpp @@ -245,5 +245,54 @@ namespace Intrepid2 { Kokkos::deep_copy(this->dofCoords_, dofCoords); } + template + void + Basis_HGRAD_WEDGE_C1_FEM::getScratchSpaceSize( + ordinal_type& perTeamSpaceSize, + ordinal_type& perThreadSpaceSize, + const PointViewType inputPoints, + const EOperator operatorType) const { + perTeamSpaceSize = 0; + perThreadSpaceSize = 0; + } + + template + KOKKOS_INLINE_FUNCTION + void + Basis_HGRAD_WEDGE_C1_FEM::getValues( + OutputViewType outputValues, + const PointViewType inputPoints, + const EOperator operatorType, + const typename Kokkos::TeamPolicy::member_type& team_member, + const typename DT::execution_space::scratch_memory_space & scratchStorage, + const ordinal_type subcellDim, + const ordinal_type subcellOrdinal) const { + + INTREPID2_TEST_FOR_ABORT( !((subcellDim <= 0) && (subcellOrdinal == -1)), + ">>> ERROR: (Intrepid2::Basis_HGRAD_WEDGE_C1_FEM::getValues), The capability of selecting subsets of basis functions has not been implemented yet."); + + (void) scratchStorage; //avoid unused variable warning + + const int numPoints = inputPoints.extent(0); + + switch(operatorType) { + case OPERATOR_VALUE: + Kokkos::parallel_for (Kokkos::TeamThreadRange (team_member, numPoints), [=] (ordinal_type& pt) { + auto output = Kokkos::subview( outputValues, Kokkos::ALL(), pt, Kokkos::ALL() ); + const auto input = Kokkos::subview( inputPoints, pt, Kokkos::ALL() ); + Impl::Basis_HGRAD_WEDGE_C1_FEM::template Serial::getValues( output, input); + }); + break; + case OPERATOR_GRAD: + Kokkos::parallel_for (Kokkos::TeamThreadRange (team_member, numPoints), [=] (ordinal_type& pt) { + auto output = Kokkos::subview( outputValues, Kokkos::ALL(), pt, Kokkos::ALL() ); + const auto input = Kokkos::subview( inputPoints, pt, Kokkos::ALL() ); + Impl::Basis_HGRAD_WEDGE_C1_FEM::template Serial::getValues( output, input); + }); + break; + default: {} + } + } + }// namespace Intrepid2 #endif diff --git a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_WEDGE_C2_FEM.hpp b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_WEDGE_C2_FEM.hpp index d4cb38e7ca55..c952afcf0e6e 100644 --- a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_WEDGE_C2_FEM.hpp +++ b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_WEDGE_C2_FEM.hpp @@ -215,6 +215,23 @@ namespace Intrepid2 { operatorType );; } + virtual void + getScratchSpaceSize( ordinal_type& perTeamSpaceSize, + ordinal_type& perThreadSpaceSize, + const PointViewType inputPointsconst, + const EOperator operatorType = OPERATOR_VALUE) const override; + + KOKKOS_INLINE_FUNCTION + virtual void + getValues( + OutputViewType outputValues, + const PointViewType inputPoints, + const EOperator operatorType, + const typename Kokkos::TeamPolicy::member_type& team_member, + const typename DeviceType::execution_space::scratch_memory_space & scratchStorage, + const ordinal_type subcellDim = -1, + const ordinal_type subcellOrdinal = -1) const override; + virtual void getDofCoords( ScalarViewType dofCoords ) const override { diff --git a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_WEDGE_C2_FEMDef.hpp b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_WEDGE_C2_FEMDef.hpp index 363d21ad19ea..9f5327d94187 100644 --- a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_WEDGE_C2_FEMDef.hpp +++ b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HGRAD_WEDGE_C2_FEMDef.hpp @@ -30,12 +30,13 @@ namespace Intrepid2 { Basis_HGRAD_WEDGE_DEG2_FEM::Serial:: getValues( OutputViewType output, const inputViewType input ) { + typedef typename inputViewType::value_type value_type; switch (opType) { case OPERATOR_VALUE: { - const auto x = input(0); - const auto y = input(1); - const auto z = input(2); - const auto w = 1.0 - x - y; + const value_type x = input(0); + const value_type y = input(1); + const value_type z = input(2); + const value_type w = 1.0 - x - y; // output is a rank-1 array with dimensions (basisCardinality_) if constexpr (!serendipity) { @@ -80,9 +81,9 @@ namespace Intrepid2 { break; } case OPERATOR_GRAD: { - const auto x = input(0); - const auto y = input(1); - const auto z = input(2); + const value_type x = input(0); + const value_type y = input(1); + const value_type z = input(2); if constexpr (!serendipity) { output.access(0, 0) = ((-3 + 4*x + 4*y)*(-1 + z)*z)/2.; @@ -158,7 +159,7 @@ namespace Intrepid2 { output.access(17, 1) = 4*(-1 + x + 2*y)*(-1 + z*z); output.access(17, 2) = 8*y*(-1 + x + y)*z; } else { - const auto w = 1.0 - x - y; + const value_type w = 1.0 - x - y; output.access(0, 0) = -(2.0*w - 1.0 - 0.5*z)*(1.0 - z); output.access(0, 1) = -(2.0*w - 1.0 - 0.5*z)*(1.0 - z); @@ -223,9 +224,9 @@ namespace Intrepid2 { break; } case OPERATOR_D2: { - const auto x = input(0); - const auto y = input(1); - const auto z = input(2); + const value_type x = input(0); + const value_type y = input(1); + const value_type z = input(2); if constexpr (!serendipity) { output.access(0, 0) = 2.*(-1. + z)*z; @@ -356,7 +357,7 @@ namespace Intrepid2 { } else { //serendipity element - const auto w = 1.0 - x - y; + const value_type w = 1.0 - x - y; output.access(0, 0) = 2.0*(1.0 - z); output.access(0, 1) = 2.0*(1.0 - z); output.access(0, 2) = 2.0*w - 0.5 - z; @@ -466,9 +467,9 @@ namespace Intrepid2 { } case OPERATOR_D3: { if constexpr (!serendipity) { - const auto x = input(0); - const auto y = input(1); - const auto z = input(2); + const value_type x = input(0); + const value_type y = input(1); + const value_type z = input(2); output.access(0, 0) = 0.; output.access(0, 1) = 0.; @@ -1082,5 +1083,56 @@ namespace Intrepid2 { Kokkos::deep_copy(this->dofCoords_, dofCoords); } + template + void + Basis_HGRAD_WEDGE_DEG2_FEM::getScratchSpaceSize( + ordinal_type& perTeamSpaceSize, + ordinal_type& perThreadSpaceSize, + const PointViewType inputPoints, + const EOperator operatorType) const { + perTeamSpaceSize = 0; + perThreadSpaceSize = 0; + } + + template + KOKKOS_INLINE_FUNCTION + void + Basis_HGRAD_WEDGE_DEG2_FEM::getValues( + OutputViewType outputValues, + const PointViewType inputPoints, + const EOperator operatorType, + const typename Kokkos::TeamPolicy::member_type& team_member, + const typename DT::execution_space::scratch_memory_space & scratchStorage, + const ordinal_type subcellDim, + const ordinal_type subcellOrdinal) const { + + INTREPID2_TEST_FOR_ABORT( !((subcellDim <= 0) && (subcellOrdinal == -1)), + ">>> ERROR: (Intrepid2::Basis_HGRAD_WEDGE_DEG2_FEM::getValues), The capability of selecting subsets of basis functions has not been implemented yet."); + + (void) scratchStorage; //avoid unused variable warning + + const int numPoints = inputPoints.extent(0); + + switch(operatorType) { + case OPERATOR_VALUE: + Kokkos::parallel_for (Kokkos::TeamThreadRange (team_member, numPoints), [=] (ordinal_type& pt) { + auto output = Kokkos::subview( outputValues, Kokkos::ALL(), pt, Kokkos::ALL() ); + const auto input = Kokkos::subview( inputPoints, pt, Kokkos::ALL() ); + using SerialValue = typename Impl::Basis_HGRAD_WEDGE_DEG2_FEM::template Serial; + SerialValue::getValues( output, input); + }); + break; + case OPERATOR_GRAD: + Kokkos::parallel_for (Kokkos::TeamThreadRange (team_member, numPoints), [=] (ordinal_type& pt) { + auto output = Kokkos::subview( outputValues, Kokkos::ALL(), pt, Kokkos::ALL() ); + const auto input = Kokkos::subview( inputPoints, pt, Kokkos::ALL() ); + using SerialGrad = typename Impl::Basis_HGRAD_WEDGE_DEG2_FEM::template Serial; + SerialGrad::getValues( output, input); + }); + break; + default: {} + } + } + }// namespace Intrepid2 #endif diff --git a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HVOL_HEX_Cn_FEM.hpp b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HVOL_HEX_Cn_FEM.hpp index 96cf0a64405b..388eb9ccdd1b 100644 --- a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HVOL_HEX_Cn_FEM.hpp +++ b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HVOL_HEX_Cn_FEM.hpp @@ -137,20 +137,22 @@ namespace Intrepid2 { class Basis_HVOL_HEX_Cn_FEM : public Basis { public: - using OrdinalTypeArray1DHost = typename Basis::OrdinalTypeArray1DHost; - using OrdinalTypeArray2DHost = typename Basis::OrdinalTypeArray2DHost; - using OrdinalTypeArray3DHost = typename Basis::OrdinalTypeArray3DHost; + using BasisBase = Basis; + + using typename BasisBase::OrdinalTypeArray1DHost; + using typename BasisBase::OrdinalTypeArray2DHost; + using typename BasisBase::OrdinalTypeArray3DHost; + + using typename BasisBase::OutputViewType; + using typename BasisBase::PointViewType ; + using typename BasisBase::ScalarViewType; /** \brief Constructor. */ Basis_HVOL_HEX_Cn_FEM(const ordinal_type order, const EPointType pointType = POINTTYPE_EQUISPACED); - using OutputViewType = typename Basis::OutputViewType; - using PointViewType = typename Basis::PointViewType; - using ScalarViewType = typename Basis::ScalarViewType; - - using Basis::getValues; + using BasisBase::getValues; virtual void @@ -172,6 +174,23 @@ namespace Intrepid2 { operatorType ); } + virtual void + getScratchSpaceSize( ordinal_type& perTeamSpaceSize, + ordinal_type& perThreadSpaceSize, + const PointViewType inputPoints, + const EOperator operatorType = OPERATOR_VALUE) const override; + + KOKKOS_INLINE_FUNCTION + virtual void + getValues( + OutputViewType outputValues, + const PointViewType inputPoints, + const EOperator operatorType, + const typename Kokkos::TeamPolicy::member_type& team_member, + const typename DeviceType::execution_space::scratch_memory_space & scratchStorage, + const ordinal_type subcellDim = -1, + const ordinal_type subcellOrdinal = -1) const override; + virtual void diff --git a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HVOL_HEX_Cn_FEMDef.hpp b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HVOL_HEX_Cn_FEMDef.hpp index 652df8ee2689..617eeb9cad84 100644 --- a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HVOL_HEX_Cn_FEMDef.hpp +++ b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HVOL_HEX_Cn_FEMDef.hpp @@ -9,7 +9,7 @@ /** \file Intrepid2_HVOL_HEX_Cn_FEMDef.hpp \brief Definition file for FEM basis functions of degree n for H(vol) functions on HEX cells - \author Created by M. Perego, based on the Intrepid2::HGRAD_HEX_Cn_FEM class + \author Created by M. Perego, based on the Intrepid2::HVOL_HEX_Cn_FEM class */ #ifndef __INTREPID2_HVOL_HEX_CN_FEMDEF_HPP__ @@ -20,18 +20,18 @@ namespace Intrepid2 { // ------------------------------------------------------------------------------------- namespace Impl { - template + template template + typename InputViewType, + typename WorkViewType, + typename VinvViewType> KOKKOS_INLINE_FUNCTION void - Basis_HVOL_HEX_Cn_FEM::Serial:: + Basis_HVOL_HEX_Cn_FEM::Serial:: getValues( OutputViewType output, - const inputViewType input, - workViewType work, - const vinvViewType vinv, + const InputViewType input, + WorkViewType work, + const VinvViewType vinv, const ordinal_type operatorDn ) { ordinal_type opDn = operatorDn; @@ -43,21 +43,21 @@ namespace Intrepid2 { const auto input_y = Kokkos::subview(input, Kokkos::ALL(), range_type(1,2)); const auto input_z = Kokkos::subview(input, Kokkos::ALL(), range_type(2,3)); - const ordinal_type dim_s = get_dimension_scalar(work); + const ordinal_type dim_s = get_dimension_scalar(input); auto ptr0 = work.data(); auto ptr1 = work.data()+cardLine*npts*dim_s; auto ptr2 = work.data()+2*cardLine*npts*dim_s; auto ptr3 = work.data()+3*cardLine*npts*dim_s; - typedef typename Kokkos::DynRankView viewType; - auto vcprop = Kokkos::common_view_alloc_prop(work); + typedef typename Kokkos::DynRankView ViewType; + auto vcprop = Kokkos::common_view_alloc_prop(input); - switch (opType) { + switch (OpType) { case OPERATOR_VALUE: { - viewType work_line(Kokkos::view_wrap(ptr0, vcprop), cardLine, npts); - viewType output_x(Kokkos::view_wrap(ptr1, vcprop), cardLine, npts); - viewType output_y(Kokkos::view_wrap(ptr2, vcprop), cardLine, npts); - viewType output_z(Kokkos::view_wrap(ptr3, vcprop), cardLine, npts); + ViewType work_line(Kokkos::view_wrap(ptr0, vcprop), cardLine, npts); + ViewType output_x(Kokkos::view_wrap(ptr1, vcprop), cardLine, npts); + ViewType output_y(Kokkos::view_wrap(ptr2, vcprop), cardLine, npts); + ViewType output_z(Kokkos::view_wrap(ptr3, vcprop), cardLine, npts); Impl::Basis_HVOL_LINE_Cn_FEM::Serial:: getValues(output_x, input_x, work_line, vinv); @@ -88,7 +88,7 @@ namespace Intrepid2 { case OPERATOR_D8: case OPERATOR_D9: case OPERATOR_D10: - opDn = getOperatorOrder(opType); + opDn = getOperatorOrder(OpType); case OPERATOR_Dn: { const ordinal_type dkcard = opDn + 1; @@ -105,35 +105,35 @@ namespace Intrepid2 { if (mult_x < 0) { // pass } else { - viewType work_line(Kokkos::view_wrap(ptr0, vcprop), cardLine, npts); + ViewType work_line(Kokkos::view_wrap(ptr0, vcprop), cardLine, npts); decltype(work_line) output_x, output_y, output_z; if (mult_x) { - output_x = viewType(Kokkos::view_wrap(ptr1, vcprop), cardLine, npts, 1); + output_x = ViewType(Kokkos::view_wrap(ptr1, vcprop), cardLine, npts, 1); Impl::Basis_HVOL_LINE_Cn_FEM::Serial:: getValues(output_x, input_x, work_line, vinv, mult_x); } else { - output_x = viewType(Kokkos::view_wrap(ptr1, vcprop), cardLine, npts); + output_x = ViewType(Kokkos::view_wrap(ptr1, vcprop), cardLine, npts); Impl::Basis_HVOL_LINE_Cn_FEM::Serial:: getValues(output_x, input_x, work_line, vinv); } if (mult_y) { - output_y = viewType(Kokkos::view_wrap(ptr2, vcprop), cardLine, npts, 1); + output_y = ViewType(Kokkos::view_wrap(ptr2, vcprop), cardLine, npts, 1); Impl::Basis_HVOL_LINE_Cn_FEM::Serial:: getValues(output_y, input_y, work_line, vinv, mult_y); } else { - output_y = viewType(Kokkos::view_wrap(ptr2, vcprop), cardLine, npts); + output_y = ViewType(Kokkos::view_wrap(ptr2, vcprop), cardLine, npts); Impl::Basis_HVOL_LINE_Cn_FEM::Serial:: getValues(output_y, input_y, work_line, vinv); } if (mult_z) { - output_z = viewType(Kokkos::view_wrap(ptr3, vcprop), cardLine, npts, 1); + output_z = ViewType(Kokkos::view_wrap(ptr3, vcprop), cardLine, npts, 1); Impl::Basis_HVOL_LINE_Cn_FEM::Serial:: getValues(output_z, input_z, work_line, vinv, mult_z); } else { - output_z = viewType(Kokkos::view_wrap(ptr3, vcprop), cardLine, npts); + output_z = ViewType(Kokkos::view_wrap(ptr3, vcprop), cardLine, npts); Impl::Basis_HVOL_LINE_Cn_FEM::Serial:: getValues(output_z, input_z, work_line, vinv); } @@ -316,7 +316,55 @@ namespace Intrepid2 { this->dofCoords_ = Kokkos::create_mirror_view(typename DT::memory_space(), dofCoordsHost); Kokkos::deep_copy(this->dofCoords_, dofCoordsHost); } - -}// namespace Intrepid2 + + template + void + Basis_HVOL_HEX_Cn_FEM::getScratchSpaceSize( + ordinal_type& perTeamSpaceSize, + ordinal_type& perThreadSpaceSize, + const PointViewType inputPoints, + const EOperator operatorType) const { + perTeamSpaceSize = 0; + perThreadSpaceSize = 4*this->vinv_.extent(0)*get_dimension_scalar(inputPoints)*sizeof(typename BasisBase::scalarType); + } + + template + KOKKOS_INLINE_FUNCTION + void + Basis_HVOL_HEX_Cn_FEM::getValues( + OutputViewType outputValues, + const PointViewType inputPoints, + const EOperator operatorType, + const typename Kokkos::TeamPolicy::member_type& team_member, + const typename DT::execution_space::scratch_memory_space & scratchStorage, + const ordinal_type subcellDim, + const ordinal_type subcellOrdinal) const { + + INTREPID2_TEST_FOR_ABORT( !((subcellDim == -1) && (subcellOrdinal == -1)), + ">>> ERROR: (Intrepid2::Basis_HVOL_HEX_Cn_FEM::getValues), The capability of selecting subsets of basis functions has not been implemented yet."); + + const int numPoints = inputPoints.extent(0); + using ScalarType = typename ScalarTraits::scalar_type; + using WorkViewType = Kokkos::DynRankView< ScalarType,typename DT::execution_space::scratch_memory_space,Kokkos::MemoryTraits >; + auto sizePerPoint = 4*this->vinv_.extent(0)*get_dimension_scalar(inputPoints); + WorkViewType workView(scratchStorage, sizePerPoint*team_member.team_size()); + using range_type = Kokkos::pair; + switch(operatorType) { + case OPERATOR_VALUE: + Kokkos::parallel_for (Kokkos::TeamThreadRange (team_member, numPoints), [=] (ordinal_type& pt) { + auto output = Kokkos::subview( outputValues, Kokkos::ALL(), range_type (pt,pt+1), Kokkos::ALL() ); + const auto input = Kokkos::subview( inputPoints, range_type(pt, pt+1), Kokkos::ALL() ); + WorkViewType work(workView.data() + sizePerPoint*team_member.team_rank(), sizePerPoint); + Impl::Basis_HVOL_HEX_Cn_FEM::Serial::getValues( output, input, work, this->vinv_, this->basisDegree_); + }); + break; + default: { + INTREPID2_TEST_FOR_ABORT( true, + ">>> ERROR (Basis_HVOL_HEX_Cn_FEM): getValues not implemented for this operator"); + } + } + } + +} // namespace Intrepid2 #endif diff --git a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HVOL_LINE_Cn_FEM.hpp b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HVOL_LINE_Cn_FEM.hpp index 380438f33bb4..0be4ce27fba8 100644 --- a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HVOL_LINE_Cn_FEM.hpp +++ b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HVOL_LINE_Cn_FEM.hpp @@ -145,15 +145,16 @@ namespace Intrepid2 { : public Basis { public: using BasisBase = Basis; + using HostBasis = Basis_HVOL_LINE_Cn_FEM; - - using OrdinalTypeArray1DHost = typename BasisBase::OrdinalTypeArray1DHost; - using OrdinalTypeArray2DHost = typename BasisBase::OrdinalTypeArray2DHost; - using OrdinalTypeArray3DHost = typename BasisBase::OrdinalTypeArray3DHost; - - using OutputViewType = typename BasisBase::OutputViewType; - using PointViewType = typename BasisBase::PointViewType ; - using ScalarViewType = typename BasisBase::ScalarViewType; + + using typename BasisBase::OrdinalTypeArray1DHost; + using typename BasisBase::OrdinalTypeArray2DHost; + using typename BasisBase::OrdinalTypeArray3DHost; + + using typename BasisBase::OutputViewType; + using typename BasisBase::PointViewType ; + using typename BasisBase::ScalarViewType; /** \brief Constructor. */ @@ -182,6 +183,23 @@ namespace Intrepid2 { operatorType ); } + virtual void + getScratchSpaceSize( ordinal_type& perTeamSpaceSize, + ordinal_type& perThreadSpaceSize, + const PointViewType inputPointsconst, + const EOperator operatorType = OPERATOR_VALUE) const override; + + KOKKOS_INLINE_FUNCTION + virtual void + getValues( + OutputViewType outputValues, + const PointViewType inputPoints, + const EOperator operatorType, + const typename Kokkos::TeamPolicy::member_type& team_member, + const typename DeviceType::execution_space::scratch_memory_space & scratchStorage, + const ordinal_type subcellDim = -1, + const ordinal_type subcellOrdinal = -1) const override; + virtual void getDofCoords( ScalarViewType dofCoords ) const override { diff --git a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HVOL_LINE_Cn_FEMDef.hpp b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HVOL_LINE_Cn_FEMDef.hpp index 3d742d4a30a4..dc8f25d3cd7e 100644 --- a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HVOL_LINE_Cn_FEMDef.hpp +++ b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HVOL_LINE_Cn_FEMDef.hpp @@ -9,7 +9,7 @@ /** \file Intrepid2_HVOL_LINE_Cn_FEMDef.hpp \brief Definition file for FEM basis functions of degree n for H(vol) functions on LINE. - \author Created by M. Perego, based on the Intrepid2::HGRAD_LINE_Cn_FEM class + \author Created by M. Perego, based on the Intrepid2::HVOL_LINE_Cn_FEM class */ #ifndef __INTREPID2_HVOL_LINE_CN_FEM_DEF_HPP__ @@ -22,16 +22,16 @@ namespace Intrepid2 { template template + typename InputViewType, + typename WorkViewType, + typename VinvViewType> KOKKOS_INLINE_FUNCTION void Basis_HVOL_LINE_Cn_FEM::Serial:: getValues( OutputViewType output, - const inputViewType input, - workViewType work, - const vinvViewType vinv, + const InputViewType input, + WorkViewType work, + const VinvViewType vinv, const ordinal_type operatorDn ) { ordinal_type opDn = operatorDn; @@ -41,12 +41,12 @@ namespace Intrepid2 { const ordinal_type order = card - 1; const double alpha = 0.0, beta = 0.0; - typedef typename Kokkos::DynRankView viewType; - auto vcprop = Kokkos::common_view_alloc_prop(work); + typedef typename Kokkos::DynRankView ViewType; + auto vcprop = Kokkos::common_view_alloc_prop(input); switch (opType) { case OPERATOR_VALUE: { - viewType phis(Kokkos::view_wrap(work.data(), vcprop), card, npts); + ViewType phis(Kokkos::view_wrap(work.data(), vcprop), card, npts); Impl::Basis_HGRAD_LINE_Cn_FEM_JACOBI:: Serial::getValues(phis, input, order, alpha, beta); @@ -74,7 +74,7 @@ namespace Intrepid2 { case OPERATOR_Dn: { // dkcard is always 1 for 1D element const ordinal_type dkcard = 1; - viewType phis(Kokkos::view_wrap(work.data(), vcprop), card, npts, dkcard); + ViewType phis(Kokkos::view_wrap(work.data(), vcprop), card, npts, dkcard); Impl::Basis_HGRAD_LINE_Cn_FEM_JACOBI:: Serial::getValues(phis, input, order, alpha, beta, opDn); @@ -289,22 +289,56 @@ namespace Intrepid2 { posDfOrd); } } + + template + void + Basis_HVOL_LINE_Cn_FEM::getScratchSpaceSize( + ordinal_type& perTeamSpaceSize, + ordinal_type& perThreadSpaceSize, + const PointViewType inputPoints, + const EOperator operatorType) const { + perTeamSpaceSize = 0; + perThreadSpaceSize = this->vinv_.extent(0)*get_dimension_scalar(inputPoints)*sizeof(typename BasisBase::scalarType); + } + + template + KOKKOS_INLINE_FUNCTION + void + Basis_HVOL_LINE_Cn_FEM::getValues( + OutputViewType outputValues, + const PointViewType inputPoints, + const EOperator operatorType, + const typename Kokkos::TeamPolicy::member_type& team_member, + const typename DT::execution_space::scratch_memory_space & scratchStorage, + const ordinal_type subcellDim, + const ordinal_type subcellOrdinal) const { + + INTREPID2_TEST_FOR_ABORT( !((subcellDim == -1) && (subcellOrdinal == -1)), + ">>> ERROR: (Intrepid2::Basis_HVOL_LINE_Cn_FEM::getValues), The capability of selecting subsets of basis functions has not been implemented yet."); + + const int numPoints = inputPoints.extent(0); + using ScalarType = typename ScalarTraits::scalar_type; + using WorkViewType = Kokkos::DynRankView< ScalarType,typename DT::execution_space::scratch_memory_space,Kokkos::MemoryTraits >; + ordinal_type sizePerPoint = this->vinv_.extent(0)*get_dimension_scalar(inputPoints); + WorkViewType workView(scratchStorage, sizePerPoint*team_member.team_size()); + using range_type = Kokkos::pair; + + switch(operatorType) { + case OPERATOR_VALUE: + Kokkos::parallel_for (Kokkos::TeamThreadRange (team_member, numPoints), [=] (ordinal_type& pt) { + auto output = Kokkos::subview( outputValues, Kokkos::ALL(), range_type (pt,pt+1), Kokkos::ALL() ); + const auto input = Kokkos::subview( inputPoints, range_type(pt, pt+1), Kokkos::ALL() ); + WorkViewType work(workView.data() + sizePerPoint*team_member.team_rank(), sizePerPoint); + Impl::Basis_HVOL_LINE_Cn_FEM::Serial::getValues( output, input, work, this->vinv_ ); + }); + break; + default: { + INTREPID2_TEST_FOR_ABORT( true, + ">>> ERROR (Basis_HVOL_LINE_Cn_FEM): getValues not implemented for this operator"); + } + } + } }// namespace Intrepid2 #endif - - - - - - - - - - - - - - - diff --git a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HVOL_QUAD_Cn_FEM.hpp b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HVOL_QUAD_Cn_FEM.hpp index 496522a6278c..6329c3cb30ce 100644 --- a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HVOL_QUAD_Cn_FEM.hpp +++ b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HVOL_QUAD_Cn_FEM.hpp @@ -132,20 +132,22 @@ namespace Intrepid2 { class Basis_HVOL_QUAD_Cn_FEM : public Basis { public: - using OrdinalTypeArray1DHost = typename Basis::OrdinalTypeArray1DHost; - using OrdinalTypeArray2DHost = typename Basis::OrdinalTypeArray2DHost; - using OrdinalTypeArray3DHost = typename Basis::OrdinalTypeArray3DHost; + using BasisBase = Basis; + + using typename BasisBase::OrdinalTypeArray1DHost; + using typename BasisBase::OrdinalTypeArray2DHost; + using typename BasisBase::OrdinalTypeArray3DHost; + + using typename BasisBase::OutputViewType; + using typename BasisBase::PointViewType ; + using typename BasisBase::ScalarViewType; /** \brief Constructor. */ Basis_HVOL_QUAD_Cn_FEM(const ordinal_type order, const EPointType pointType = POINTTYPE_EQUISPACED); - using OutputViewType = typename Basis::OutputViewType; - using PointViewType = typename Basis::PointViewType; - using ScalarViewType = typename Basis::ScalarViewType; - - using Basis::getValues; + using BasisBase::getValues; virtual void @@ -167,6 +169,24 @@ namespace Intrepid2 { operatorType ); } + virtual void + getScratchSpaceSize( ordinal_type& perTeamSpaceSize, + ordinal_type& perThreadSpaceSize, + const PointViewType inputPoints, + const EOperator operatorType = OPERATOR_VALUE) const override; + + KOKKOS_INLINE_FUNCTION + virtual void + getValues( + OutputViewType outputValues, + const PointViewType inputPoints, + const EOperator operatorType, + const typename Kokkos::TeamPolicy::member_type& team_member, + const typename DeviceType::execution_space::scratch_memory_space & scratchStorage, + const ordinal_type subcellDim = -1, + const ordinal_type subcellOrdinal = -1) const override; + + virtual void getDofCoords( ScalarViewType dofCoords ) const override { diff --git a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HVOL_QUAD_Cn_FEMDef.hpp b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HVOL_QUAD_Cn_FEMDef.hpp index 2a9e2678b771..f492b6a65f7c 100644 --- a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HVOL_QUAD_Cn_FEMDef.hpp +++ b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HVOL_QUAD_Cn_FEMDef.hpp @@ -19,22 +19,22 @@ namespace Intrepid2 { // ------------------------------------------------------------------------------------- namespace Impl { - - template + + template template + typename InputViewType, + typename WorkViewType, + typename VinvViewType> KOKKOS_INLINE_FUNCTION void - Basis_HVOL_QUAD_Cn_FEM::Serial:: + Basis_HVOL_QUAD_Cn_FEM::Serial:: getValues( OutputViewType output, - const inputViewType input, - workViewType work, - const vinvViewType vinv, + const InputViewType input, + WorkViewType work, + const VinvViewType vinv, const ordinal_type operatorDn ) { ordinal_type opDn = operatorDn; - + const ordinal_type cardLine = vinv.extent(0); const ordinal_type npts = input.extent(0); @@ -42,19 +42,19 @@ namespace Intrepid2 { const auto input_x = Kokkos::subview(input, Kokkos::ALL(), range_type(0,1)); const auto input_y = Kokkos::subview(input, Kokkos::ALL(), range_type(1,2)); - const int dim_s = get_dimension_scalar(work); + const ordinal_type dim_s = get_dimension_scalar(input); auto ptr0 = work.data(); auto ptr1 = work.data()+cardLine*npts*dim_s; auto ptr2 = work.data()+2*cardLine*npts*dim_s; - typedef typename Kokkos::DynRankView viewType; - auto vcprop = Kokkos::common_view_alloc_prop(work); - - switch (opType) { + typedef typename Kokkos::DynRankView ViewType; + auto vcprop = Kokkos::common_view_alloc_prop(input); + + switch (OpType) { case OPERATOR_VALUE: { - viewType work_line(Kokkos::view_wrap(ptr0, vcprop), cardLine, npts); - viewType output_x(Kokkos::view_wrap(ptr1, vcprop), cardLine, npts); - viewType output_y(Kokkos::view_wrap(ptr2, vcprop), cardLine, npts); + ViewType work_line(Kokkos::view_wrap(ptr0, vcprop), cardLine, npts); + ViewType output_x(Kokkos::view_wrap(ptr1, vcprop), cardLine, npts); + ViewType output_y(Kokkos::view_wrap(ptr2, vcprop), cardLine, npts); Impl::Basis_HVOL_LINE_Cn_FEM::Serial:: getValues(output_x, input_x, work_line, vinv); @@ -81,33 +81,33 @@ namespace Intrepid2 { case OPERATOR_D8: case OPERATOR_D9: case OPERATOR_D10: - opDn = getOperatorOrder(opType); + opDn = getOperatorOrder(OpType); case OPERATOR_Dn: { const auto dkcard = opDn + 1; for (auto l=0;l:: getValues(output_x, input_x, work_line, vinv, mult_x); } else { - output_x = viewType(Kokkos::view_wrap(ptr1, vcprop), cardLine, npts); + output_x = ViewType(Kokkos::view_wrap(ptr1, vcprop), cardLine, npts); Impl::Basis_HVOL_LINE_Cn_FEM::Serial:: getValues(output_x, input_x, work_line, vinv); } if (mult_y) { - output_y = viewType(Kokkos::view_wrap(ptr2, vcprop), cardLine, npts, 1); + output_y = ViewType(Kokkos::view_wrap(ptr2, vcprop), cardLine, npts, 1); Impl::Basis_HVOL_LINE_Cn_FEM::Serial:: getValues(output_y, input_y, work_line, vinv, mult_y); } else { - output_y = viewType(Kokkos::view_wrap(ptr2, vcprop), cardLine, npts); + output_y = ViewType(Kokkos::view_wrap(ptr2, vcprop), cardLine, npts); Impl::Basis_HVOL_LINE_Cn_FEM::Serial:: getValues(output_y, input_y, work_line, vinv); } @@ -282,7 +282,55 @@ namespace Intrepid2 { this->dofCoords_ = Kokkos::create_mirror_view(typename DT::memory_space(), dofCoordsHost); Kokkos::deep_copy(this->dofCoords_, dofCoordsHost); } - -} + + template + void + Basis_HVOL_QUAD_Cn_FEM::getScratchSpaceSize( + ordinal_type& perTeamSpaceSize, + ordinal_type& perThreadSpaceSize, + const PointViewType inputPoints, + const EOperator operatorType) const { + perTeamSpaceSize = 0; + perThreadSpaceSize = 3*this->vinv_.extent(0)*get_dimension_scalar(inputPoints)*sizeof(typename BasisBase::scalarType); + } + + template + KOKKOS_INLINE_FUNCTION + void + Basis_HVOL_QUAD_Cn_FEM::getValues( + OutputViewType outputValues, + const PointViewType inputPoints, + const EOperator operatorType, + const typename Kokkos::TeamPolicy::member_type& team_member, + const typename DT::execution_space::scratch_memory_space & scratchStorage, + const ordinal_type subcellDim, + const ordinal_type subcellOrdinal) const { + + INTREPID2_TEST_FOR_ABORT( !((subcellDim == -1) && (subcellOrdinal == -1)), + ">>> ERROR: (Intrepid2::Basis_HVOL_QUAD_Cn_FEM::getValues), The capability of selecting subsets of basis functions has not been implemented yet."); + + const int numPoints = inputPoints.extent(0); + using ScalarType = typename ScalarTraits::scalar_type; + using WorkViewType = Kokkos::DynRankView< ScalarType,typename DT::execution_space::scratch_memory_space,Kokkos::MemoryTraits >; + auto sizePerPoint = 3*this->vinv_.extent(0)*get_dimension_scalar(inputPoints); + WorkViewType workView(scratchStorage, sizePerPoint*team_member.team_size()); + using range_type = Kokkos::pair; + switch(operatorType) { + case OPERATOR_VALUE: + Kokkos::parallel_for (Kokkos::TeamThreadRange (team_member, numPoints), [=] (ordinal_type& pt) { + auto output = Kokkos::subview( outputValues, Kokkos::ALL(), range_type (pt,pt+1), Kokkos::ALL() ); + const auto input = Kokkos::subview( inputPoints, range_type(pt, pt+1), Kokkos::ALL() ); + WorkViewType work(workView.data() + sizePerPoint*team_member.team_rank(), sizePerPoint); + Impl::Basis_HVOL_QUAD_Cn_FEM::Serial::getValues( output, input, work, this->vinv_, this->basisDegree_); + }); + break; + default: { + INTREPID2_TEST_FOR_ABORT( true, + ">>> ERROR (Basis_HVOL_QUAD_Cn_FEM): getValues not implemented for this operator"); + } + } + } + +} // namespace Intrepid2 #endif diff --git a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HVOL_TET_Cn_FEM.hpp b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HVOL_TET_Cn_FEM.hpp index d47afbf7724f..8f9010f619b8 100644 --- a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HVOL_TET_Cn_FEM.hpp +++ b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HVOL_TET_Cn_FEM.hpp @@ -156,23 +156,23 @@ namespace Intrepid2 { class Basis_HVOL_TET_Cn_FEM : public Basis { public: - using OrdinalTypeArray1DHost = typename Basis::OrdinalTypeArray1DHost; - using OrdinalTypeArray2DHost = typename Basis::OrdinalTypeArray2DHost; - using OrdinalTypeArray3DHost = typename Basis::OrdinalTypeArray3DHost; + using BasisBase = Basis; + + using typename BasisBase::OrdinalTypeArray1DHost; + using typename BasisBase::OrdinalTypeArray2DHost; + using typename BasisBase::OrdinalTypeArray3DHost; + + using typename BasisBase::OutputViewType; + using typename BasisBase::PointViewType ; + using typename BasisBase::ScalarViewType; /** \brief Constructor. */ Basis_HVOL_TET_Cn_FEM(const ordinal_type order, const EPointType pointType = POINTTYPE_EQUISPACED); - - - using OutputViewType = typename Basis::OutputViewType; - using PointViewType = typename Basis::PointViewType; - using ScalarViewType = typename Basis::ScalarViewType; - - typedef typename Basis::scalarType scalarType; - - using Basis::getValues; + + using scalarType = typename BasisBase::scalarType; + using BasisBase::getValues; virtual void @@ -194,6 +194,24 @@ namespace Intrepid2 { operatorType); } + virtual void + getScratchSpaceSize( ordinal_type& perTeamSpaceSize, + ordinal_type& perThreadSpaceSize, + const PointViewType inputPoints, + const EOperator operatorType = OPERATOR_VALUE) const override; + + KOKKOS_INLINE_FUNCTION + virtual void + getValues( + OutputViewType outputValues, + const PointViewType inputPoints, + const EOperator operatorType, + const typename Kokkos::TeamPolicy::member_type& team_member, + const typename DeviceType::execution_space::scratch_memory_space & scratchStorage, + const ordinal_type subcellDim = -1, + const ordinal_type subcellOrdinal = -1) const override; + + virtual void getDofCoords( ScalarViewType dofCoords ) const override { diff --git a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HVOL_TET_Cn_FEMDef.hpp b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HVOL_TET_Cn_FEMDef.hpp index a0945a008159..7927a1e124f6 100644 --- a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HVOL_TET_Cn_FEMDef.hpp +++ b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HVOL_TET_Cn_FEMDef.hpp @@ -23,18 +23,18 @@ namespace Intrepid2 { namespace Impl { - template + template template + typename InputViewType, + typename WorkViewType, + typename VinvViewType> KOKKOS_INLINE_FUNCTION void - Basis_HVOL_TET_Cn_FEM::Serial:: + Basis_HVOL_TET_Cn_FEM::Serial:: getValues( OutputViewType output, - const inputViewType input, - workViewType work, - const vinvViewType vinv ) { + const InputViewType input, + WorkViewType work, + const VinvViewType vinv ) { constexpr ordinal_type spaceDim = 3; const ordinal_type @@ -50,17 +50,17 @@ namespace Intrepid2 { } } - typedef typename Kokkos::DynRankView viewType; - auto vcprop = Kokkos::common_view_alloc_prop(work); + typedef typename Kokkos::DynRankView ViewType; + auto vcprop = Kokkos::common_view_alloc_prop(input); auto ptr = work.data(); - switch (opType) { + switch (OpType) { case OPERATOR_VALUE: { - const viewType phis(Kokkos::view_wrap(ptr, vcprop), card, npts); - workViewType dummyView; + const ViewType phis(Kokkos::view_wrap(ptr, vcprop), card, npts); + ViewType dummyView; Impl::Basis_HGRAD_TET_Cn_FEM_ORTH:: - Serial::getValues(phis, input, dummyView, order); + Serial::getValues(phis, input, dummyView, order); for (ordinal_type i=0;i::getValues(phis, input, workView, order); + Serial::getValues(phis, input, workView, order); for (ordinal_type i=0;i(); //(orDn + 1); - const viewType phis(Kokkos::view_wrap(ptr, vcprop), card, npts, dkcard); - workViewType dummyView; + const ordinal_type dkcard = getDkCardinality(); //(orDn + 1); + const + ViewType phis(Kokkos::view_wrap(ptr, vcprop), card, npts, dkcard); + ViewType dummyView; Impl::Basis_HGRAD_TET_Cn_FEM_ORTH:: - Serial::getValues(phis, input, dummyView, order); + Serial::getValues(phis, input, dummyView, order); for (ordinal_type i=0;i + void + Basis_HVOL_TET_Cn_FEM::getScratchSpaceSize( + ordinal_type& perTeamSpaceSize, + ordinal_type& perThreadSpaceSize, + const PointViewType inputPoints, + const EOperator operatorType) const { + perTeamSpaceSize = 0; + perThreadSpaceSize = this->vinv_.extent(0)*get_dimension_scalar(inputPoints)*sizeof(typename BasisBase::scalarType); + } + + template + KOKKOS_INLINE_FUNCTION + void + Basis_HVOL_TET_Cn_FEM::getValues( + OutputViewType outputValues, + const PointViewType inputPoints, + const EOperator operatorType, + const typename Kokkos::TeamPolicy::member_type& team_member, + const typename DT::execution_space::scratch_memory_space & scratchStorage, + const ordinal_type subcellDim, + const ordinal_type subcellOrdinal) const { + + INTREPID2_TEST_FOR_ABORT( !((subcellDim == -1) && (subcellOrdinal == -1)), + ">>> ERROR: (Intrepid2::Basis_HVOL_TET_Cn_FEM::getValues), The capability of selecting subsets of basis functions has not been implemented yet."); + + const int numPoints = inputPoints.extent(0); + using ScalarType = typename ScalarTraits::scalar_type; + using WorkViewType = Kokkos::DynRankView< ScalarType,typename DT::execution_space::scratch_memory_space,Kokkos::MemoryTraits >; + auto sizePerPoint = this->vinv_.extent(0)*get_dimension_scalar(inputPoints); + WorkViewType workView(scratchStorage, sizePerPoint*team_member.team_size()); + using range_type = Kokkos::pair; + switch(operatorType) { + case OPERATOR_VALUE: + Kokkos::parallel_for (Kokkos::TeamThreadRange (team_member, numPoints), [=] (ordinal_type& pt) { + auto output = Kokkos::subview( outputValues, Kokkos::ALL(), range_type (pt,pt+1), Kokkos::ALL() ); + const auto input = Kokkos::subview( inputPoints, range_type(pt, pt+1), Kokkos::ALL() ); + WorkViewType work(workView.data() + sizePerPoint*team_member.team_rank(), sizePerPoint); + Impl::Basis_HVOL_TET_Cn_FEM::Serial::getValues( output, input, work, this->vinv_); + }); + break; + default: { + INTREPID2_TEST_FOR_ABORT( true, + ">>> ERROR (Basis_HVOL_TET_Cn_FEM): getValues not implemented for this operator"); + } + } + } + } // namespace Intrepid2 #endif diff --git a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HVOL_TRI_Cn_FEM.hpp b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HVOL_TRI_Cn_FEM.hpp index 43a2161c9050..ff20e7426957 100644 --- a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HVOL_TRI_Cn_FEM.hpp +++ b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HVOL_TRI_Cn_FEM.hpp @@ -151,25 +151,24 @@ namespace Intrepid2 { class Basis_HVOL_TRI_Cn_FEM : public Basis { public: + using BasisBase = Basis; using HostBasis = Basis_HVOL_TRI_Cn_FEM; - - using OrdinalTypeArray1DHost = typename Basis::OrdinalTypeArray1DHost; - using OrdinalTypeArray2DHost = typename Basis::OrdinalTypeArray2DHost; - using OrdinalTypeArray3DHost = typename Basis::OrdinalTypeArray3DHost; + + using typename BasisBase::OrdinalTypeArray1DHost; + using typename BasisBase::OrdinalTypeArray2DHost; + using typename BasisBase::OrdinalTypeArray3DHost; + + using typename BasisBase::OutputViewType; + using typename BasisBase::PointViewType ; + using typename BasisBase::ScalarViewType; /** \brief Constructor. */ Basis_HVOL_TRI_Cn_FEM(const ordinal_type order, const EPointType pointType = POINTTYPE_EQUISPACED); - - - using OutputViewType = typename Basis::OutputViewType; - using PointViewType = typename Basis::PointViewType; - using ScalarViewType = typename Basis::ScalarViewType; - - typedef typename Basis::scalarType scalarType; - - using Basis::getValues; + + using scalarType = typename BasisBase::scalarType; + using BasisBase::getValues; virtual void @@ -191,6 +190,24 @@ namespace Intrepid2 { operatorType); } + virtual void + getScratchSpaceSize( ordinal_type& perTeamSpaceSize, + ordinal_type& perThreadSpaceSize, + const PointViewType inputPoints, + const EOperator operatorType = OPERATOR_VALUE) const override; + + KOKKOS_INLINE_FUNCTION + virtual void + getValues( + OutputViewType outputValues, + const PointViewType inputPoints, + const EOperator operatorType, + const typename Kokkos::TeamPolicy::member_type& team_member, + const typename DeviceType::execution_space::scratch_memory_space & scratchStorage, + const ordinal_type subcellDim = -1, + const ordinal_type subcellOrdinal = -1) const override; + + virtual void getDofCoords( ScalarViewType dofCoords ) const override { diff --git a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HVOL_TRI_Cn_FEMDef.hpp b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HVOL_TRI_Cn_FEMDef.hpp index f870940f506b..aa6f54065ff6 100644 --- a/packages/intrepid2/src/Discretization/Basis/Intrepid2_HVOL_TRI_Cn_FEMDef.hpp +++ b/packages/intrepid2/src/Discretization/Basis/Intrepid2_HVOL_TRI_Cn_FEMDef.hpp @@ -22,18 +22,18 @@ namespace Intrepid2 { // ------------------------------------------------------------------------------------- namespace Impl { -template -template -KOKKOS_INLINE_FUNCTION -void -Basis_HVOL_TRI_Cn_FEM::Serial:: -getValues( OutputViewType output, - const inputViewType input, - workViewType work, - const vinvViewType vinv ) { + template + template + KOKKOS_INLINE_FUNCTION + void + Basis_HVOL_TRI_Cn_FEM::Serial:: + getValues( OutputViewType output, + const InputViewType input, + WorkViewType work, + const VinvViewType vinv ) { constexpr ordinal_type spaceDim = 2; const ordinal_type @@ -49,17 +49,17 @@ getValues( OutputViewType output, } } - typedef typename Kokkos::DynRankView viewType; - auto vcprop = Kokkos::common_view_alloc_prop(work); + typedef typename Kokkos::DynRankView ViewType; + auto vcprop = Kokkos::common_view_alloc_prop(input); auto ptr = work.data(); - switch (opType) { + switch (OpType) { case OPERATOR_VALUE: { - const viewType phis(Kokkos::view_wrap(ptr, vcprop), card, npts); - workViewType dummyView; + const ViewType phis(Kokkos::view_wrap(ptr, vcprop), card, npts); + ViewType dummyView; Impl::Basis_HGRAD_TRI_Cn_FEM_ORTH:: - Serial::getValues(phis, input, dummyView, order); + Serial::getValues(phis, input, dummyView, order); for (ordinal_type i=0;i::getValues(phis, input, workView, order); + Serial::getValues(phis, input, workView, order); for (ordinal_type i=0;i(); //(orDn + 1); - const viewType phis(Kokkos::view_wrap(ptr, vcprop), card, npts, dkcard); - workViewType dummyView; + const ordinal_type dkcard = getDkCardinality(); //(orDn + 1); + const ViewType phis(Kokkos::view_wrap(ptr, vcprop), card, npts, dkcard); + ViewType dummyView; Impl::Basis_HGRAD_TRI_Cn_FEM_ORTH:: - Serial::getValues(phis, input, dummyView, order); + Serial::getValues(phis, input, dummyView, order); for (ordinal_type i=0;i + void + Basis_HVOL_TRI_Cn_FEM::getScratchSpaceSize( + ordinal_type& perTeamSpaceSize, + ordinal_type& perThreadSpaceSize, + const PointViewType inputPoints, + const EOperator operatorType) const { + perTeamSpaceSize = 0; + perThreadSpaceSize = this->vinv_.extent(0)*get_dimension_scalar(inputPoints)*sizeof(typename BasisBase::scalarType); + } + + template + KOKKOS_INLINE_FUNCTION + void + Basis_HVOL_TRI_Cn_FEM::getValues( + OutputViewType outputValues, + const PointViewType inputPoints, + const EOperator operatorType, + const typename Kokkos::TeamPolicy::member_type& team_member, + const typename DT::execution_space::scratch_memory_space & scratchStorage, + const ordinal_type subcellDim, + const ordinal_type subcellOrdinal) const { + + INTREPID2_TEST_FOR_ABORT( !((subcellDim == -1) && (subcellOrdinal == -1)), + ">>> ERROR: (Intrepid2::Basis_HVOL_TRI_Cn_FEM::getValues), The capability of selecting subsets of basis functions has not been implemented yet."); + + const int numPoints = inputPoints.extent(0); + using ScalarType = typename ScalarTraits::scalar_type; + using WorkViewType = Kokkos::DynRankView< ScalarType,typename DT::execution_space::scratch_memory_space,Kokkos::MemoryTraits >; + auto sizePerPoint = this->vinv_.extent(0)*get_dimension_scalar(inputPoints); + WorkViewType workView(scratchStorage, sizePerPoint*team_member.team_size()); + using range_type = Kokkos::pair; + switch(operatorType) { + case OPERATOR_VALUE: + Kokkos::parallel_for (Kokkos::TeamThreadRange (team_member, numPoints), [=] (ordinal_type& pt) { + auto output = Kokkos::subview( outputValues, Kokkos::ALL(), range_type (pt,pt+1), Kokkos::ALL() ); + const auto input = Kokkos::subview( inputPoints, range_type(pt, pt+1), Kokkos::ALL() ); + WorkViewType work(workView.data() + sizePerPoint*team_member.team_rank(), sizePerPoint); + Impl::Basis_HVOL_TRI_Cn_FEM::Serial::getValues( output, input, work, this->vinv_); + }); + break; + default: { + INTREPID2_TEST_FOR_ABORT( true, + ">>> ERROR (Basis_HVOL_TRI_Cn_FEM): getValues not implemented for this operator"); + } + } + } + } // namespace Intrepid2 #endif diff --git a/packages/intrepid2/src/Shared/Intrepid2_PolylibDef.hpp b/packages/intrepid2/src/Shared/Intrepid2_PolylibDef.hpp index 26d71b652d17..b60f5fe09297 100644 --- a/packages/intrepid2/src/Shared/Intrepid2_PolylibDef.hpp +++ b/packages/intrepid2/src/Shared/Intrepid2_PolylibDef.hpp @@ -591,57 +591,50 @@ namespace Intrepid2 { for (ordinal_type i = 0; i < np; ++i) polyd(i) = 0.5*(alpha + beta + two); } else { - double a1, a2, a3, a4; - const double apb = alpha + beta; + INTREPID2_TEST_FOR_ABORT(polyd.data() && !polyd.data() , + ">>> ERROR (Polylib::Serial::JacobiPolynomial): polyi view needed to compute polyd view."); + if(!polyi.data()) return; - typename polyiViewType::value_type - poly[MaxPolylibPoint]={}, polyn1[MaxPolylibPoint]={}, polyn2[MaxPolylibPoint]={}; + constexpr ordinal_type maxOrder = 2*MaxPolylibPoint-1; - if (polyi.data()) - for (ordinal_type i=0;i>> ERROR (Polylib::Serial::JacobiPolynomial): Requested order exceeds maxOrder ."); + - for (ordinal_type i = 0; i < np; ++i) { - polyn2[i] = one; - polyn1[i] = 0.5*(alpha - beta + (alpha + beta + two)*z(i)); - } + double a2[maxOrder]={}, a3[maxOrder]={}, a4[maxOrder]={}; + double ad1(0.0), ad2(0.0), ad3(0.0); + const double apb = alpha + beta; + const double amb = alpha - beta; + + typename polyiViewType::value_type polyn1 = polyi(0), polyn2 = polyi(0); for (auto k = 2; k <= n; ++k) { - a1 = two*k*(k + apb)*(two*k + apb - two); - a2 = (two*k + apb - one)*(alpha*alpha - beta*beta); - a3 = (two*k + apb - two)*(two*k + apb - one)*(two*k + apb); - a4 = two*(k + alpha - one)*(k + beta - one)*(two*k + apb); - - a2 /= a1; - a3 /= a1; - a4 /= a1; - - for (ordinal_type i = 0; i < np; ++i) { - poly [i] = (a2 + a3*z(i))*polyn1[i] - a4*polyn2[i]; - polyn2[i] = polyn1[i]; - polyn1[i] = poly [i]; - } + double a1 = two*k*(k + apb)*(two*k + apb - two); + a2[k] = (two*k + apb - one)*(apb*amb)/a1; + a3[k] = (two*k + apb - two)*(two*k + apb - one)*(two*k + apb)/a1; + a4[k] = two*(k + alpha - one)*(k + beta - one)*(two*k + apb)/a1; } if (polyd.data()) { - a1 = n*(alpha - beta); - a2 = n*(two*n + alpha + beta); - a3 = two*(n + alpha)*(n + beta); - a4 = (two*n + alpha + beta); - a1 /= a4; - a2 /= a4; - a3 /= a4; - - // note polyn2 points to polyn1 at end of poly iterations - for (ordinal_type i = 0; i < np; ++i) { - polyd(i) = (a1- a2*z(i))*poly[i] + a3*polyn2[i]; + double ad4 = (two*n + alpha + beta); + ad1 = n*(alpha - beta)/ad4; + ad2 = n*(two*n + alpha + beta)/ad4; + ad3 = two*(n + alpha)*(n + beta)/ad4; + } + + for (ordinal_type i = 0; i < np; ++i) { + polyn2 = one; + polyn1 = 0.5*(amb + (apb + two)*z(i)); + for (auto k = 2; k <= n; ++k) { + polyi(i) = (a2[k] + a3[k]*z(i))*polyn1 - a4[k]*polyn2; + polyn2 = polyn1; + polyn1 = polyi(i); + } + if (polyd.data()) { + polyd(i) = (ad1- ad2*z(i))*polyi(i) + ad3*polyn2; polyd(i) /= (one - z(i)*z(i)); } } - - if (polyi.data()) - for (ordinal_type i=0;i::value && std::is_trivial::value) ? 0 : get_dimension_scalar(view); } + + /// Struct for deleting device instantiation + template + struct DeviceDeleter { + template + void operator()(T* ptr) { + Kokkos::parallel_for(Kokkos::RangePolicy(0,1), + KOKKOS_LAMBDA (const int i) { ptr->~T(); }); + typename Device::execution_space().fence(); + Kokkos::kokkos_free(ptr); + } + }; + + /// Function for creating a vtable on device (requires copy ctor for + /// derived object). Allocates device memory and must be called from + /// host. + template + std::unique_ptr> + copy_virtual_class_to_device(const Derived& host_source) + { + auto* p = static_cast(Kokkos::kokkos_malloc(sizeof(Derived))); + Kokkos::parallel_for(Kokkos::RangePolicy(0,1), + KOKKOS_LAMBDA (const int i) {new (p) Derived(host_source); }); + typename Device::execution_space().fence(); + return std::unique_ptr>(p); + } } // end namespace Intrepid2 #endif diff --git a/packages/intrepid2/unit-test/Discretization/Basis/HCURL_HEX_I1_FEM/CMakeLists.txt b/packages/intrepid2/unit-test/Discretization/Basis/HCURL_HEX_I1_FEM/CMakeLists.txt index f080139e2292..f0c9e31cd911 100644 --- a/packages/intrepid2/unit-test/Discretization/Basis/HCURL_HEX_I1_FEM/CMakeLists.txt +++ b/packages/intrepid2/unit-test/Discretization/Basis/HCURL_HEX_I1_FEM/CMakeLists.txt @@ -1,8 +1,13 @@ TRIBITS_INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}) + +# test +SET(Intrepid2_TEST_ETI_FILE "test_01") + # value types SET(Intrepid2_TEST_ETI_VALUETYPE_NAME "") SET(Intrepid2_TEST_ETI_VALUETYPE "") +SET(Intrepid2_TEST_ETI_SACADO "") LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE_NAME "DOUBLE") LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE "double") @@ -17,9 +22,7 @@ ENDIF() LIST(LENGTH Intrepid2_TEST_ETI_VALUETYPE_NAME ETI_VALUETYPE_COUNT) MATH(EXPR ETI_VALUETYPE_COUNT "${ETI_VALUETYPE_COUNT}-1") -# Host test -SET(Intrepid2_TEST_ETI_FILE "test_01") - +# device SET(Intrepid2_TEST_ETI_DEVICE_NAME "") SET(Intrepid2_TEST_ETI_DEVICE "") IF(Kokkos_ENABLE_SERIAL) @@ -68,3 +71,76 @@ FOREACH(I RANGE ${ETI_DEVICE_COUNT}) ENDFOREACH() ENDFOREACH() + + + +# test +SET(Intrepid2_TEST_ETI_FILE "test_02") + +# value types +SET(Intrepid2_TEST_ETI_VALUETYPE_NAME "") +SET(Intrepid2_TEST_ETI_VALUETYPE "") +SET(Intrepid2_TEST_ETI_SACADO "") + +LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE_NAME "DOUBLE_DOUBLE") +LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE "double,double") +LIST(APPEND Intrepid2_TEST_ETI_SACADO "0") + +IF (HAVE_INTREPID2_SACADO) + LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE_NAME "DFAD_DFAD") + LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE "Sacado::Fad::DFad,Sacado::Fad::DFad ") + LIST(APPEND Intrepid2_TEST_ETI_SACADO "33") +ENDIF() + +LIST(LENGTH Intrepid2_TEST_ETI_VALUETYPE_NAME ETI_VALUETYPE_COUNT) +MATH(EXPR ETI_VALUETYPE_COUNT "${ETI_VALUETYPE_COUNT}-1") + +# device +SET(Intrepid2_TEST_ETI_DEVICE_NAME "") +SET(Intrepid2_TEST_ETI_DEVICE "") +IF(Kokkos_ENABLE_SERIAL) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "Serial") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() +IF(Kokkos_ENABLE_OPENMP) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "OpenMP") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() +IF(Kokkos_ENABLE_CUDA) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "CUDA") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() +IF(Kokkos_ENABLE_HIP) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "HIP") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() + +LIST(LENGTH Intrepid2_TEST_ETI_DEVICE_NAME ETI_DEVICE_COUNT) +MATH(EXPR ETI_DEVICE_COUNT "${ETI_DEVICE_COUNT}-1") + +FOREACH(I RANGE ${ETI_DEVICE_COUNT}) + LIST(GET Intrepid2_TEST_ETI_DEVICE_NAME ${I} ETI_DEVICE_NAME) + LIST(GET Intrepid2_TEST_ETI_DEVICE ${I} ETI_DEVICE) + FOREACH(J RANGE ${ETI_VALUETYPE_COUNT}) + LIST(GET Intrepid2_TEST_ETI_VALUETYPE_NAME ${J} ETI_VALUETYPE_NAME) + LIST(GET Intrepid2_TEST_ETI_VALUETYPE ${J} ETI_VALUETYPE) + LIST(GET Intrepid2_TEST_ETI_SACADO ${J} ETI_SACADO) + FOREACH(ETI_FILE IN LISTS Intrepid2_TEST_ETI_FILE) + SET(ETI_NAME "${ETI_FILE}_${ETI_DEVICE_NAME}_${ETI_VALUETYPE_NAME}") + MESSAGE(STATUS "Generating TEST: HCURL_HEX_I1_FEM ${ETI_NAME}.cpp") + CONFIGURE_FILE(eti/${ETI_FILE}_ETI.in ${ETI_NAME}.cpp) + + TRIBITS_ADD_EXECUTABLE_AND_TEST( + ${ETI_NAME} + SOURCES ${ETI_NAME}.cpp + ARGS PrintItAll + NUM_MPI_PROCS 1 + PASS_REGULAR_EXPRESSION "TEST PASSED" + ADD_DIR_TO_NAME + ) + + ENDFOREACH() + ENDFOREACH() +ENDFOREACH() + + diff --git a/packages/intrepid2/unit-test/Discretization/Basis/HCURL_HEX_I1_FEM/eti/test_02_ETI.in b/packages/intrepid2/unit-test/Discretization/Basis/HCURL_HEX_I1_FEM/eti/test_02_ETI.in new file mode 100644 index 000000000000..cd4d6dabdf43 --- /dev/null +++ b/packages/intrepid2/unit-test/Discretization/Basis/HCURL_HEX_I1_FEM/eti/test_02_ETI.in @@ -0,0 +1,52 @@ +// @HEADER +// ***************************************************************************** +// Intrepid2 Package +// +// Copyright 2007 NTESS and the Intrepid2 contributors. +// SPDX-License-Identifier: BSD-3-Clause +// ***************************************************************************** +// @HEADER + +/** \file test_01.cpp + \brief Unit test of Intrepid2::Basis_HCURL_HEX_I1_FEM team-level getValues. + \author Kyungjoo Kim +*/ + +#include "Kokkos_Core.hpp" + +#define ETI_SACADO @ETI_SACADO@ +#if (ETI_SACADO != 0) /// SACADO +#include "Kokkos_ViewFactory.hpp" +#include "Sacado.hpp" +#endif + +#if (ETI_SACADO == 0) /// double double +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__) +#elif (ETI_SACADO == 11 /* SFAD SFAD */ || ETI_SACADO == 33 /* DFAD DFAD */) +constexpr int num_deriv = 3; +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#elif (ETI_SACADO == 23) +constexpr int num_deriv = 3; +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#elif (ETI_SACADO == 20) +constexpr int num_deriv = 2; +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__) +#endif + +#include "test_02.hpp" + +int main(int argc, char *argv[]) { + + const bool verbose = (argc-1) > 0; + Kokkos::initialize(); + + Intrepid2::Test::HCURL_HEX_I1_FEM_Test02<@ETI_VALUETYPE@,@ETI_DEVICE@>(verbose); + + Kokkos::finalize(); + return 0; +} + diff --git a/packages/intrepid2/unit-test/Discretization/Basis/HCURL_HEX_I1_FEM/test_02.hpp b/packages/intrepid2/unit-test/Discretization/Basis/HCURL_HEX_I1_FEM/test_02.hpp new file mode 100644 index 000000000000..7f4e2807360d --- /dev/null +++ b/packages/intrepid2/unit-test/Discretization/Basis/HCURL_HEX_I1_FEM/test_02.hpp @@ -0,0 +1,187 @@ +// @HEADER +// ***************************************************************************** +// Intrepid2 Package +// +// Copyright 2007 NTESS and the Intrepid2 contributors. +// SPDX-License-Identifier: BSD-3-Clause +// ***************************************************************************** +// @HEADER + +/** \file test_02.hpp + \brief Unit tests for the Intrepid2::HCURL_HEX_I1_FEM class. + \author Created by Kyungjoo Kim, Mauro Perego + */ + + +#include "Intrepid2_config.h" +#include "Kokkos_Random.hpp" +#ifdef HAVE_INTREPID2_DEBUG +#define INTREPID2_TEST_FOR_DEBUG_ABORT_OVERRIDE_TO_CONTINUE +#endif + +#include "Intrepid2_Types.hpp" +#include "Intrepid2_Utils.hpp" + +#include "Intrepid2_HCURL_HEX_I1_FEM.hpp" +#include "packages/intrepid2/unit-test/Discretization/Basis/Setup.hpp" + +namespace Intrepid2 { + + namespace Test { + + // This test evaluates the basis functions at a set of points on a batch of cells using the team-level getValues, + // and compares the results with those obtained using the classic getValues function. + template + int HCURL_HEX_I1_FEM_Test02(const bool verbose) { + + //! Setup test output stream. + Teuchos::RCP outStream = setup_output_stream( + verbose, "HCURL_HEX_I1_FEM, Test 2", {} + ); + + *outStream + << "\n" + << "===============================================================================\n" + << "| Testing Team-level Implemntation of getValues |\n" + << "===============================================================================\n"; + + using DeviceSpaceType = typename DeviceType::execution_space; + Kokkos::print_configuration(std::cout, false); + + int errorFlag = 0; + + try { + using BasisType = Basis_HCURL_HEX_I1_FEM; + auto basisPtr = Teuchos::rcp(new BasisType()); + + const int ncells = 5, npts = 10, ndim = 3; + Kokkos::DynRankView ConstructWithLabelOutView(outputValuesA, ncells, basisPtr->getCardinality(), npts, ndim); + Kokkos::DynRankView ConstructWithLabelOutView(outputValuesB, basisPtr->getCardinality(), npts, ndim); + + Kokkos::DynRankView ConstructWithLabelOutView(outputCurlsA, ncells, basisPtr->getCardinality(), npts, ndim); + Kokkos::DynRankView ConstructWithLabelOutView(outputCurlsB, basisPtr->getCardinality(), npts, ndim); + + Kokkos::DynRankView ConstructWithLabelPointView(point, 1); + + using ScalarType = typename ScalarTraits::scalar_type; + + Kokkos::View inputPointsViewToUseRandom("inputPoints", npts*ndim*get_dimension_scalar(point)); + auto vcprop = Kokkos::common_view_alloc_prop(point); + Kokkos::DynRankView inputPoints (Kokkos::view_wrap(inputPointsViewToUseRandom.data(), vcprop), npts, ndim); + + // random values between (0,1) + Kokkos::Random_XorShift64_Pool random(13718); + Kokkos::fill_random(inputPointsViewToUseRandom, random, 1.0); + + + *outStream << "Computing values and curls for " << ncells << " cells and " << npts << " points using team-level getValues function" <(*basisPtr); + auto basisRawPtr_device = basisPtr_device.get(); + + int scratch_space_level =1; + const int vectorSize = getVectorSizeForHierarchicalParallelism(); + Kokkos::TeamPolicy teamPolicy(ncells, Kokkos::AUTO,vectorSize); + + { //compute values + auto functor = KOKKOS_LAMBDA (typename Kokkos::TeamPolicy::member_type team_member) { + auto valsACell = Kokkos::subview(outputValuesA, team_member.league_rank(), Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL()); + basisRawPtr_device->getValues(valsACell, inputPoints, OPERATOR_VALUE, team_member, team_member.team_scratch(scratch_space_level)); + }; + + //Get the required size of the scratch space per team and per thread. + int perThreadSpaceSize(0), perTeamSpaceSize(0); + basisPtr->getScratchSpaceSize(perTeamSpaceSize,perThreadSpaceSize,inputPoints, OPERATOR_VALUE); + teamPolicy.set_scratch_size(scratch_space_level, Kokkos::PerTeam(perTeamSpaceSize), Kokkos::PerThread(perThreadSpaceSize)); + + Kokkos::parallel_for (teamPolicy,functor); + } + + { //compute curls + auto functor = KOKKOS_LAMBDA (typename Kokkos::TeamPolicy::member_type team_member) { + auto curlsACell = Kokkos::subview(outputCurlsA, team_member.league_rank(), Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL()); + basisRawPtr_device->getValues(curlsACell, inputPoints, OPERATOR_CURL, team_member, team_member.team_scratch(scratch_space_level)); + }; + + //Get the required size of the scratch space per team and per thread. + int perThreadSpaceSize(0), perTeamSpaceSize(0); + basisPtr->getScratchSpaceSize(perTeamSpaceSize,perThreadSpaceSize,inputPoints, OPERATOR_CURL); + teamPolicy.set_scratch_size(scratch_space_level, Kokkos::PerTeam(perTeamSpaceSize), Kokkos::PerThread(perThreadSpaceSize)); + + Kokkos::parallel_for (teamPolicy,functor); + } + } + + *outStream << "Computing values and curls for " << npts << " points using high-level getValues function" <getValues(outputValuesB, inputPoints, OPERATOR_VALUE); + basisPtr->getValues(outputCurlsB, inputPoints, OPERATOR_CURL); + + *outStream << "Comparing values and curls on host" <(); + for (size_t ic=0;ic tol) { + ++errorFlag; + std::cout << ", ic: " << ic << ", i: " << i << ", j: " << j + << ", val A: [" << outputValuesA_Host(ic,i,j,0) << ", " << outputValuesA_Host(ic,i,j,1) << "]" + << ", val B: [" << outputValuesB_Host(i,j,0) << ", " << outputValuesB_Host(i,j,1) << "]" + << ", |diff|: " << diff + << ", tol: " << tol + << std::endl; + } + } + } + + { + // compare curls + const auto outputCurlsA_Host = Kokkos::create_mirror_view(outputCurlsA); Kokkos::deep_copy(outputCurlsA_Host, outputCurlsA); + const auto outputCurlsB_Host = Kokkos::create_mirror_view(outputCurlsB); Kokkos::deep_copy(outputCurlsB_Host, outputCurlsB); + + OutValueType diff = 0; + auto tol = epsilon(); + for (size_t ic=0;ic tol) { + ++errorFlag; + std::cout << ", ic: " << ic << ", i: " << i << ", j: " << j + << ", curls A: [" << outputCurlsA_Host(ic,i,j,0)<< ", " << outputCurlsA_Host(ic,i,j,1) << ", " << outputCurlsA_Host(ic,i,j,2) << "]" + << ", curls B: [" << outputCurlsB_Host(i,j,0) << ", " << outputCurlsB_Host(i,j,1)<< ", " << outputCurlsB_Host(i,j,2) << "]" + << ", |diff|: " << diff + << ", tol: " << tol + << std::endl; + } + } + } + } catch (std::exception &err) { + std::cout << "UNEXPECTED ERROR !!! ----------------------------------------------------------\n"; + std::cout << err.what() << '\n'; + std::cout << "-------------------------------------------------------------------------------" << "\n\n"; + errorFlag = -1000; + }; + + if (errorFlag != 0) + std::cout << "End Result: TEST FAILED\n"; + else + std::cout << "End Result: TEST PASSED\n"; + + return errorFlag; + } + } +} diff --git a/packages/intrepid2/unit-test/Discretization/Basis/HCURL_HEX_In_FEM/CMakeLists.txt b/packages/intrepid2/unit-test/Discretization/Basis/HCURL_HEX_In_FEM/CMakeLists.txt index b682181c9d5b..2e5f6844ed27 100644 --- a/packages/intrepid2/unit-test/Discretization/Basis/HCURL_HEX_In_FEM/CMakeLists.txt +++ b/packages/intrepid2/unit-test/Discretization/Basis/HCURL_HEX_In_FEM/CMakeLists.txt @@ -1,8 +1,13 @@ TRIBITS_INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}) + +# test +SET(Intrepid2_TEST_ETI_FILE "test_01") + # value types SET(Intrepid2_TEST_ETI_VALUETYPE_NAME "") SET(Intrepid2_TEST_ETI_VALUETYPE "") +SET(Intrepid2_TEST_ETI_SACADO "") LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE_NAME "DOUBLE_DOUBLE") LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE "double,double") @@ -32,9 +37,7 @@ ENDIF() LIST(LENGTH Intrepid2_TEST_ETI_VALUETYPE_NAME ETI_VALUETYPE_COUNT) MATH(EXPR ETI_VALUETYPE_COUNT "${ETI_VALUETYPE_COUNT}-1") -# test -SET(Intrepid2_TEST_ETI_FILE "test_01") - +# device SET(Intrepid2_TEST_ETI_DEVICE_NAME "") SET(Intrepid2_TEST_ETI_DEVICE "") IF(Kokkos_ENABLE_SERIAL) @@ -83,3 +86,75 @@ FOREACH(I RANGE ${ETI_DEVICE_COUNT}) ENDFOREACH() ENDFOREACH() + + + +# test +SET(Intrepid2_TEST_ETI_FILE "test_02") + +# value types +SET(Intrepid2_TEST_ETI_VALUETYPE_NAME "") +SET(Intrepid2_TEST_ETI_VALUETYPE "") +SET(Intrepid2_TEST_ETI_SACADO "") + +LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE_NAME "DOUBLE_DOUBLE") +LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE "double,double") +LIST(APPEND Intrepid2_TEST_ETI_SACADO "0") + +IF (HAVE_INTREPID2_SACADO) + LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE_NAME "DFAD_DFAD") + LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE "Sacado::Fad::DFad,Sacado::Fad::DFad ") + LIST(APPEND Intrepid2_TEST_ETI_SACADO "33") +ENDIF() + +LIST(LENGTH Intrepid2_TEST_ETI_VALUETYPE_NAME ETI_VALUETYPE_COUNT) +MATH(EXPR ETI_VALUETYPE_COUNT "${ETI_VALUETYPE_COUNT}-1") + +# device +SET(Intrepid2_TEST_ETI_DEVICE_NAME "") +SET(Intrepid2_TEST_ETI_DEVICE "") +IF(Kokkos_ENABLE_SERIAL) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "Serial") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() +IF(Kokkos_ENABLE_OPENMP) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "OpenMP") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() +IF(Kokkos_ENABLE_CUDA) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "CUDA") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() +IF(Kokkos_ENABLE_HIP) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "HIP") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() + +LIST(LENGTH Intrepid2_TEST_ETI_DEVICE_NAME ETI_DEVICE_COUNT) +MATH(EXPR ETI_DEVICE_COUNT "${ETI_DEVICE_COUNT}-1") + +FOREACH(I RANGE ${ETI_DEVICE_COUNT}) + LIST(GET Intrepid2_TEST_ETI_DEVICE_NAME ${I} ETI_DEVICE_NAME) + LIST(GET Intrepid2_TEST_ETI_DEVICE ${I} ETI_DEVICE) + FOREACH(J RANGE ${ETI_VALUETYPE_COUNT}) + LIST(GET Intrepid2_TEST_ETI_VALUETYPE_NAME ${J} ETI_VALUETYPE_NAME) + LIST(GET Intrepid2_TEST_ETI_VALUETYPE ${J} ETI_VALUETYPE) + LIST(GET Intrepid2_TEST_ETI_SACADO ${J} ETI_SACADO) + FOREACH(ETI_FILE IN LISTS Intrepid2_TEST_ETI_FILE) + SET(ETI_NAME "${ETI_FILE}_${ETI_DEVICE_NAME}_${ETI_VALUETYPE_NAME}") + MESSAGE(STATUS "Generating TEST: HCURL_HEX_In_FEM ${ETI_NAME}.cpp") + CONFIGURE_FILE(eti/${ETI_FILE}_ETI.in ${ETI_NAME}.cpp) + + TRIBITS_ADD_EXECUTABLE_AND_TEST( + ${ETI_NAME} + SOURCES ${ETI_NAME}.cpp + ARGS PrintItAll + NUM_MPI_PROCS 1 + PASS_REGULAR_EXPRESSION "TEST PASSED" + ADD_DIR_TO_NAME + ) + + ENDFOREACH() + ENDFOREACH() +ENDFOREACH() + diff --git a/packages/intrepid2/unit-test/Discretization/Basis/HCURL_HEX_In_FEM/eti/test_02_ETI.in b/packages/intrepid2/unit-test/Discretization/Basis/HCURL_HEX_In_FEM/eti/test_02_ETI.in new file mode 100644 index 000000000000..41f15e65574e --- /dev/null +++ b/packages/intrepid2/unit-test/Discretization/Basis/HCURL_HEX_In_FEM/eti/test_02_ETI.in @@ -0,0 +1,52 @@ +// @HEADER +// ***************************************************************************** +// Intrepid2 Package +// +// Copyright 2007 NTESS and the Intrepid2 contributors. +// SPDX-License-Identifier: BSD-3-Clause +// ***************************************************************************** +// @HEADER + +/** \file test_01.cpp + \brief Unit test of Intrepid2::Basis_HCURL_HEX_In_FEM team-level getValues. + \author Kyungjoo Kim +*/ + +#include "Kokkos_Core.hpp" + +#define ETI_SACADO @ETI_SACADO@ +#if (ETI_SACADO != 0) /// SACADO +#include "Kokkos_ViewFactory.hpp" +#include "Sacado.hpp" +#endif + +#if (ETI_SACADO == 0) /// double double +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__) +#elif (ETI_SACADO == 11 /* SFAD SFAD */ || ETI_SACADO == 33 /* DFAD DFAD */) +constexpr int num_deriv = 3; +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#elif (ETI_SACADO == 23) +constexpr int num_deriv = 3; +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#elif (ETI_SACADO == 20) +constexpr int num_deriv = 2; +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__) +#endif + +#include "test_02.hpp" + +int main(int argc, char *argv[]) { + + const bool verbose = (argc-1) > 0; + Kokkos::initialize(); + + Intrepid2::Test::HCURL_HEX_In_FEM_Test02<@ETI_VALUETYPE@,@ETI_DEVICE@>(verbose); + + Kokkos::finalize(); + return 0; +} + diff --git a/packages/intrepid2/unit-test/Discretization/Basis/HCURL_HEX_In_FEM/test_02.hpp b/packages/intrepid2/unit-test/Discretization/Basis/HCURL_HEX_In_FEM/test_02.hpp new file mode 100644 index 000000000000..e9ecf8ca65a4 --- /dev/null +++ b/packages/intrepid2/unit-test/Discretization/Basis/HCURL_HEX_In_FEM/test_02.hpp @@ -0,0 +1,203 @@ +// @HEADER +// ***************************************************************************** +// Intrepid2 Package +// +// Copyright 2007 NTESS and the Intrepid2 contributors. +// SPDX-License-Identifier: BSD-3-Clause +// ***************************************************************************** +// @HEADER + +/** \file test_02.hpp + \brief Unit tests for the Intrepid2::HCURL_HEX_In_FEM class. + \author Created by Kyungjoo Kim, Mauro Perego + */ + + +#include "Intrepid2_config.h" +#include "Kokkos_Random.hpp" +#ifdef HAVE_INTREPID2_DEBUG +#define INTREPID2_TEST_FOR_DEBUG_ABORT_OVERRIDE_TO_CONTINUE +#endif + +#include "Intrepid2_Types.hpp" +#include "Intrepid2_Utils.hpp" + +#include "Intrepid2_HCURL_HEX_In_FEM.hpp" +#include "packages/intrepid2/unit-test/Discretization/Basis/Setup.hpp" + +namespace Intrepid2 { + + namespace Test { + + // This test evaluates the basis functions at a set of points on a batch of cells using the team-level getValues, + // and compares the results with those obtained using the classic getValues function. + template + int HCURL_HEX_In_FEM_Test02(const bool verbose) { + + //! Setup test output stream. + Teuchos::RCP outStream = setup_output_stream( + verbose, "HCURL_HEX_In_FEM, Test 2", {} + ); + + *outStream + << "\n" + << "===============================================================================\n" + << "| Testing Team-level Implemntation of getValues |\n" + << "===============================================================================\n"; + + using DeviceSpaceType = typename DeviceType::execution_space; + Kokkos::print_configuration(std::cout, false); + + int errorFlag = 0; + constexpr int maxOrder = 9; + try { + for (int order=1;order<=maxOrder;++order) { + using BasisType = Basis_HCURL_HEX_In_FEM; + auto basisPtr = Teuchos::rcp(new BasisType(order)); + + const int ncells = 5, npts = 10, ndim = 3; + Kokkos::DynRankView ConstructWithLabelOutView(outputValuesA, ncells, basisPtr->getCardinality(), npts, ndim); + Kokkos::DynRankView ConstructWithLabelOutView(outputValuesB, basisPtr->getCardinality(), npts, ndim); + + Kokkos::DynRankView ConstructWithLabelOutView(outputCurlsA, ncells, basisPtr->getCardinality(), npts, ndim); + Kokkos::DynRankView ConstructWithLabelOutView(outputCurlsB, basisPtr->getCardinality(), npts, ndim); + + Kokkos::DynRankView ConstructWithLabelPointView(point, 1); + + using ScalarType = typename ScalarTraits::scalar_type; + + Kokkos::View inputPointsViewToUseRandom("inputPoints", npts*ndim*get_dimension_scalar(point)); + auto vcprop = Kokkos::common_view_alloc_prop(point); + Kokkos::DynRankView inputPoints (Kokkos::view_wrap(inputPointsViewToUseRandom.data(), vcprop), npts, ndim); + + // random values between (0,1) + Kokkos::Random_XorShift64_Pool random(13718); + Kokkos::fill_random(inputPointsViewToUseRandom, random, 1.0); + + + *outStream << "Order: " << order << ": Computing values and curls for " << ncells << " cells and " << npts << " points using team-level getValues function" <(*basisPtr); + auto basisRawPtr_device = basisPtr_device.get(); + + int scratch_space_level =1; + const int vectorSize = getVectorSizeForHierarchicalParallelism(); + Kokkos::TeamPolicy teamPolicy(ncells, Kokkos::AUTO,vectorSize); + + { //compute values + auto functor = KOKKOS_LAMBDA (typename Kokkos::TeamPolicy::member_type team_member) { + auto valsACell = Kokkos::subview(outputValuesA, team_member.league_rank(), Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL()); + basisRawPtr_device->getValues(valsACell, inputPoints, OPERATOR_VALUE, team_member, team_member.team_scratch(scratch_space_level)); + }; + + // avoid using a team size larger than needed, to reduce allocated scrach space memory + ordinal_type team_size = teamPolicy.team_size_recommended(functor, Kokkos::ParallelForTag()); + *outStream << "Max Recommended team size: " << team_size << ", Requested team size: " << npts <(ncells, team_size,vectorSize); + + //Get the required size of the scratch space per team and per thread. + int perThreadSpaceSize(0), perTeamSpaceSize(0); + basisPtr->getScratchSpaceSize(perTeamSpaceSize,perThreadSpaceSize,inputPoints, OPERATOR_VALUE); + teamPolicy.set_scratch_size(scratch_space_level, Kokkos::PerTeam(perTeamSpaceSize), Kokkos::PerThread(perThreadSpaceSize)); + + Kokkos::parallel_for (teamPolicy,functor); + } + + { //compute curls + auto functor = KOKKOS_LAMBDA (typename Kokkos::TeamPolicy::member_type team_member) { + auto curlsACell = Kokkos::subview(outputCurlsA, team_member.league_rank(), Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL()); + basisRawPtr_device->getValues(curlsACell, inputPoints, OPERATOR_CURL, team_member, team_member.team_scratch(scratch_space_level)); + }; + + // avoid using a team size larger than needed, to reduce allocated scrach space memory + ordinal_type team_size = teamPolicy.team_size_recommended(functor, Kokkos::ParallelForTag()); + *outStream << "Max Recommended team size: " << team_size << ", Requested team size: " << npts <(ncells, team_size,vectorSize); + + //Get the required size of the scratch space per team and per thread. + int perThreadSpaceSize(0), perTeamSpaceSize(0); + basisPtr->getScratchSpaceSize(perTeamSpaceSize,perThreadSpaceSize,inputPoints, OPERATOR_CURL); + teamPolicy.set_scratch_size(scratch_space_level, Kokkos::PerTeam(perTeamSpaceSize), Kokkos::PerThread(perThreadSpaceSize)); + + Kokkos::parallel_for (teamPolicy,functor); + } + } + + *outStream << "Order: " << order << ": Computing values and curls for " << npts << " points using high-level getValues function" <getValues(outputValuesB, inputPoints, OPERATOR_VALUE); + basisPtr->getValues(outputCurlsB, inputPoints, OPERATOR_CURL); + + *outStream << "Order: " << order << ": Comparing values and curls on host" <(); + for (size_t ic=0;ic tol) { + ++errorFlag; + std::cout << " order: " << order + << ", ic: " << ic << ", i: " << i << ", j: " << j + << ", val A: [" << outputValuesA_Host(ic,i,j,0) << ", " << outputValuesA_Host(ic,i,j,1) << "]" + << ", val B: [" << outputValuesB_Host(i,j,0) << ", " << outputValuesB_Host(i,j,1) << "]" + << ", |diff|: " << diff + << ", tol: " << tol + << std::endl; + } + } + } + + { + // compare curls + const auto outputCurlsA_Host = Kokkos::create_mirror_view(outputCurlsA); Kokkos::deep_copy(outputCurlsA_Host, outputCurlsA); + const auto outputCurlsB_Host = Kokkos::create_mirror_view(outputCurlsB); Kokkos::deep_copy(outputCurlsB_Host, outputCurlsB); + + OutValueType diff = 0; + auto tol = epsilon(); + for (size_t ic=0;ic tol) { + ++errorFlag; + std::cout << " order: " << order + << ", ic: " << ic << ", i: " << i << ", j: " << j + << ", curls A: [" << outputCurlsA_Host(ic,i,j,0)<< ", " << outputCurlsA_Host(ic,i,j,1) << ", " << outputCurlsA_Host(ic,i,j,2) << "]" + << ", curls B: [" << outputCurlsB_Host(i,j,0) << ", " << outputCurlsB_Host(i,j,1)<< ", " << outputCurlsB_Host(i,j,2) << "]" + << ", |diff|: " << diff + << ", tol: " << tol + << std::endl; + } + } + } + } + } catch (std::exception &err) { + std::cout << "UNEXPECTED ERROR !!! ----------------------------------------------------------\n"; + std::cout << err.what() << '\n'; + std::cout << "-------------------------------------------------------------------------------" << "\n\n"; + errorFlag = -1000; + }; + + if (errorFlag != 0) + std::cout << "End Result: TEST FAILED\n"; + else + std::cout << "End Result: TEST PASSED\n"; + + return errorFlag; + } + } +} diff --git a/packages/intrepid2/unit-test/Discretization/Basis/HCURL_QUAD_I1_FEM/CMakeLists.txt b/packages/intrepid2/unit-test/Discretization/Basis/HCURL_QUAD_I1_FEM/CMakeLists.txt index 716000daf9b3..89117d0742fb 100644 --- a/packages/intrepid2/unit-test/Discretization/Basis/HCURL_QUAD_I1_FEM/CMakeLists.txt +++ b/packages/intrepid2/unit-test/Discretization/Basis/HCURL_QUAD_I1_FEM/CMakeLists.txt @@ -1,8 +1,13 @@ TRIBITS_INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}) + +# test +SET(Intrepid2_TEST_ETI_FILE "test_01") + # value types SET(Intrepid2_TEST_ETI_VALUETYPE_NAME "") SET(Intrepid2_TEST_ETI_VALUETYPE "") +SET(Intrepid2_TEST_ETI_SACADO "") LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE_NAME "DOUBLE") LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE "double") @@ -17,9 +22,7 @@ ENDIF() LIST(LENGTH Intrepid2_TEST_ETI_VALUETYPE_NAME ETI_VALUETYPE_COUNT) MATH(EXPR ETI_VALUETYPE_COUNT "${ETI_VALUETYPE_COUNT}-1") -# Host test -SET(Intrepid2_TEST_ETI_FILE "test_01") - +# device SET(Intrepid2_TEST_ETI_DEVICE_NAME "") SET(Intrepid2_TEST_ETI_DEVICE "") IF(Kokkos_ENABLE_SERIAL) @@ -68,3 +71,75 @@ FOREACH(I RANGE ${ETI_DEVICE_COUNT}) ENDFOREACH() ENDFOREACH() + + + +# test +SET(Intrepid2_TEST_ETI_FILE "test_02") + +# value types +SET(Intrepid2_TEST_ETI_VALUETYPE_NAME "") +SET(Intrepid2_TEST_ETI_VALUETYPE "") +SET(Intrepid2_TEST_ETI_SACADO "") + +LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE_NAME "DOUBLE_DOUBLE") +LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE "double,double") +LIST(APPEND Intrepid2_TEST_ETI_SACADO "0") + +IF (HAVE_INTREPID2_SACADO) + LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE_NAME "DFAD_DFAD") + LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE "Sacado::Fad::DFad,Sacado::Fad::DFad ") + LIST(APPEND Intrepid2_TEST_ETI_SACADO "33") +ENDIF() + +LIST(LENGTH Intrepid2_TEST_ETI_VALUETYPE_NAME ETI_VALUETYPE_COUNT) +MATH(EXPR ETI_VALUETYPE_COUNT "${ETI_VALUETYPE_COUNT}-1") + +# device +SET(Intrepid2_TEST_ETI_DEVICE_NAME "") +SET(Intrepid2_TEST_ETI_DEVICE "") +IF(Kokkos_ENABLE_SERIAL) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "Serial") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() +IF(Kokkos_ENABLE_OPENMP) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "OpenMP") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() +IF(Kokkos_ENABLE_CUDA) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "CUDA") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() +IF(Kokkos_ENABLE_HIP) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "HIP") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() + +LIST(LENGTH Intrepid2_TEST_ETI_DEVICE_NAME ETI_DEVICE_COUNT) +MATH(EXPR ETI_DEVICE_COUNT "${ETI_DEVICE_COUNT}-1") + +FOREACH(I RANGE ${ETI_DEVICE_COUNT}) + LIST(GET Intrepid2_TEST_ETI_DEVICE_NAME ${I} ETI_DEVICE_NAME) + LIST(GET Intrepid2_TEST_ETI_DEVICE ${I} ETI_DEVICE) + FOREACH(J RANGE ${ETI_VALUETYPE_COUNT}) + LIST(GET Intrepid2_TEST_ETI_VALUETYPE_NAME ${J} ETI_VALUETYPE_NAME) + LIST(GET Intrepid2_TEST_ETI_VALUETYPE ${J} ETI_VALUETYPE) + LIST(GET Intrepid2_TEST_ETI_SACADO ${J} ETI_SACADO) + FOREACH(ETI_FILE IN LISTS Intrepid2_TEST_ETI_FILE) + SET(ETI_NAME "${ETI_FILE}_${ETI_DEVICE_NAME}_${ETI_VALUETYPE_NAME}") + MESSAGE(STATUS "Generating TEST: HCURL_QUAD_I1_FEM ${ETI_NAME}.cpp") + CONFIGURE_FILE(eti/${ETI_FILE}_ETI.in ${ETI_NAME}.cpp) + + TRIBITS_ADD_EXECUTABLE_AND_TEST( + ${ETI_NAME} + SOURCES ${ETI_NAME}.cpp + ARGS PrintItAll + NUM_MPI_PROCS 1 + PASS_REGULAR_EXPRESSION "TEST PASSED" + ADD_DIR_TO_NAME + ) + + ENDFOREACH() + ENDFOREACH() +ENDFOREACH() + diff --git a/packages/intrepid2/unit-test/Discretization/Basis/HCURL_QUAD_I1_FEM/eti/test_02_ETI.in b/packages/intrepid2/unit-test/Discretization/Basis/HCURL_QUAD_I1_FEM/eti/test_02_ETI.in new file mode 100644 index 000000000000..01d5359f6b02 --- /dev/null +++ b/packages/intrepid2/unit-test/Discretization/Basis/HCURL_QUAD_I1_FEM/eti/test_02_ETI.in @@ -0,0 +1,52 @@ +// @HEADER +// ***************************************************************************** +// Intrepid2 Package +// +// Copyright 2007 NTESS and the Intrepid2 contributors. +// SPDX-License-Identifier: BSD-3-Clause +// ***************************************************************************** +// @HEADER + +/** \file test_01.cpp + \brief Unit test of Intrepid2::Basis_HCURL_QUAD_I1_FEM team-level getValues. + \author Kyungjoo Kim +*/ + +#include "Kokkos_Core.hpp" + +#define ETI_SACADO @ETI_SACADO@ +#if (ETI_SACADO != 0) /// SACADO +#include "Kokkos_ViewFactory.hpp" +#include "Sacado.hpp" +#endif + +#if (ETI_SACADO == 0) /// double double +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__) +#elif (ETI_SACADO == 11 /* SFAD SFAD */ || ETI_SACADO == 33 /* DFAD DFAD */) +constexpr int num_deriv = 3; +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#elif (ETI_SACADO == 23) +constexpr int num_deriv = 3; +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#elif (ETI_SACADO == 20) +constexpr int num_deriv = 2; +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__) +#endif + +#include "test_02.hpp" + +int main(int argc, char *argv[]) { + + const bool verbose = (argc-1) > 0; + Kokkos::initialize(); + + Intrepid2::Test::HCURL_QUAD_I1_FEM_Test02<@ETI_VALUETYPE@,@ETI_DEVICE@>(verbose); + + Kokkos::finalize(); + return 0; +} + diff --git a/packages/intrepid2/unit-test/Discretization/Basis/HCURL_QUAD_I1_FEM/test_02.hpp b/packages/intrepid2/unit-test/Discretization/Basis/HCURL_QUAD_I1_FEM/test_02.hpp new file mode 100644 index 000000000000..ecef9a26d9d4 --- /dev/null +++ b/packages/intrepid2/unit-test/Discretization/Basis/HCURL_QUAD_I1_FEM/test_02.hpp @@ -0,0 +1,185 @@ +// @HEADER +// ***************************************************************************** +// Intrepid2 Package +// +// Copyright 2007 NTESS and the Intrepid2 contributors. +// SPDX-License-Identifier: BSD-3-Clause +// ***************************************************************************** +// @HEADER + +/** \file test_02.hpp + \brief Unit tests for the Intrepid2::HCURL_QUAD_I1_FEM class. + \author Created by Kyungjoo Kim, Mauro Perego + */ + + +#include "Intrepid2_config.h" +#include "Kokkos_Random.hpp" +#ifdef HAVE_INTREPID2_DEBUG +#define INTREPID2_TEST_FOR_DEBUG_ABORT_OVERRIDE_TO_CONTINUE +#endif + +#include "Intrepid2_Types.hpp" +#include "Intrepid2_Utils.hpp" + +#include "Intrepid2_HCURL_QUAD_I1_FEM.hpp" +#include "packages/intrepid2/unit-test/Discretization/Basis/Setup.hpp" + +namespace Intrepid2 { + + namespace Test { + + // This test evaluates the basis functions at a set of points on a batch of cells using the team-level getValues, + // and compares the results with those obtained using the classic getValues function. + template + int HCURL_QUAD_I1_FEM_Test02(const bool verbose) { + + //! Setup test output stream. + Teuchos::RCP outStream = setup_output_stream( + verbose, "HCURL_QUAD_I1_FEM, Test 2", {} + ); + + *outStream + << "\n" + << "===============================================================================\n" + << "| Testing Team-level Implemntation of getValues |\n" + << "===============================================================================\n"; + + using DeviceSpaceType = typename DeviceType::execution_space; + Kokkos::print_configuration(std::cout, false); + + int errorFlag = 0; + + try { + using BasisType = Basis_HCURL_QUAD_I1_FEM; + auto basisPtr = Teuchos::rcp(new BasisType()); + + const int ncells = 5, npts = 10, ndim = 2; + Kokkos::DynRankView ConstructWithLabelOutView(outputValuesA, ncells, basisPtr->getCardinality(), npts, ndim); + Kokkos::DynRankView ConstructWithLabelOutView(outputValuesB, basisPtr->getCardinality(), npts, ndim); + + Kokkos::DynRankView ConstructWithLabelOutView(outputCurlsA, ncells, basisPtr->getCardinality(), npts); + Kokkos::DynRankView ConstructWithLabelOutView(outputCurlsB, basisPtr->getCardinality(), npts); + + Kokkos::DynRankView ConstructWithLabelPointView(point, 1); + + using ScalarType = typename ScalarTraits::scalar_type; + + Kokkos::View inputPointsViewToUseRandom("inputPoints", npts*ndim*get_dimension_scalar(point)); + auto vcprop = Kokkos::common_view_alloc_prop(point); + Kokkos::DynRankView inputPoints (Kokkos::view_wrap(inputPointsViewToUseRandom.data(), vcprop), npts, ndim); + + // random values between (0,1) + Kokkos::Random_XorShift64_Pool random(13718); + Kokkos::fill_random(inputPointsViewToUseRandom, random, 1.0); + + + *outStream << "Computing values and curls for " << ncells << " cells and " << npts << " points using team-level getValues function" <(*basisPtr); + auto basisRawPtr_device = basisPtr_device.get(); + + int scratch_space_level =1; + const int vectorSize = getVectorSizeForHierarchicalParallelism(); + Kokkos::TeamPolicy teamPolicy(ncells, Kokkos::AUTO,vectorSize); + + { //compute values + auto functor = KOKKOS_LAMBDA (typename Kokkos::TeamPolicy::member_type team_member) { + auto valsACell = Kokkos::subview(outputValuesA, team_member.league_rank(), Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL()); + basisRawPtr_device->getValues(valsACell, inputPoints, OPERATOR_VALUE, team_member, team_member.team_scratch(scratch_space_level)); + }; + + //Get the required size of the scratch space per team and per thread. + int perThreadSpaceSize(0), perTeamSpaceSize(0); + basisPtr->getScratchSpaceSize(perTeamSpaceSize,perThreadSpaceSize,inputPoints, OPERATOR_VALUE); + teamPolicy.set_scratch_size(scratch_space_level, Kokkos::PerTeam(perTeamSpaceSize), Kokkos::PerThread(perThreadSpaceSize)); + + Kokkos::parallel_for (teamPolicy,functor); + } + + { //compute curls + auto functor = KOKKOS_LAMBDA (typename Kokkos::TeamPolicy::member_type team_member) { + auto curlsACell = Kokkos::subview(outputCurlsA, team_member.league_rank(), Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL()); + basisRawPtr_device->getValues(curlsACell, inputPoints, OPERATOR_CURL, team_member, team_member.team_scratch(scratch_space_level)); + }; + + //Get the required size of the scratch space per team and per thread. + int perThreadSpaceSize(0), perTeamSpaceSize(0); + basisPtr->getScratchSpaceSize(perTeamSpaceSize,perThreadSpaceSize,inputPoints, OPERATOR_CURL); + teamPolicy.set_scratch_size(scratch_space_level, Kokkos::PerTeam(perTeamSpaceSize), Kokkos::PerThread(perThreadSpaceSize)); + + Kokkos::parallel_for (teamPolicy,functor); + } + } + + *outStream << "Computing values and curls for " << npts << " points using high-level getValues function" <getValues(outputValuesB, inputPoints, OPERATOR_VALUE); + basisPtr->getValues(outputCurlsB, inputPoints, OPERATOR_CURL); + + *outStream << "Comparing values and curls on host" <(); + for (size_t ic=0;ic tol) { + ++errorFlag; + std::cout << ", ic: " << ic << ", i: " << i << ", j: " << j + << ", val A: [" << outputValuesA_Host(ic,i,j,0) << ", " << outputValuesA_Host(ic,i,j,1) << "]" + << ", val B: [" << outputValuesB_Host(i,j,0) << ", " << outputValuesB_Host(i,j,1) << "]" + << ", |diff|: " << diff + << ", tol: " << tol + << std::endl; + } + } + } + + { + // compare curls + const auto outputCurlsA_Host = Kokkos::create_mirror_view(outputCurlsA); Kokkos::deep_copy(outputCurlsA_Host, outputCurlsA); + const auto outputCurlsB_Host = Kokkos::create_mirror_view(outputCurlsB); Kokkos::deep_copy(outputCurlsB_Host, outputCurlsB); + + OutValueType diff = 0; + auto tol = epsilon(); + for (size_t ic=0;ic tol) { + ++errorFlag; + std::cout << ", ic: " << ic << ", i: " << i << ", j: " << j + << ", curls A: [" << outputCurlsA_Host(ic,i,j)<<"]" + << ", curls B: [" << outputCurlsB_Host(i,j) << "]" + << ", |diff|: " << diff + << ", tol: " << tol + << std::endl; + } + } + } + } catch (std::exception &err) { + std::cout << "UNEXPECTED ERROR !!! ----------------------------------------------------------\n"; + std::cout << err.what() << '\n'; + std::cout << "-------------------------------------------------------------------------------" << "\n\n"; + errorFlag = -1000; + }; + + if (errorFlag != 0) + std::cout << "End Result: TEST FAILED\n"; + else + std::cout << "End Result: TEST PASSED\n"; + + return errorFlag; + } + } +} diff --git a/packages/intrepid2/unit-test/Discretization/Basis/HCURL_QUAD_In_FEM/CMakeLists.txt b/packages/intrepid2/unit-test/Discretization/Basis/HCURL_QUAD_In_FEM/CMakeLists.txt index c831e83ec896..2f44c158238f 100644 --- a/packages/intrepid2/unit-test/Discretization/Basis/HCURL_QUAD_In_FEM/CMakeLists.txt +++ b/packages/intrepid2/unit-test/Discretization/Basis/HCURL_QUAD_In_FEM/CMakeLists.txt @@ -1,8 +1,13 @@ TRIBITS_INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}) + +# test +SET(Intrepid2_TEST_ETI_FILE "test_01") + # value types SET(Intrepid2_TEST_ETI_VALUETYPE_NAME "") SET(Intrepid2_TEST_ETI_VALUETYPE "") +SET(Intrepid2_TEST_ETI_SACADO "") LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE_NAME "DOUBLE_DOUBLE") LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE "double,double") @@ -32,9 +37,80 @@ ENDIF() LIST(LENGTH Intrepid2_TEST_ETI_VALUETYPE_NAME ETI_VALUETYPE_COUNT) MATH(EXPR ETI_VALUETYPE_COUNT "${ETI_VALUETYPE_COUNT}-1") +# device +SET(Intrepid2_TEST_ETI_DEVICE_NAME "") +SET(Intrepid2_TEST_ETI_DEVICE "") +IF(Kokkos_ENABLE_SERIAL) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "Serial") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() +IF(Kokkos_ENABLE_OPENMP) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "OpenMP") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() +IF(Kokkos_ENABLE_CUDA) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "CUDA") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() +IF(Kokkos_ENABLE_HIP) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "HIP") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() + +LIST(LENGTH Intrepid2_TEST_ETI_DEVICE_NAME ETI_DEVICE_COUNT) +MATH(EXPR ETI_DEVICE_COUNT "${ETI_DEVICE_COUNT}-1") + +FOREACH(I RANGE ${ETI_DEVICE_COUNT}) + LIST(GET Intrepid2_TEST_ETI_DEVICE_NAME ${I} ETI_DEVICE_NAME) + LIST(GET Intrepid2_TEST_ETI_DEVICE ${I} ETI_DEVICE) + #MESSAGE(STATUS "Generating TEST HCURL_QUAD_In_FEM for ${ETI_DEVICE_NAME} with ${ETI_DEVICE}") + FOREACH(J RANGE ${ETI_VALUETYPE_COUNT}) + LIST(GET Intrepid2_TEST_ETI_VALUETYPE_NAME ${J} ETI_VALUETYPE_NAME) + LIST(GET Intrepid2_TEST_ETI_VALUETYPE ${J} ETI_VALUETYPE) + LIST(GET Intrepid2_TEST_ETI_SACADO ${J} ETI_SACADO) + FOREACH(ETI_FILE IN LISTS Intrepid2_TEST_ETI_FILE) + SET(ETI_NAME "${ETI_FILE}_${ETI_DEVICE_NAME}_${ETI_VALUETYPE_NAME}") + MESSAGE(STATUS "Generating TEST: HCURL_QUAD_In_FEM ${ETI_NAME}.cpp") + CONFIGURE_FILE(eti/${ETI_FILE}_ETI.in ${ETI_NAME}.cpp) + + TRIBITS_ADD_EXECUTABLE_AND_TEST( + ${ETI_NAME} + SOURCES ${ETI_NAME}.cpp + ARGS PrintItAll + NUM_MPI_PROCS 1 + PASS_REGULAR_EXPRESSION "TEST PASSED" + ADD_DIR_TO_NAME + ) + + ENDFOREACH() + ENDFOREACH() +ENDFOREACH() + + + + # test -SET(Intrepid2_TEST_ETI_FILE "test_01") +SET(Intrepid2_TEST_ETI_FILE "test_02") +# value types +SET(Intrepid2_TEST_ETI_VALUETYPE_NAME "") +SET(Intrepid2_TEST_ETI_VALUETYPE "") +SET(Intrepid2_TEST_ETI_SACADO "") + +LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE_NAME "DOUBLE_DOUBLE") +LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE "double,double") +LIST(APPEND Intrepid2_TEST_ETI_SACADO "0") + +IF (HAVE_INTREPID2_SACADO) + LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE_NAME "DFAD_DFAD") + LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE "Sacado::Fad::DFad,Sacado::Fad::DFad ") + LIST(APPEND Intrepid2_TEST_ETI_SACADO "33") +ENDIF() + +LIST(LENGTH Intrepid2_TEST_ETI_VALUETYPE_NAME ETI_VALUETYPE_COUNT) +MATH(EXPR ETI_VALUETYPE_COUNT "${ETI_VALUETYPE_COUNT}-1") + +# device SET(Intrepid2_TEST_ETI_DEVICE_NAME "") SET(Intrepid2_TEST_ETI_DEVICE "") IF(Kokkos_ENABLE_SERIAL) @@ -60,7 +136,6 @@ MATH(EXPR ETI_DEVICE_COUNT "${ETI_DEVICE_COUNT}-1") FOREACH(I RANGE ${ETI_DEVICE_COUNT}) LIST(GET Intrepid2_TEST_ETI_DEVICE_NAME ${I} ETI_DEVICE_NAME) LIST(GET Intrepid2_TEST_ETI_DEVICE ${I} ETI_DEVICE) - #MESSAGE(STATUS "Generating TEST HCURL_QUAD_In_FEM for ${ETI_DEVICE_NAME} with ${ETI_DEVICE}") FOREACH(J RANGE ${ETI_VALUETYPE_COUNT}) LIST(GET Intrepid2_TEST_ETI_VALUETYPE_NAME ${J} ETI_VALUETYPE_NAME) LIST(GET Intrepid2_TEST_ETI_VALUETYPE ${J} ETI_VALUETYPE) diff --git a/packages/intrepid2/unit-test/Discretization/Basis/HCURL_QUAD_In_FEM/eti/test_02_ETI.in b/packages/intrepid2/unit-test/Discretization/Basis/HCURL_QUAD_In_FEM/eti/test_02_ETI.in new file mode 100644 index 000000000000..daa3176be226 --- /dev/null +++ b/packages/intrepid2/unit-test/Discretization/Basis/HCURL_QUAD_In_FEM/eti/test_02_ETI.in @@ -0,0 +1,52 @@ +// @HEADER +// ***************************************************************************** +// Intrepid2 Package +// +// Copyright 2007 NTESS and the Intrepid2 contributors. +// SPDX-License-Identifier: BSD-3-Clause +// ***************************************************************************** +// @HEADER + +/** \file test_01.cpp + \brief Unit test of Intrepid2::Basis_HCURL_QUAD_In_FEM team-level getValues. + \author Kyungjoo Kim +*/ + +#include "Kokkos_Core.hpp" + +#define ETI_SACADO @ETI_SACADO@ +#if (ETI_SACADO != 0) /// SACADO +#include "Kokkos_ViewFactory.hpp" +#include "Sacado.hpp" +#endif + +#if (ETI_SACADO == 0) /// double double +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__) +#elif (ETI_SACADO == 11 /* SFAD SFAD */ || ETI_SACADO == 33 /* DFAD DFAD */) +constexpr int num_deriv = 3; +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#elif (ETI_SACADO == 23) +constexpr int num_deriv = 3; +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#elif (ETI_SACADO == 20) +constexpr int num_deriv = 2; +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__) +#endif + +#include "test_02.hpp" + +int main(int argc, char *argv[]) { + + const bool verbose = (argc-1) > 0; + Kokkos::initialize(); + + Intrepid2::Test::HCURL_QUAD_In_FEM_Test02<@ETI_VALUETYPE@,@ETI_DEVICE@>(verbose); + + Kokkos::finalize(); + return 0; +} + diff --git a/packages/intrepid2/unit-test/Discretization/Basis/HCURL_QUAD_In_FEM/test_02.hpp b/packages/intrepid2/unit-test/Discretization/Basis/HCURL_QUAD_In_FEM/test_02.hpp new file mode 100644 index 000000000000..2ae8438a11ac --- /dev/null +++ b/packages/intrepid2/unit-test/Discretization/Basis/HCURL_QUAD_In_FEM/test_02.hpp @@ -0,0 +1,189 @@ +// @HEADER +// ***************************************************************************** +// Intrepid2 Package +// +// Copyright 2007 NTESS and the Intrepid2 contributors. +// SPDX-License-Identifier: BSD-3-Clause +// ***************************************************************************** +// @HEADER + +/** \file test_02.hpp + \brief Unit tests for the Intrepid2::HCURL_QUAD_In_FEM class. + \author Created by Kyungjoo Kim, Mauro Perego + */ + + +#include "Intrepid2_config.h" +#include "Kokkos_Random.hpp" +#ifdef HAVE_INTREPID2_DEBUG +#define INTREPID2_TEST_FOR_DEBUG_ABORT_OVERRIDE_TO_CONTINUE +#endif + +#include "Intrepid2_Types.hpp" +#include "Intrepid2_Utils.hpp" + +#include "Intrepid2_HCURL_QUAD_In_FEM.hpp" +#include "packages/intrepid2/unit-test/Discretization/Basis/Setup.hpp" + +namespace Intrepid2 { + + namespace Test { + + // This test evaluates the basis functions at a set of points on a batch of cells using the team-level getValues, + // and compares the results with those obtained using the classic getValues function. + template + int HCURL_QUAD_In_FEM_Test02(const bool verbose) { + + //! Setup test output stream. + Teuchos::RCP outStream = setup_output_stream( + verbose, "HCURL_QUAD_In_FEM, Test 2", {} + ); + + *outStream + << "\n" + << "===============================================================================\n" + << "| Testing Team-level Implemntation of getValues |\n" + << "===============================================================================\n"; + + using DeviceSpaceType = typename DeviceType::execution_space; + Kokkos::print_configuration(std::cout, false); + + int errorFlag = 0; + constexpr int maxOrder = 9; + try { + for (int order=1;order<=maxOrder;++order) { + using BasisType = Basis_HCURL_QUAD_In_FEM; + auto basisPtr = Teuchos::rcp(new BasisType(order)); + + const int ncells = 5, npts = 10, ndim = 2; + Kokkos::DynRankView ConstructWithLabelOutView(outputValuesA, ncells, basisPtr->getCardinality(), npts, ndim); + Kokkos::DynRankView ConstructWithLabelOutView(outputValuesB, basisPtr->getCardinality(), npts, ndim); + + Kokkos::DynRankView ConstructWithLabelOutView(outputCurlsA, ncells, basisPtr->getCardinality(), npts); + Kokkos::DynRankView ConstructWithLabelOutView(outputCurlsB, basisPtr->getCardinality(), npts); + + Kokkos::DynRankView ConstructWithLabelPointView(point, 1); + + using ScalarType = typename ScalarTraits::scalar_type; + + Kokkos::View inputPointsViewToUseRandom("inputPoints", npts*ndim*get_dimension_scalar(point)); + auto vcprop = Kokkos::common_view_alloc_prop(point); + Kokkos::DynRankView inputPoints (Kokkos::view_wrap(inputPointsViewToUseRandom.data(), vcprop), npts, ndim); + + // random values between (0,1) + Kokkos::Random_XorShift64_Pool random(13718); + Kokkos::fill_random(inputPointsViewToUseRandom, random, 1.0); + + + *outStream << "Order: " << order << ": Computing values and curls for " << ncells << " cells and " << npts << " points using team-level getValues function" <(*basisPtr); + auto basisRawPtr_device = basisPtr_device.get(); + + int scratch_space_level =1; + const int vectorSize = getVectorSizeForHierarchicalParallelism(); + Kokkos::TeamPolicy teamPolicy(ncells, Kokkos::AUTO,vectorSize); + + { //compute values + auto functor = KOKKOS_LAMBDA (typename Kokkos::TeamPolicy::member_type team_member) { + auto valsACell = Kokkos::subview(outputValuesA, team_member.league_rank(), Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL()); + basisRawPtr_device->getValues(valsACell, inputPoints, OPERATOR_VALUE, team_member, team_member.team_scratch(scratch_space_level)); + }; + + //Get the required size of the scratch space per team and per thread. + int perThreadSpaceSize(0), perTeamSpaceSize(0); + basisPtr->getScratchSpaceSize(perTeamSpaceSize,perThreadSpaceSize,inputPoints, OPERATOR_VALUE); + teamPolicy.set_scratch_size(scratch_space_level, Kokkos::PerTeam(perTeamSpaceSize), Kokkos::PerThread(perThreadSpaceSize)); + + Kokkos::parallel_for (teamPolicy,functor); + } + + { //compute curls + auto functor = KOKKOS_LAMBDA (typename Kokkos::TeamPolicy::member_type team_member) { + auto curlsACell = Kokkos::subview(outputCurlsA, team_member.league_rank(), Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL()); + basisRawPtr_device->getValues(curlsACell, inputPoints, OPERATOR_CURL, team_member, team_member.team_scratch(scratch_space_level)); + }; + + //Get the required size of the scratch space per team and per thread. + int perThreadSpaceSize(0), perTeamSpaceSize(0); + basisPtr->getScratchSpaceSize(perTeamSpaceSize,perThreadSpaceSize,inputPoints, OPERATOR_CURL); + teamPolicy.set_scratch_size(scratch_space_level, Kokkos::PerTeam(perTeamSpaceSize), Kokkos::PerThread(perThreadSpaceSize)); + + Kokkos::parallel_for (teamPolicy,functor); + } + } + + *outStream << "Order: " << order << ": Computing values and curls for " << npts << " points using high-level getValues function" <getValues(outputValuesB, inputPoints, OPERATOR_VALUE); + basisPtr->getValues(outputCurlsB, inputPoints, OPERATOR_CURL); + + *outStream << "Order: " << order << ": Comparing values and curls on host" <(); + for (size_t ic=0;ic tol) { + ++errorFlag; + std::cout << " order: " << order + << ", ic: " << ic << ", i: " << i << ", j: " << j + << ", val A: [" << outputValuesA_Host(ic,i,j,0) << ", " << outputValuesA_Host(ic,i,j,1) << "]" + << ", val B: [" << outputValuesB_Host(i,j,0) << ", " << outputValuesB_Host(i,j,1) << "]" + << ", |diff|: " << diff + << ", tol: " << tol + << std::endl; + } + } + } + + { + // compare curls + const auto outputCurlsA_Host = Kokkos::create_mirror_view(outputCurlsA); Kokkos::deep_copy(outputCurlsA_Host, outputCurlsA); + const auto outputCurlsB_Host = Kokkos::create_mirror_view(outputCurlsB); Kokkos::deep_copy(outputCurlsB_Host, outputCurlsB); + + OutValueType diff = 0; + auto tol = epsilon(); + for (size_t ic=0;ic tol) { + ++errorFlag; + std::cout << " order: " << order + << ", ic: " << ic << ", i: " << i << ", j: " << j + << ", curls A: [" << outputCurlsA_Host(ic,i,j)<<"]" + << ", curls B: [" << outputCurlsB_Host(i,j) << "]" + << ", |diff|: " << diff + << ", tol: " << tol + << std::endl; + } + } + } + } + } catch (std::exception &err) { + std::cout << "UNEXPECTED ERROR !!! ----------------------------------------------------------\n"; + std::cout << err.what() << '\n'; + std::cout << "-------------------------------------------------------------------------------" << "\n\n"; + errorFlag = -1000; + }; + + if (errorFlag != 0) + std::cout << "End Result: TEST FAILED\n"; + else + std::cout << "End Result: TEST PASSED\n"; + + return errorFlag; + } + } +} diff --git a/packages/intrepid2/unit-test/Discretization/Basis/HCURL_TET_I1_FEM/CMakeLists.txt b/packages/intrepid2/unit-test/Discretization/Basis/HCURL_TET_I1_FEM/CMakeLists.txt index 46e84774b70d..234b8e2d6fed 100644 --- a/packages/intrepid2/unit-test/Discretization/Basis/HCURL_TET_I1_FEM/CMakeLists.txt +++ b/packages/intrepid2/unit-test/Discretization/Basis/HCURL_TET_I1_FEM/CMakeLists.txt @@ -1,8 +1,13 @@ TRIBITS_INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}) + +# test +SET(Intrepid2_TEST_ETI_FILE "test_01") + # value types SET(Intrepid2_TEST_ETI_VALUETYPE_NAME "") SET(Intrepid2_TEST_ETI_VALUETYPE "") +SET(Intrepid2_TEST_ETI_SACADO "") LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE_NAME "DOUBLE") LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE "double") @@ -17,9 +22,7 @@ ENDIF() LIST(LENGTH Intrepid2_TEST_ETI_VALUETYPE_NAME ETI_VALUETYPE_COUNT) MATH(EXPR ETI_VALUETYPE_COUNT "${ETI_VALUETYPE_COUNT}-1") -# Host test -SET(Intrepid2_TEST_ETI_FILE "test_01") - +# device SET(Intrepid2_TEST_ETI_DEVICE_NAME "") SET(Intrepid2_TEST_ETI_DEVICE "") IF(Kokkos_ENABLE_SERIAL) @@ -68,3 +71,76 @@ FOREACH(I RANGE ${ETI_DEVICE_COUNT}) ENDFOREACH() ENDFOREACH() + + + +# test +SET(Intrepid2_TEST_ETI_FILE "test_02") + +# value types +SET(Intrepid2_TEST_ETI_VALUETYPE_NAME "") +SET(Intrepid2_TEST_ETI_VALUETYPE "") +SET(Intrepid2_TEST_ETI_SACADO "") + +LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE_NAME "DOUBLE_DOUBLE") +LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE "double,double") +LIST(APPEND Intrepid2_TEST_ETI_SACADO "0") + +IF (HAVE_INTREPID2_SACADO) + LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE_NAME "DFAD_DFAD") + LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE "Sacado::Fad::DFad,Sacado::Fad::DFad ") + LIST(APPEND Intrepid2_TEST_ETI_SACADO "33") +ENDIF() + +LIST(LENGTH Intrepid2_TEST_ETI_VALUETYPE_NAME ETI_VALUETYPE_COUNT) +MATH(EXPR ETI_VALUETYPE_COUNT "${ETI_VALUETYPE_COUNT}-1") + +# device +SET(Intrepid2_TEST_ETI_DEVICE_NAME "") +SET(Intrepid2_TEST_ETI_DEVICE "") +IF(Kokkos_ENABLE_SERIAL) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "Serial") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() +IF(Kokkos_ENABLE_OPENMP) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "OpenMP") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() +IF(Kokkos_ENABLE_CUDA) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "CUDA") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() +IF(Kokkos_ENABLE_HIP) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "HIP") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() + +LIST(LENGTH Intrepid2_TEST_ETI_DEVICE_NAME ETI_DEVICE_COUNT) +MATH(EXPR ETI_DEVICE_COUNT "${ETI_DEVICE_COUNT}-1") + +FOREACH(I RANGE ${ETI_DEVICE_COUNT}) + LIST(GET Intrepid2_TEST_ETI_DEVICE_NAME ${I} ETI_DEVICE_NAME) + LIST(GET Intrepid2_TEST_ETI_DEVICE ${I} ETI_DEVICE) + FOREACH(J RANGE ${ETI_VALUETYPE_COUNT}) + LIST(GET Intrepid2_TEST_ETI_VALUETYPE_NAME ${J} ETI_VALUETYPE_NAME) + LIST(GET Intrepid2_TEST_ETI_VALUETYPE ${J} ETI_VALUETYPE) + LIST(GET Intrepid2_TEST_ETI_SACADO ${J} ETI_SACADO) + FOREACH(ETI_FILE IN LISTS Intrepid2_TEST_ETI_FILE) + SET(ETI_NAME "${ETI_FILE}_${ETI_DEVICE_NAME}_${ETI_VALUETYPE_NAME}") + MESSAGE(STATUS "Generating TEST: HCURL_TET_I1_FEM ${ETI_NAME}.cpp") + CONFIGURE_FILE(eti/${ETI_FILE}_ETI.in ${ETI_NAME}.cpp) + + TRIBITS_ADD_EXECUTABLE_AND_TEST( + ${ETI_NAME} + SOURCES ${ETI_NAME}.cpp + ARGS PrintItAll + NUM_MPI_PROCS 1 + PASS_REGULAR_EXPRESSION "TEST PASSED" + ADD_DIR_TO_NAME + ) + + ENDFOREACH() + ENDFOREACH() +ENDFOREACH() + + diff --git a/packages/intrepid2/unit-test/Discretization/Basis/HCURL_TET_I1_FEM/eti/test_02_ETI.in b/packages/intrepid2/unit-test/Discretization/Basis/HCURL_TET_I1_FEM/eti/test_02_ETI.in new file mode 100644 index 000000000000..8fadc4a2c865 --- /dev/null +++ b/packages/intrepid2/unit-test/Discretization/Basis/HCURL_TET_I1_FEM/eti/test_02_ETI.in @@ -0,0 +1,52 @@ +// @HEADER +// ***************************************************************************** +// Intrepid2 Package +// +// Copyright 2007 NTESS and the Intrepid2 contributors. +// SPDX-License-Identifier: BSD-3-Clause +// ***************************************************************************** +// @HEADER + +/** \file test_01.cpp + \brief Unit test of Intrepid2::Basis_HCURL_TET_I1_FEM team-level getValues. + \author Kyungjoo Kim +*/ + +#include "Kokkos_Core.hpp" + +#define ETI_SACADO @ETI_SACADO@ +#if (ETI_SACADO != 0) /// SACADO +#include "Kokkos_ViewFactory.hpp" +#include "Sacado.hpp" +#endif + +#if (ETI_SACADO == 0) /// double double +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__) +#elif (ETI_SACADO == 11 /* SFAD SFAD */ || ETI_SACADO == 33 /* DFAD DFAD */) +constexpr int num_deriv = 3; +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#elif (ETI_SACADO == 23) +constexpr int num_deriv = 3; +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#elif (ETI_SACADO == 20) +constexpr int num_deriv = 2; +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__) +#endif + +#include "test_02.hpp" + +int main(int argc, char *argv[]) { + + const bool verbose = (argc-1) > 0; + Kokkos::initialize(); + + Intrepid2::Test::HCURL_TET_I1_FEM_Test02<@ETI_VALUETYPE@,@ETI_DEVICE@>(verbose); + + Kokkos::finalize(); + return 0; +} + diff --git a/packages/intrepid2/unit-test/Discretization/Basis/HCURL_TET_I1_FEM/test_02.hpp b/packages/intrepid2/unit-test/Discretization/Basis/HCURL_TET_I1_FEM/test_02.hpp new file mode 100644 index 000000000000..9c112664aff0 --- /dev/null +++ b/packages/intrepid2/unit-test/Discretization/Basis/HCURL_TET_I1_FEM/test_02.hpp @@ -0,0 +1,187 @@ +// @HEADER +// ***************************************************************************** +// Intrepid2 Package +// +// Copyright 2007 NTESS and the Intrepid2 contributors. +// SPDX-License-Identifier: BSD-3-Clause +// ***************************************************************************** +// @HEADER + +/** \file test_02.hpp + \brief Unit tests for the Intrepid2::HCURL_TET_I1_FEM class. + \author Created by Kyungjoo Kim, Mauro Perego + */ + + +#include "Intrepid2_config.h" +#include "Kokkos_Random.hpp" +#ifdef HAVE_INTREPID2_DEBUG +#define INTREPID2_TEST_FOR_DEBUG_ABORT_OVERRIDE_TO_CONTINUE +#endif + +#include "Intrepid2_Types.hpp" +#include "Intrepid2_Utils.hpp" + +#include "Intrepid2_HCURL_TET_I1_FEM.hpp" +#include "packages/intrepid2/unit-test/Discretization/Basis/Setup.hpp" + +namespace Intrepid2 { + + namespace Test { + + // This test evaluates the basis functions at a set of points on a batch of cells using the team-level getValues, + // and compares the results with those obtained using the classic getValues function. + template + int HCURL_TET_I1_FEM_Test02(const bool verbose) { + + //! Setup test output stream. + Teuchos::RCP outStream = setup_output_stream( + verbose, "HCURL_TET_I1_FEM, Test 2", {} + ); + + *outStream + << "\n" + << "===============================================================================\n" + << "| Testing Team-level Implemntation of getValues |\n" + << "===============================================================================\n"; + + using DeviceSpaceType = typename DeviceType::execution_space; + Kokkos::print_configuration(std::cout, false); + + int errorFlag = 0; + + try { + using BasisType = Basis_HCURL_TET_I1_FEM; + auto basisPtr = Teuchos::rcp(new BasisType()); + + const int ncells = 5, npts = 10, ndim = 3; + Kokkos::DynRankView ConstructWithLabelOutView(outputValuesA, ncells, basisPtr->getCardinality(), npts, ndim); + Kokkos::DynRankView ConstructWithLabelOutView(outputValuesB, basisPtr->getCardinality(), npts, ndim); + + Kokkos::DynRankView ConstructWithLabelOutView(outputCurlsA, ncells, basisPtr->getCardinality(), npts, ndim); + Kokkos::DynRankView ConstructWithLabelOutView(outputCurlsB, basisPtr->getCardinality(), npts, ndim); + + Kokkos::DynRankView ConstructWithLabelPointView(point, 1); + + using ScalarType = typename ScalarTraits::scalar_type; + + Kokkos::View inputPointsViewToUseRandom("inputPoints", npts*ndim*get_dimension_scalar(point)); + auto vcprop = Kokkos::common_view_alloc_prop(point); + Kokkos::DynRankView inputPoints (Kokkos::view_wrap(inputPointsViewToUseRandom.data(), vcprop), npts, ndim); + + // random values between (0,1) + Kokkos::Random_XorShift64_Pool random(13718); + Kokkos::fill_random(inputPointsViewToUseRandom, random, 1.0); + + + *outStream << "Computing values and curls for " << ncells << " cells and " << npts << " points using team-level getValues function" <(*basisPtr); + auto basisRawPtr_device = basisPtr_device.get(); + + int scratch_space_level =1; + const int vectorSize = getVectorSizeForHierarchicalParallelism(); + Kokkos::TeamPolicy teamPolicy(ncells, Kokkos::AUTO,vectorSize); + + { //compute values + auto functor = KOKKOS_LAMBDA (typename Kokkos::TeamPolicy::member_type team_member) { + auto valsACell = Kokkos::subview(outputValuesA, team_member.league_rank(), Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL()); + basisRawPtr_device->getValues(valsACell, inputPoints, OPERATOR_VALUE, team_member, team_member.team_scratch(scratch_space_level)); + }; + + //Get the required size of the scratch space per team and per thread. + int perThreadSpaceSize(0), perTeamSpaceSize(0); + basisPtr->getScratchSpaceSize(perTeamSpaceSize,perThreadSpaceSize,inputPoints, OPERATOR_VALUE); + teamPolicy.set_scratch_size(scratch_space_level, Kokkos::PerTeam(perTeamSpaceSize), Kokkos::PerThread(perThreadSpaceSize)); + + Kokkos::parallel_for (teamPolicy,functor); + } + + { //compute curls + auto functor = KOKKOS_LAMBDA (typename Kokkos::TeamPolicy::member_type team_member) { + auto curlsACell = Kokkos::subview(outputCurlsA, team_member.league_rank(), Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL()); + basisRawPtr_device->getValues(curlsACell, inputPoints, OPERATOR_CURL, team_member, team_member.team_scratch(scratch_space_level)); + }; + + //Get the required size of the scratch space per team and per thread. + int perThreadSpaceSize(0), perTeamSpaceSize(0); + basisPtr->getScratchSpaceSize(perTeamSpaceSize,perThreadSpaceSize,inputPoints, OPERATOR_CURL); + teamPolicy.set_scratch_size(scratch_space_level, Kokkos::PerTeam(perTeamSpaceSize), Kokkos::PerThread(perThreadSpaceSize)); + + Kokkos::parallel_for (teamPolicy,functor); + } + } + + *outStream << "Computing values and curls for " << npts << " points using high-level getValues function" <getValues(outputValuesB, inputPoints, OPERATOR_VALUE); + basisPtr->getValues(outputCurlsB, inputPoints, OPERATOR_CURL); + + *outStream << "Comparing values and curls on host" <(); + for (size_t ic=0;ic tol) { + ++errorFlag; + std::cout << ", ic: " << ic << ", i: " << i << ", j: " << j + << ", val A: [" << outputValuesA_Host(ic,i,j,0) << ", " << outputValuesA_Host(ic,i,j,1) << ", " << outputValuesA_Host(ic,i,j,2) << "]" + << ", val B: [" << outputValuesB_Host(i,j,0) << ", " << outputValuesB_Host(i,j,1) << ", " << outputValuesB_Host(i,j,2) << "]" + << ", |diff|: " << diff + << ", tol: " << tol + << std::endl; + } + } + } + + { + // compare curls + const auto outputCurlsA_Host = Kokkos::create_mirror_view(outputCurlsA); Kokkos::deep_copy(outputCurlsA_Host, outputCurlsA); + const auto outputCurlsB_Host = Kokkos::create_mirror_view(outputCurlsB); Kokkos::deep_copy(outputCurlsB_Host, outputCurlsB); + + OutValueType diff = 0; + auto tol = epsilon(); + for (size_t ic=0;ic tol) { + ++errorFlag; + std::cout << ", ic: " << ic << ", i: " << i << ", j: " << j + << ", curls A: [" << outputCurlsA_Host(ic,i,j,0)<< ", " << outputCurlsA_Host(ic,i,j,1) << ", " << outputCurlsA_Host(ic,i,j,2) << "]" + << ", curls B: [" << outputCurlsB_Host(i,j,0) << ", " << outputCurlsB_Host(i,j,1)<< ", " << outputCurlsB_Host(i,j,2) << "]" + << ", |diff|: " << diff + << ", tol: " << tol + << std::endl; + } + } + } + } catch (std::exception &err) { + std::cout << "UNEXPECTED ERROR !!! ----------------------------------------------------------\n"; + std::cout << err.what() << '\n'; + std::cout << "-------------------------------------------------------------------------------" << "\n\n"; + errorFlag = -1000; + }; + + if (errorFlag != 0) + std::cout << "End Result: TEST FAILED\n"; + else + std::cout << "End Result: TEST PASSED\n"; + + return errorFlag; + } + } +} diff --git a/packages/intrepid2/unit-test/Discretization/Basis/HCURL_TET_In_FEM/CMakeLists.txt b/packages/intrepid2/unit-test/Discretization/Basis/HCURL_TET_In_FEM/CMakeLists.txt index 46e4453c0d57..c40f3503ccf9 100644 --- a/packages/intrepid2/unit-test/Discretization/Basis/HCURL_TET_In_FEM/CMakeLists.txt +++ b/packages/intrepid2/unit-test/Discretization/Basis/HCURL_TET_In_FEM/CMakeLists.txt @@ -1,8 +1,13 @@ TRIBITS_INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}) + +# test +SET(Intrepid2_TEST_ETI_FILE "test_01") + # value types SET(Intrepid2_TEST_ETI_VALUETYPE_NAME "") SET(Intrepid2_TEST_ETI_VALUETYPE "") +SET(Intrepid2_TEST_ETI_SACADO "") LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE_NAME "DOUBLE_DOUBLE") LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE "double,double") @@ -32,9 +37,80 @@ ENDIF() LIST(LENGTH Intrepid2_TEST_ETI_VALUETYPE_NAME ETI_VALUETYPE_COUNT) MATH(EXPR ETI_VALUETYPE_COUNT "${ETI_VALUETYPE_COUNT}-1") +# device +SET(Intrepid2_TEST_ETI_DEVICE_NAME "") +SET(Intrepid2_TEST_ETI_DEVICE "") +IF(Kokkos_ENABLE_SERIAL) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "Serial") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() +IF(Kokkos_ENABLE_OPENMP) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "OpenMP") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() +IF(Kokkos_ENABLE_CUDA) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "CUDA") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() +IF(Kokkos_ENABLE_HIP) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "HIP") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() + +LIST(LENGTH Intrepid2_TEST_ETI_DEVICE_NAME ETI_DEVICE_COUNT) +MATH(EXPR ETI_DEVICE_COUNT "${ETI_DEVICE_COUNT}-1") + +FOREACH(I RANGE ${ETI_DEVICE_COUNT}) + LIST(GET Intrepid2_TEST_ETI_DEVICE_NAME ${I} ETI_DEVICE_NAME) + LIST(GET Intrepid2_TEST_ETI_DEVICE ${I} ETI_DEVICE) + #MESSAGE(STATUS "Generating TEST HCURL_TET_In_FEM for ${ETI_DEVICE_NAME} with ${ETI_DEVICE}") + FOREACH(J RANGE ${ETI_VALUETYPE_COUNT}) + LIST(GET Intrepid2_TEST_ETI_VALUETYPE_NAME ${J} ETI_VALUETYPE_NAME) + LIST(GET Intrepid2_TEST_ETI_VALUETYPE ${J} ETI_VALUETYPE) + LIST(GET Intrepid2_TEST_ETI_SACADO ${J} ETI_SACADO) + FOREACH(ETI_FILE IN LISTS Intrepid2_TEST_ETI_FILE) + SET(ETI_NAME "${ETI_FILE}_${ETI_DEVICE_NAME}_${ETI_VALUETYPE_NAME}") + MESSAGE(STATUS "Generating TEST: HCURL_TET_In_FEM ${ETI_NAME}.cpp") + CONFIGURE_FILE(eti/${ETI_FILE}_ETI.in ${ETI_NAME}.cpp) + + TRIBITS_ADD_EXECUTABLE_AND_TEST( + ${ETI_NAME} + SOURCES ${ETI_NAME}.cpp + ARGS PrintItAll + NUM_MPI_PROCS 1 + PASS_REGULAR_EXPRESSION "TEST PASSED" + ADD_DIR_TO_NAME + ) + + ENDFOREACH() + ENDFOREACH() +ENDFOREACH() + + + + # test -SET(Intrepid2_TEST_ETI_FILE "test_01") +SET(Intrepid2_TEST_ETI_FILE "test_02") +# value types +SET(Intrepid2_TEST_ETI_VALUETYPE_NAME "") +SET(Intrepid2_TEST_ETI_VALUETYPE "") +SET(Intrepid2_TEST_ETI_SACADO "") + +LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE_NAME "DOUBLE_DOUBLE") +LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE "double,double") +LIST(APPEND Intrepid2_TEST_ETI_SACADO "0") + +IF (HAVE_INTREPID2_SACADO) + LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE_NAME "DFAD_DFAD") + LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE "Sacado::Fad::DFad,Sacado::Fad::DFad ") + LIST(APPEND Intrepid2_TEST_ETI_SACADO "33") +ENDIF() + +LIST(LENGTH Intrepid2_TEST_ETI_VALUETYPE_NAME ETI_VALUETYPE_COUNT) +MATH(EXPR ETI_VALUETYPE_COUNT "${ETI_VALUETYPE_COUNT}-1") + +# device SET(Intrepid2_TEST_ETI_DEVICE_NAME "") SET(Intrepid2_TEST_ETI_DEVICE "") IF(Kokkos_ENABLE_SERIAL) @@ -60,7 +136,6 @@ MATH(EXPR ETI_DEVICE_COUNT "${ETI_DEVICE_COUNT}-1") FOREACH(I RANGE ${ETI_DEVICE_COUNT}) LIST(GET Intrepid2_TEST_ETI_DEVICE_NAME ${I} ETI_DEVICE_NAME) LIST(GET Intrepid2_TEST_ETI_DEVICE ${I} ETI_DEVICE) - #MESSAGE(STATUS "Generating TEST HCURL_TET_In_FEM for ${ETI_DEVICE_NAME} with ${ETI_DEVICE}") FOREACH(J RANGE ${ETI_VALUETYPE_COUNT}) LIST(GET Intrepid2_TEST_ETI_VALUETYPE_NAME ${J} ETI_VALUETYPE_NAME) LIST(GET Intrepid2_TEST_ETI_VALUETYPE ${J} ETI_VALUETYPE) diff --git a/packages/intrepid2/unit-test/Discretization/Basis/HCURL_TET_In_FEM/eti/test_02_ETI.in b/packages/intrepid2/unit-test/Discretization/Basis/HCURL_TET_In_FEM/eti/test_02_ETI.in new file mode 100644 index 000000000000..278f9326b54c --- /dev/null +++ b/packages/intrepid2/unit-test/Discretization/Basis/HCURL_TET_In_FEM/eti/test_02_ETI.in @@ -0,0 +1,52 @@ +// @HEADER +// ***************************************************************************** +// Intrepid2 Package +// +// Copyright 2007 NTESS and the Intrepid2 contributors. +// SPDX-License-Identifier: BSD-3-Clause +// ***************************************************************************** +// @HEADER + +/** \file test_01.cpp + \brief Unit test of Intrepid2::Basis_HCURL_TET_In_FEM team-level getValues. + \author Kyungjoo Kim +*/ + +#include "Kokkos_Core.hpp" + +#define ETI_SACADO @ETI_SACADO@ +#if (ETI_SACADO != 0) /// SACADO +#include "Kokkos_ViewFactory.hpp" +#include "Sacado.hpp" +#endif + +#if (ETI_SACADO == 0) /// double double +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__) +#elif (ETI_SACADO == 11 /* SFAD SFAD */ || ETI_SACADO == 33 /* DFAD DFAD */) +constexpr int num_deriv = 3; +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#elif (ETI_SACADO == 23) +constexpr int num_deriv = 3; +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#elif (ETI_SACADO == 20) +constexpr int num_deriv = 2; +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__) +#endif + +#include "test_02.hpp" + +int main(int argc, char *argv[]) { + + const bool verbose = (argc-1) > 0; + Kokkos::initialize(); + + Intrepid2::Test::HCURL_TET_In_FEM_Test02<@ETI_VALUETYPE@,@ETI_DEVICE@>(verbose); + + Kokkos::finalize(); + return 0; +} + diff --git a/packages/intrepid2/unit-test/Discretization/Basis/HCURL_TET_In_FEM/test_02.hpp b/packages/intrepid2/unit-test/Discretization/Basis/HCURL_TET_In_FEM/test_02.hpp new file mode 100644 index 000000000000..c06ec5688c39 --- /dev/null +++ b/packages/intrepid2/unit-test/Discretization/Basis/HCURL_TET_In_FEM/test_02.hpp @@ -0,0 +1,204 @@ +// @HEADER +// ***************************************************************************** +// Intrepid2 Package +// +// Copyright 2007 NTESS and the Intrepid2 contributors. +// SPDX-License-Identifier: BSD-3-Clause +// ***************************************************************************** +// @HEADER + +/** \file test_02.hpp + \brief Unit tests for the Intrepid2::HCURL_TET_In_FEM class. + \author Created by Kyungjoo Kim, Mauro Perego + */ + + +#include "Intrepid2_config.h" +#include "Kokkos_Random.hpp" +#ifdef HAVE_INTREPID2_DEBUG +#define INTREPID2_TEST_FOR_DEBUG_ABORT_OVERRIDE_TO_CONTINUE +#endif + +#include "Intrepid2_Types.hpp" +#include "Intrepid2_Utils.hpp" + +#include "Intrepid2_HCURL_TET_In_FEM.hpp" +#include "packages/intrepid2/unit-test/Discretization/Basis/Setup.hpp" + +namespace Intrepid2 { + + namespace Test { + + // This test evaluates the basis functions at a set of points on a batch of cells using the team-level getValues, + // and compares the results with those obtained using the classic getValues function. + template + int HCURL_TET_In_FEM_Test02(const bool verbose) { + + //! Setup test output stream. + Teuchos::RCP outStream = setup_output_stream( + verbose, "HCURL_TET_In_FEM, Test 2", {} + ); + + *outStream + << "\n" + << "===============================================================================\n" + << "| Testing Team-level Implemntation of getValues |\n" + << "===============================================================================\n"; + + using DeviceSpaceType = typename DeviceType::execution_space; + Kokkos::print_configuration(std::cout, false); + + int errorFlag = 0; + constexpr int maxOrder = 7; + + try { + for (int order=1;order <= maxOrder;++order) { + using BasisType = Basis_HCURL_TET_In_FEM; + auto basisPtr = Teuchos::rcp(new BasisType(order)); + + const int ncells = 5, npts = 10, ndim = 3; + Kokkos::DynRankView ConstructWithLabelOutView(outputValuesA, ncells, basisPtr->getCardinality(), npts, ndim); + Kokkos::DynRankView ConstructWithLabelOutView(outputValuesB, basisPtr->getCardinality(), npts, ndim); + + Kokkos::DynRankView ConstructWithLabelOutView(outputCurlsA, ncells, basisPtr->getCardinality(), npts, ndim); + Kokkos::DynRankView ConstructWithLabelOutView(outputCurlsB, basisPtr->getCardinality(), npts, ndim); + + Kokkos::DynRankView ConstructWithLabelPointView(point, 1); + + using ScalarType = typename ScalarTraits::scalar_type; + + Kokkos::View inputPointsViewToUseRandom("inputPoints", npts*ndim*get_dimension_scalar(point)); + auto vcprop = Kokkos::common_view_alloc_prop(point); + Kokkos::DynRankView inputPoints (Kokkos::view_wrap(inputPointsViewToUseRandom.data(), vcprop), npts, ndim); + + // random values between (0,1) + Kokkos::Random_XorShift64_Pool random(13718); + Kokkos::fill_random(inputPointsViewToUseRandom, random, 1.0); + + + *outStream << "Order: " << order << ": Computing values and curls for " << ncells << " cells and " << npts << " points using team-level getValues function" <(*basisPtr); + auto basisRawPtr_device = basisPtr_device.get(); + + int scratch_space_level =1; + const int vectorSize = getVectorSizeForHierarchicalParallelism(); + Kokkos::TeamPolicy teamPolicy(ncells, Kokkos::AUTO,vectorSize); + + { //compute values + auto functor = KOKKOS_LAMBDA (typename Kokkos::TeamPolicy::member_type team_member) { + auto valsACell = Kokkos::subview(outputValuesA, team_member.league_rank(), Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL()); + basisRawPtr_device->getValues(valsACell, inputPoints, OPERATOR_VALUE, team_member, team_member.team_scratch(scratch_space_level)); + }; + + // avoid using a team size larger than needed, to reduce allocated scrach space memory + ordinal_type team_size = teamPolicy.team_size_recommended(functor, Kokkos::ParallelForTag()); + *outStream << "Max Recommended team size: " << team_size << ", Requested team size: " << npts <(ncells, team_size,vectorSize); + + //Get the required size of the scratch space per team and per thread. + int perThreadSpaceSize(0), perTeamSpaceSize(0); + basisPtr->getScratchSpaceSize(perTeamSpaceSize,perThreadSpaceSize,inputPoints, OPERATOR_VALUE); + teamPolicy.set_scratch_size(scratch_space_level, Kokkos::PerTeam(perTeamSpaceSize), Kokkos::PerThread(perThreadSpaceSize)); + + Kokkos::parallel_for (teamPolicy,functor); + } + + { //compute curls + auto functor = KOKKOS_LAMBDA (typename Kokkos::TeamPolicy::member_type team_member) { + auto curlsACell = Kokkos::subview(outputCurlsA, team_member.league_rank(), Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL()); + basisRawPtr_device->getValues(curlsACell, inputPoints, OPERATOR_CURL, team_member, team_member.team_scratch(scratch_space_level)); + }; + + // avoid using a team size larger than needed, to reduce allocated scrach space memory + ordinal_type team_size = teamPolicy.team_size_recommended(functor, Kokkos::ParallelForTag()); + *outStream << "Max Recommended team size: " << team_size << ", Requested team size: " << npts <(ncells, team_size,vectorSize); + + //Get the required size of the scratch space per team and per thread. + int perThreadSpaceSize(0), perTeamSpaceSize(0); + basisPtr->getScratchSpaceSize(perTeamSpaceSize,perThreadSpaceSize,inputPoints, OPERATOR_CURL); + teamPolicy.set_scratch_size(scratch_space_level, Kokkos::PerTeam(perTeamSpaceSize), Kokkos::PerThread(perThreadSpaceSize)); + + Kokkos::parallel_for (teamPolicy,functor); + } + } + + *outStream << "Order: " << order << ": Computing values and curls for " << npts << " points using high-level getValues function" <getValues(outputValuesB, inputPoints, OPERATOR_VALUE); + basisPtr->getValues(outputCurlsB, inputPoints, OPERATOR_CURL); + + *outStream << "Order: " << order << ": Comparing values and curls on host" <(); + for (size_t ic=0;ic tol) { + ++errorFlag; + std::cout << " order: " << order + << ", ic: " << ic << ", i: " << i << ", j: " << j + << ", val A: [" << outputValuesA_Host(ic,i,j,0) << ", " << outputValuesA_Host(ic,i,j,1) << "]" + << ", val B: [" << outputValuesB_Host(i,j,0) << ", " << outputValuesB_Host(i,j,1) << "]" + << ", |diff|: " << diff + << ", tol: " << tol + << std::endl; + } + } + } + + { + // compare curls + const auto outputCurlsA_Host = Kokkos::create_mirror_view(outputCurlsA); Kokkos::deep_copy(outputCurlsA_Host, outputCurlsA); + const auto outputCurlsB_Host = Kokkos::create_mirror_view(outputCurlsB); Kokkos::deep_copy(outputCurlsB_Host, outputCurlsB); + + OutValueType diff = 0; + auto tol = epsilon(); + for (size_t ic=0;ic tol) { + ++errorFlag; + std::cout << " order: " << order + << ", ic: " << ic << ", i: " << i << ", j: " << j + << ", curls A: [" << outputCurlsA_Host(ic,i,j,0)<< ", " << outputCurlsA_Host(ic,i,j,1) << ", " << outputCurlsA_Host(ic,i,j,2) << "]" + << ", curls B: [" << outputCurlsB_Host(i,j,0) << ", " << outputCurlsB_Host(i,j,1)<< ", " << outputCurlsB_Host(i,j,2) << "]" + << ", |diff|: " << diff + << ", tol: " << tol + << std::endl; + } + } + } + } + } catch (std::exception &err) { + std::cout << "UNEXPECTED ERROR !!! ----------------------------------------------------------\n"; + std::cout << err.what() << '\n'; + std::cout << "-------------------------------------------------------------------------------" << "\n\n"; + errorFlag = -1000; + }; + + if (errorFlag != 0) + std::cout << "End Result: TEST FAILED\n"; + else + std::cout << "End Result: TEST PASSED\n"; + + return errorFlag; + } + } +} diff --git a/packages/intrepid2/unit-test/Discretization/Basis/HCURL_TRI_I1_FEM/CMakeLists.txt b/packages/intrepid2/unit-test/Discretization/Basis/HCURL_TRI_I1_FEM/CMakeLists.txt index 2bf7bfdee691..b87adda0a338 100644 --- a/packages/intrepid2/unit-test/Discretization/Basis/HCURL_TRI_I1_FEM/CMakeLists.txt +++ b/packages/intrepid2/unit-test/Discretization/Basis/HCURL_TRI_I1_FEM/CMakeLists.txt @@ -1,8 +1,13 @@ TRIBITS_INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}) + +# test +SET(Intrepid2_TEST_ETI_FILE "test_01") + # value types SET(Intrepid2_TEST_ETI_VALUETYPE_NAME "") SET(Intrepid2_TEST_ETI_VALUETYPE "") +SET(Intrepid2_TEST_ETI_SACADO "") LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE_NAME "DOUBLE") LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE "double") @@ -17,9 +22,7 @@ ENDIF() LIST(LENGTH Intrepid2_TEST_ETI_VALUETYPE_NAME ETI_VALUETYPE_COUNT) MATH(EXPR ETI_VALUETYPE_COUNT "${ETI_VALUETYPE_COUNT}-1") -# Host test -SET(Intrepid2_TEST_ETI_FILE "test_01") - +# device SET(Intrepid2_TEST_ETI_DEVICE_NAME "") SET(Intrepid2_TEST_ETI_DEVICE "") IF(Kokkos_ENABLE_SERIAL) @@ -68,3 +71,75 @@ FOREACH(I RANGE ${ETI_DEVICE_COUNT}) ENDFOREACH() ENDFOREACH() + + + +# test +SET(Intrepid2_TEST_ETI_FILE "test_02") + +# value types +SET(Intrepid2_TEST_ETI_VALUETYPE_NAME "") +SET(Intrepid2_TEST_ETI_VALUETYPE "") +SET(Intrepid2_TEST_ETI_SACADO "") + +LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE_NAME "DOUBLE_DOUBLE") +LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE "double,double") +LIST(APPEND Intrepid2_TEST_ETI_SACADO "0") + +IF (HAVE_INTREPID2_SACADO) + LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE_NAME "DFAD_DFAD") + LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE "Sacado::Fad::DFad,Sacado::Fad::DFad ") + LIST(APPEND Intrepid2_TEST_ETI_SACADO "33") +ENDIF() + +LIST(LENGTH Intrepid2_TEST_ETI_VALUETYPE_NAME ETI_VALUETYPE_COUNT) +MATH(EXPR ETI_VALUETYPE_COUNT "${ETI_VALUETYPE_COUNT}-1") + +# device +SET(Intrepid2_TEST_ETI_DEVICE_NAME "") +SET(Intrepid2_TEST_ETI_DEVICE "") +IF(Kokkos_ENABLE_SERIAL) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "Serial") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() +IF(Kokkos_ENABLE_OPENMP) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "OpenMP") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() +IF(Kokkos_ENABLE_CUDA) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "CUDA") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() +IF(Kokkos_ENABLE_HIP) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "HIP") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() + +LIST(LENGTH Intrepid2_TEST_ETI_DEVICE_NAME ETI_DEVICE_COUNT) +MATH(EXPR ETI_DEVICE_COUNT "${ETI_DEVICE_COUNT}-1") + +FOREACH(I RANGE ${ETI_DEVICE_COUNT}) + LIST(GET Intrepid2_TEST_ETI_DEVICE_NAME ${I} ETI_DEVICE_NAME) + LIST(GET Intrepid2_TEST_ETI_DEVICE ${I} ETI_DEVICE) + FOREACH(J RANGE ${ETI_VALUETYPE_COUNT}) + LIST(GET Intrepid2_TEST_ETI_VALUETYPE_NAME ${J} ETI_VALUETYPE_NAME) + LIST(GET Intrepid2_TEST_ETI_VALUETYPE ${J} ETI_VALUETYPE) + LIST(GET Intrepid2_TEST_ETI_SACADO ${J} ETI_SACADO) + FOREACH(ETI_FILE IN LISTS Intrepid2_TEST_ETI_FILE) + SET(ETI_NAME "${ETI_FILE}_${ETI_DEVICE_NAME}_${ETI_VALUETYPE_NAME}") + MESSAGE(STATUS "Generating TEST: HCURL_TRI_I1_FEM ${ETI_NAME}.cpp") + CONFIGURE_FILE(eti/${ETI_FILE}_ETI.in ${ETI_NAME}.cpp) + + TRIBITS_ADD_EXECUTABLE_AND_TEST( + ${ETI_NAME} + SOURCES ${ETI_NAME}.cpp + ARGS PrintItAll + NUM_MPI_PROCS 1 + PASS_REGULAR_EXPRESSION "TEST PASSED" + ADD_DIR_TO_NAME + ) + + ENDFOREACH() + ENDFOREACH() +ENDFOREACH() + diff --git a/packages/intrepid2/unit-test/Discretization/Basis/HCURL_TRI_I1_FEM/eti/test_02_ETI.in b/packages/intrepid2/unit-test/Discretization/Basis/HCURL_TRI_I1_FEM/eti/test_02_ETI.in new file mode 100644 index 000000000000..2fe8396db2d1 --- /dev/null +++ b/packages/intrepid2/unit-test/Discretization/Basis/HCURL_TRI_I1_FEM/eti/test_02_ETI.in @@ -0,0 +1,52 @@ +// @HEADER +// ***************************************************************************** +// Intrepid2 Package +// +// Copyright 2007 NTESS and the Intrepid2 contributors. +// SPDX-License-Identifier: BSD-3-Clause +// ***************************************************************************** +// @HEADER + +/** \file test_01.cpp + \brief Unit test of Intrepid2::Basis_HCURL_TRI_I1_FEM team-level getValues. + \author Kyungjoo Kim +*/ + +#include "Kokkos_Core.hpp" + +#define ETI_SACADO @ETI_SACADO@ +#if (ETI_SACADO != 0) /// SACADO +#include "Kokkos_ViewFactory.hpp" +#include "Sacado.hpp" +#endif + +#if (ETI_SACADO == 0) /// double double +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__) +#elif (ETI_SACADO == 11 /* SFAD SFAD */ || ETI_SACADO == 33 /* DFAD DFAD */) +constexpr int num_deriv = 3; +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#elif (ETI_SACADO == 23) +constexpr int num_deriv = 3; +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#elif (ETI_SACADO == 20) +constexpr int num_deriv = 2; +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__) +#endif + +#include "test_02.hpp" + +int main(int argc, char *argv[]) { + + const bool verbose = (argc-1) > 0; + Kokkos::initialize(); + + Intrepid2::Test::HCURL_TRI_I1_FEM_Test02<@ETI_VALUETYPE@,@ETI_DEVICE@>(verbose); + + Kokkos::finalize(); + return 0; +} + diff --git a/packages/intrepid2/unit-test/Discretization/Basis/HCURL_TRI_I1_FEM/test_02.hpp b/packages/intrepid2/unit-test/Discretization/Basis/HCURL_TRI_I1_FEM/test_02.hpp new file mode 100644 index 000000000000..3b255303dd1f --- /dev/null +++ b/packages/intrepid2/unit-test/Discretization/Basis/HCURL_TRI_I1_FEM/test_02.hpp @@ -0,0 +1,185 @@ +// @HEADER +// ***************************************************************************** +// Intrepid2 Package +// +// Copyright 2007 NTESS and the Intrepid2 contributors. +// SPDX-License-Identifier: BSD-3-Clause +// ***************************************************************************** +// @HEADER + +/** \file test_02.hpp + \brief Unit tests for the Intrepid2::HCURL_TRI_I1_FEM class. + \author Created by Kyungjoo Kim, Mauro Perego + */ + + +#include "Intrepid2_config.h" +#include "Kokkos_Random.hpp" +#ifdef HAVE_INTREPID2_DEBUG +#define INTREPID2_TEST_FOR_DEBUG_ABORT_OVERRIDE_TO_CONTINUE +#endif + +#include "Intrepid2_Types.hpp" +#include "Intrepid2_Utils.hpp" + +#include "Intrepid2_HCURL_TRI_I1_FEM.hpp" +#include "packages/intrepid2/unit-test/Discretization/Basis/Setup.hpp" + +namespace Intrepid2 { + + namespace Test { + + // This test evaluates the basis functions at a set of points on a batch of cells using the team-level getValues, + // and compares the results with those obtained using the classic getValues function. + template + int HCURL_TRI_I1_FEM_Test02(const bool verbose) { + + //! Setup test output stream. + Teuchos::RCP outStream = setup_output_stream( + verbose, "HCURL_TRI_I1_FEM, Test 2", {} + ); + + *outStream + << "\n" + << "===============================================================================\n" + << "| Testing Team-level Implemntation of getValues |\n" + << "===============================================================================\n"; + + using DeviceSpaceType = typename DeviceType::execution_space; + Kokkos::print_configuration(std::cout, false); + + int errorFlag = 0; + + try { + using BasisType = Basis_HCURL_TRI_I1_FEM; + auto basisPtr = Teuchos::rcp(new BasisType()); + + const int ncells = 5, npts = 10, ndim = 2; + Kokkos::DynRankView ConstructWithLabelOutView(outputValuesA, ncells, basisPtr->getCardinality(), npts, ndim); + Kokkos::DynRankView ConstructWithLabelOutView(outputValuesB, basisPtr->getCardinality(), npts, ndim); + + Kokkos::DynRankView ConstructWithLabelOutView(outputCurlsA, ncells, basisPtr->getCardinality(), npts); + Kokkos::DynRankView ConstructWithLabelOutView(outputCurlsB, basisPtr->getCardinality(), npts); + + Kokkos::DynRankView ConstructWithLabelPointView(point, 1); + + using ScalarType = typename ScalarTraits::scalar_type; + + Kokkos::View inputPointsViewToUseRandom("inputPoints", npts*ndim*get_dimension_scalar(point)); + auto vcprop = Kokkos::common_view_alloc_prop(point); + Kokkos::DynRankView inputPoints (Kokkos::view_wrap(inputPointsViewToUseRandom.data(), vcprop), npts, ndim); + + // random values between (0,1) + Kokkos::Random_XorShift64_Pool random(13718); + Kokkos::fill_random(inputPointsViewToUseRandom, random, 1.0); + + + *outStream << "Computing values and curls for " << ncells << " cells and " << npts << " points using team-level getValues function" <(*basisPtr); + auto basisRawPtr_device = basisPtr_device.get(); + + int scratch_space_level =1; + const int vectorSize = getVectorSizeForHierarchicalParallelism(); + Kokkos::TeamPolicy teamPolicy(ncells, Kokkos::AUTO,vectorSize); + + { //compute values + auto functor = KOKKOS_LAMBDA (typename Kokkos::TeamPolicy::member_type team_member) { + auto valsACell = Kokkos::subview(outputValuesA, team_member.league_rank(), Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL()); + basisRawPtr_device->getValues(valsACell, inputPoints, OPERATOR_VALUE, team_member, team_member.team_scratch(scratch_space_level)); + }; + + //Get the required size of the scratch space per team and per thread. + int perThreadSpaceSize(0), perTeamSpaceSize(0); + basisPtr->getScratchSpaceSize(perTeamSpaceSize,perThreadSpaceSize,inputPoints, OPERATOR_VALUE); + teamPolicy.set_scratch_size(scratch_space_level, Kokkos::PerTeam(perTeamSpaceSize), Kokkos::PerThread(perThreadSpaceSize)); + + Kokkos::parallel_for (teamPolicy,functor); + } + + { //compute curls + auto functor = KOKKOS_LAMBDA (typename Kokkos::TeamPolicy::member_type team_member) { + auto curlsACell = Kokkos::subview(outputCurlsA, team_member.league_rank(), Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL()); + basisRawPtr_device->getValues(curlsACell, inputPoints, OPERATOR_CURL, team_member, team_member.team_scratch(scratch_space_level)); + }; + + //Get the required size of the scratch space per team and per thread. + int perThreadSpaceSize(0), perTeamSpaceSize(0); + basisPtr->getScratchSpaceSize(perTeamSpaceSize,perThreadSpaceSize,inputPoints, OPERATOR_CURL); + teamPolicy.set_scratch_size(scratch_space_level, Kokkos::PerTeam(perTeamSpaceSize), Kokkos::PerThread(perThreadSpaceSize)); + + Kokkos::parallel_for (teamPolicy,functor); + } + } + + *outStream << "Computing values and curls for " << npts << " points using high-level getValues function" <getValues(outputValuesB, inputPoints, OPERATOR_VALUE); + basisPtr->getValues(outputCurlsB, inputPoints, OPERATOR_CURL); + + *outStream << "Comparing values and curls on host" <(); + for (size_t ic=0;ic tol) { + ++errorFlag; + std::cout << ", ic: " << ic << ", i: " << i << ", j: " << j + << ", val A: [" << outputValuesA_Host(ic,i,j,0) << ", " << outputValuesA_Host(ic,i,j,1) << "]" + << ", val B: [" << outputValuesB_Host(i,j,0) << ", " << outputValuesB_Host(i,j,1) << "]" + << ", |diff|: " << diff + << ", tol: " << tol + << std::endl; + } + } + } + + { + // compare curls + const auto outputCurlsA_Host = Kokkos::create_mirror_view(outputCurlsA); Kokkos::deep_copy(outputCurlsA_Host, outputCurlsA); + const auto outputCurlsB_Host = Kokkos::create_mirror_view(outputCurlsB); Kokkos::deep_copy(outputCurlsB_Host, outputCurlsB); + + OutValueType diff = 0; + auto tol = epsilon(); + for (size_t ic=0;ic tol) { + ++errorFlag; + std::cout << ", ic: " << ic << ", i: " << i << ", j: " << j + << ", curls A: [" << outputCurlsA_Host(ic,i,j)<<"]" + << ", curls B: [" << outputCurlsB_Host(i,j) << "]" + << ", |diff|: " << diff + << ", tol: " << tol + << std::endl; + } + } + } + } catch (std::exception &err) { + std::cout << "UNEXPECTED ERROR !!! ----------------------------------------------------------\n"; + std::cout << err.what() << '\n'; + std::cout << "-------------------------------------------------------------------------------" << "\n\n"; + errorFlag = -1000; + }; + + if (errorFlag != 0) + std::cout << "End Result: TEST FAILED\n"; + else + std::cout << "End Result: TEST PASSED\n"; + + return errorFlag; + } + } +} diff --git a/packages/intrepid2/unit-test/Discretization/Basis/HCURL_TRI_In_FEM/CMakeLists.txt b/packages/intrepid2/unit-test/Discretization/Basis/HCURL_TRI_In_FEM/CMakeLists.txt index 49f5b786efc9..ec30d2154004 100644 --- a/packages/intrepid2/unit-test/Discretization/Basis/HCURL_TRI_In_FEM/CMakeLists.txt +++ b/packages/intrepid2/unit-test/Discretization/Basis/HCURL_TRI_In_FEM/CMakeLists.txt @@ -1,8 +1,13 @@ TRIBITS_INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}) + +# test +SET(Intrepid2_TEST_ETI_FILE "test_01") + # value types SET(Intrepid2_TEST_ETI_VALUETYPE_NAME "") SET(Intrepid2_TEST_ETI_VALUETYPE "") +SET(Intrepid2_TEST_ETI_SACADO "") LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE_NAME "DOUBLE_DOUBLE") LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE "double,double") @@ -32,9 +37,80 @@ ENDIF() LIST(LENGTH Intrepid2_TEST_ETI_VALUETYPE_NAME ETI_VALUETYPE_COUNT) MATH(EXPR ETI_VALUETYPE_COUNT "${ETI_VALUETYPE_COUNT}-1") +# device +SET(Intrepid2_TEST_ETI_DEVICE_NAME "") +SET(Intrepid2_TEST_ETI_DEVICE "") +IF(Kokkos_ENABLE_SERIAL) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "Serial") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() +IF(Kokkos_ENABLE_OPENMP) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "OpenMP") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() +IF(Kokkos_ENABLE_CUDA) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "CUDA") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() +IF(Kokkos_ENABLE_HIP) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "HIP") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() + +LIST(LENGTH Intrepid2_TEST_ETI_DEVICE_NAME ETI_DEVICE_COUNT) +MATH(EXPR ETI_DEVICE_COUNT "${ETI_DEVICE_COUNT}-1") + +FOREACH(I RANGE ${ETI_DEVICE_COUNT}) + LIST(GET Intrepid2_TEST_ETI_DEVICE_NAME ${I} ETI_DEVICE_NAME) + LIST(GET Intrepid2_TEST_ETI_DEVICE ${I} ETI_DEVICE) + #MESSAGE(STATUS "Generating TEST HCURL_TRI_In_FEM for ${ETI_DEVICE_NAME} with ${ETI_DEVICE}") + FOREACH(J RANGE ${ETI_VALUETYPE_COUNT}) + LIST(GET Intrepid2_TEST_ETI_VALUETYPE_NAME ${J} ETI_VALUETYPE_NAME) + LIST(GET Intrepid2_TEST_ETI_VALUETYPE ${J} ETI_VALUETYPE) + LIST(GET Intrepid2_TEST_ETI_SACADO ${J} ETI_SACADO) + FOREACH(ETI_FILE IN LISTS Intrepid2_TEST_ETI_FILE) + SET(ETI_NAME "${ETI_FILE}_${ETI_DEVICE_NAME}_${ETI_VALUETYPE_NAME}") + MESSAGE(STATUS "Generating TEST: HCURL_TRI_In_FEM ${ETI_NAME}.cpp") + CONFIGURE_FILE(eti/${ETI_FILE}_ETI.in ${ETI_NAME}.cpp) + + TRIBITS_ADD_EXECUTABLE_AND_TEST( + ${ETI_NAME} + SOURCES ${ETI_NAME}.cpp + ARGS PrintItAll + NUM_MPI_PROCS 1 + PASS_REGULAR_EXPRESSION "TEST PASSED" + ADD_DIR_TO_NAME + ) + + ENDFOREACH() + ENDFOREACH() +ENDFOREACH() + + + + # test -SET(Intrepid2_TEST_ETI_FILE "test_01") +SET(Intrepid2_TEST_ETI_FILE "test_02") +# value types +SET(Intrepid2_TEST_ETI_VALUETYPE_NAME "") +SET(Intrepid2_TEST_ETI_VALUETYPE "") +SET(Intrepid2_TEST_ETI_SACADO "") + +LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE_NAME "DOUBLE_DOUBLE") +LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE "double,double") +LIST(APPEND Intrepid2_TEST_ETI_SACADO "0") + +IF (HAVE_INTREPID2_SACADO) + LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE_NAME "DFAD_DFAD") + LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE "Sacado::Fad::DFad,Sacado::Fad::DFad ") + LIST(APPEND Intrepid2_TEST_ETI_SACADO "33") +ENDIF() + +LIST(LENGTH Intrepid2_TEST_ETI_VALUETYPE_NAME ETI_VALUETYPE_COUNT) +MATH(EXPR ETI_VALUETYPE_COUNT "${ETI_VALUETYPE_COUNT}-1") + +# device SET(Intrepid2_TEST_ETI_DEVICE_NAME "") SET(Intrepid2_TEST_ETI_DEVICE "") IF(Kokkos_ENABLE_SERIAL) @@ -60,7 +136,6 @@ MATH(EXPR ETI_DEVICE_COUNT "${ETI_DEVICE_COUNT}-1") FOREACH(I RANGE ${ETI_DEVICE_COUNT}) LIST(GET Intrepid2_TEST_ETI_DEVICE_NAME ${I} ETI_DEVICE_NAME) LIST(GET Intrepid2_TEST_ETI_DEVICE ${I} ETI_DEVICE) - #MESSAGE(STATUS "Generating TEST HCURL_TRI_In_FEM for ${ETI_DEVICE_NAME} with ${ETI_DEVICE}") FOREACH(J RANGE ${ETI_VALUETYPE_COUNT}) LIST(GET Intrepid2_TEST_ETI_VALUETYPE_NAME ${J} ETI_VALUETYPE_NAME) LIST(GET Intrepid2_TEST_ETI_VALUETYPE ${J} ETI_VALUETYPE) diff --git a/packages/intrepid2/unit-test/Discretization/Basis/HCURL_TRI_In_FEM/eti/test_02_ETI.in b/packages/intrepid2/unit-test/Discretization/Basis/HCURL_TRI_In_FEM/eti/test_02_ETI.in new file mode 100644 index 000000000000..509fff60809f --- /dev/null +++ b/packages/intrepid2/unit-test/Discretization/Basis/HCURL_TRI_In_FEM/eti/test_02_ETI.in @@ -0,0 +1,52 @@ +// @HEADER +// ***************************************************************************** +// Intrepid2 Package +// +// Copyright 2007 NTESS and the Intrepid2 contributors. +// SPDX-License-Identifier: BSD-3-Clause +// ***************************************************************************** +// @HEADER + +/** \file test_01.cpp + \brief Unit test of Intrepid2::Basis_HCURL_TRI_In_FEM team-level getValues. + \author Kyungjoo Kim +*/ + +#include "Kokkos_Core.hpp" + +#define ETI_SACADO @ETI_SACADO@ +#if (ETI_SACADO != 0) /// SACADO +#include "Kokkos_ViewFactory.hpp" +#include "Sacado.hpp" +#endif + +#if (ETI_SACADO == 0) /// double double +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__) +#elif (ETI_SACADO == 11 /* SFAD SFAD */ || ETI_SACADO == 33 /* DFAD DFAD */) +constexpr int num_deriv = 3; +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#elif (ETI_SACADO == 23) +constexpr int num_deriv = 3; +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#elif (ETI_SACADO == 20) +constexpr int num_deriv = 2; +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__) +#endif + +#include "test_02.hpp" + +int main(int argc, char *argv[]) { + + const bool verbose = (argc-1) > 0; + Kokkos::initialize(); + + Intrepid2::Test::HCURL_TRI_In_FEM_Test02<@ETI_VALUETYPE@,@ETI_DEVICE@>(verbose); + + Kokkos::finalize(); + return 0; +} + diff --git a/packages/intrepid2/unit-test/Discretization/Basis/HCURL_TRI_In_FEM/test_02.hpp b/packages/intrepid2/unit-test/Discretization/Basis/HCURL_TRI_In_FEM/test_02.hpp new file mode 100644 index 000000000000..aa19ce2114e0 --- /dev/null +++ b/packages/intrepid2/unit-test/Discretization/Basis/HCURL_TRI_In_FEM/test_02.hpp @@ -0,0 +1,189 @@ +// @HEADER +// ***************************************************************************** +// Intrepid2 Package +// +// Copyright 2007 NTESS and the Intrepid2 contributors. +// SPDX-License-Identifier: BSD-3-Clause +// ***************************************************************************** +// @HEADER + +/** \file test_02.hpp + \brief Unit tests for the Intrepid2::HCURL_TRI_In_FEM class. + \author Created by Kyungjoo Kim, Mauro Perego + */ + + +#include "Intrepid2_config.h" +#include "Kokkos_Random.hpp" +#ifdef HAVE_INTREPID2_DEBUG +#define INTREPID2_TEST_FOR_DEBUG_ABORT_OVERRIDE_TO_CONTINUE +#endif + +#include "Intrepid2_Types.hpp" +#include "Intrepid2_Utils.hpp" + +#include "Intrepid2_HCURL_TRI_In_FEM.hpp" +#include "packages/intrepid2/unit-test/Discretization/Basis/Setup.hpp" + +namespace Intrepid2 { + + namespace Test { + + // This test evaluates the basis functions at a set of points on a batch of cells using the team-level getValues, + // and compares the results with those obtained using the classic getValues function. + template + int HCURL_TRI_In_FEM_Test02(const bool verbose) { + + //! Setup test output stream. + Teuchos::RCP outStream = setup_output_stream( + verbose, "HCURL_TRI_In_FEM, Test 2", {} + ); + + *outStream + << "\n" + << "===============================================================================\n" + << "| Testing Team-level Implemntation of getValues |\n" + << "===============================================================================\n"; + + using DeviceSpaceType = typename DeviceType::execution_space; + Kokkos::print_configuration(std::cout, false); + + int errorFlag = 0; + constexpr int maxOrder = 9; + try { + for (int order=1;order<=maxOrder;++order) { + using BasisType = Basis_HCURL_TRI_In_FEM; + auto basisPtr = Teuchos::rcp(new BasisType(order)); + + const int ncells = 5, npts = 10, ndim = 2; + Kokkos::DynRankView ConstructWithLabelOutView(outputValuesA, ncells, basisPtr->getCardinality(), npts, ndim); + Kokkos::DynRankView ConstructWithLabelOutView(outputValuesB, basisPtr->getCardinality(), npts, ndim); + + Kokkos::DynRankView ConstructWithLabelOutView(outputCurlsA, ncells, basisPtr->getCardinality(), npts); + Kokkos::DynRankView ConstructWithLabelOutView(outputCurlsB, basisPtr->getCardinality(), npts); + + Kokkos::DynRankView ConstructWithLabelPointView(point, 1); + + using ScalarType = typename ScalarTraits::scalar_type; + + Kokkos::View inputPointsViewToUseRandom("inputPoints", npts*ndim*get_dimension_scalar(point)); + auto vcprop = Kokkos::common_view_alloc_prop(point); + Kokkos::DynRankView inputPoints (Kokkos::view_wrap(inputPointsViewToUseRandom.data(), vcprop), npts, ndim); + + // random values between (0,1) + Kokkos::Random_XorShift64_Pool random(13718); + Kokkos::fill_random(inputPointsViewToUseRandom, random, 1.0); + + + *outStream << "Order: " << order << ": Computing values and curls for " << ncells << " cells and " << npts << " points using team-level getValues function" <(*basisPtr); + auto basisRawPtr_device = basisPtr_device.get(); + + int scratch_space_level =1; + const int vectorSize = getVectorSizeForHierarchicalParallelism(); + Kokkos::TeamPolicy teamPolicy(ncells, Kokkos::AUTO,vectorSize); + + { //compute values + auto functor = KOKKOS_LAMBDA (typename Kokkos::TeamPolicy::member_type team_member) { + auto valsACell = Kokkos::subview(outputValuesA, team_member.league_rank(), Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL()); + basisRawPtr_device->getValues(valsACell, inputPoints, OPERATOR_VALUE, team_member, team_member.team_scratch(scratch_space_level)); + }; + + //Get the required size of the scratch space per team and per thread. + int perThreadSpaceSize(0), perTeamSpaceSize(0); + basisPtr->getScratchSpaceSize(perTeamSpaceSize,perThreadSpaceSize,inputPoints, OPERATOR_VALUE); + teamPolicy.set_scratch_size(scratch_space_level, Kokkos::PerTeam(perTeamSpaceSize), Kokkos::PerThread(perThreadSpaceSize)); + + Kokkos::parallel_for (teamPolicy,functor); + } + + { //compute curls + auto functor = KOKKOS_LAMBDA (typename Kokkos::TeamPolicy::member_type team_member) { + auto curlsACell = Kokkos::subview(outputCurlsA, team_member.league_rank(), Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL()); + basisRawPtr_device->getValues(curlsACell, inputPoints, OPERATOR_CURL, team_member, team_member.team_scratch(scratch_space_level)); + }; + + //Get the required size of the scratch space per team and per thread. + int perThreadSpaceSize(0), perTeamSpaceSize(0); + basisPtr->getScratchSpaceSize(perTeamSpaceSize,perThreadSpaceSize,inputPoints, OPERATOR_CURL); + teamPolicy.set_scratch_size(scratch_space_level, Kokkos::PerTeam(perTeamSpaceSize), Kokkos::PerThread(perThreadSpaceSize)); + + Kokkos::parallel_for (teamPolicy,functor); + } + } + + *outStream << "Order: " << order << ": Computing values and curls for " << npts << " points using high-level getValues function" <getValues(outputValuesB, inputPoints, OPERATOR_VALUE); + basisPtr->getValues(outputCurlsB, inputPoints, OPERATOR_CURL); + + *outStream << "Order: " << order << ": Comparing values and curls on host" <(); + for (size_t ic=0;ic tol) { + ++errorFlag; + std::cout << " order: " << order + << ", ic: " << ic << ", i: " << i << ", j: " << j + << ", val A: [" << outputValuesA_Host(ic,i,j,0) << ", " << outputValuesA_Host(ic,i,j,1) << "]" + << ", val B: [" << outputValuesB_Host(i,j,0) << ", " << outputValuesB_Host(i,j,1) << "]" + << ", |diff|: " << diff + << ", tol: " << tol + << std::endl; + } + } + } + + { + // compare curls + const auto outputCurlsA_Host = Kokkos::create_mirror_view(outputCurlsA); Kokkos::deep_copy(outputCurlsA_Host, outputCurlsA); + const auto outputCurlsB_Host = Kokkos::create_mirror_view(outputCurlsB); Kokkos::deep_copy(outputCurlsB_Host, outputCurlsB); + + OutValueType diff = 0; + auto tol = epsilon(); + for (size_t ic=0;ic tol) { + ++errorFlag; + std::cout << " order: " << order + << ", ic: " << ic << ", i: " << i << ", j: " << j + << ", curls A: [" << outputCurlsA_Host(ic,i,j)<<"]" + << ", curls B: [" << outputCurlsB_Host(i,j) << "]" + << ", |diff|: " << diff + << ", tol: " << tol + << std::endl; + } + } + } + } + } catch (std::exception &err) { + std::cout << "UNEXPECTED ERROR !!! ----------------------------------------------------------\n"; + std::cout << err.what() << '\n'; + std::cout << "-------------------------------------------------------------------------------" << "\n\n"; + errorFlag = -1000; + }; + + if (errorFlag != 0) + std::cout << "End Result: TEST FAILED\n"; + else + std::cout << "End Result: TEST PASSED\n"; + + return errorFlag; + } + } +} diff --git a/packages/intrepid2/unit-test/Discretization/Basis/HCURL_WEDGE_I1_FEM/CMakeLists.txt b/packages/intrepid2/unit-test/Discretization/Basis/HCURL_WEDGE_I1_FEM/CMakeLists.txt index ba0496748a48..cb1ebf7b3de1 100644 --- a/packages/intrepid2/unit-test/Discretization/Basis/HCURL_WEDGE_I1_FEM/CMakeLists.txt +++ b/packages/intrepid2/unit-test/Discretization/Basis/HCURL_WEDGE_I1_FEM/CMakeLists.txt @@ -1,8 +1,13 @@ TRIBITS_INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}) + +# test +SET(Intrepid2_TEST_ETI_FILE "test_01") + # value types SET(Intrepid2_TEST_ETI_VALUETYPE_NAME "") SET(Intrepid2_TEST_ETI_VALUETYPE "") +SET(Intrepid2_TEST_ETI_SACADO "") LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE_NAME "DOUBLE") LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE "double") @@ -17,9 +22,7 @@ ENDIF() LIST(LENGTH Intrepid2_TEST_ETI_VALUETYPE_NAME ETI_VALUETYPE_COUNT) MATH(EXPR ETI_VALUETYPE_COUNT "${ETI_VALUETYPE_COUNT}-1") -# Host test -SET(Intrepid2_TEST_ETI_FILE "test_01") - +# device SET(Intrepid2_TEST_ETI_DEVICE_NAME "") SET(Intrepid2_TEST_ETI_DEVICE "") IF(Kokkos_ENABLE_SERIAL) @@ -68,3 +71,76 @@ FOREACH(I RANGE ${ETI_DEVICE_COUNT}) ENDFOREACH() ENDFOREACH() + + + +# test +SET(Intrepid2_TEST_ETI_FILE "test_02") + +# value types +SET(Intrepid2_TEST_ETI_VALUETYPE_NAME "") +SET(Intrepid2_TEST_ETI_VALUETYPE "") +SET(Intrepid2_TEST_ETI_SACADO "") + +LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE_NAME "DOUBLE_DOUBLE") +LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE "double,double") +LIST(APPEND Intrepid2_TEST_ETI_SACADO "0") + +IF (HAVE_INTREPID2_SACADO) + LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE_NAME "DFAD_DFAD") + LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE "Sacado::Fad::DFad,Sacado::Fad::DFad ") + LIST(APPEND Intrepid2_TEST_ETI_SACADO "33") +ENDIF() + +LIST(LENGTH Intrepid2_TEST_ETI_VALUETYPE_NAME ETI_VALUETYPE_COUNT) +MATH(EXPR ETI_VALUETYPE_COUNT "${ETI_VALUETYPE_COUNT}-1") + +# device +SET(Intrepid2_TEST_ETI_DEVICE_NAME "") +SET(Intrepid2_TEST_ETI_DEVICE "") +IF(Kokkos_ENABLE_SERIAL) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "Serial") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() +IF(Kokkos_ENABLE_OPENMP) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "OpenMP") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() +IF(Kokkos_ENABLE_CUDA) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "CUDA") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() +IF(Kokkos_ENABLE_HIP) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "HIP") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() + +LIST(LENGTH Intrepid2_TEST_ETI_DEVICE_NAME ETI_DEVICE_COUNT) +MATH(EXPR ETI_DEVICE_COUNT "${ETI_DEVICE_COUNT}-1") + +FOREACH(I RANGE ${ETI_DEVICE_COUNT}) + LIST(GET Intrepid2_TEST_ETI_DEVICE_NAME ${I} ETI_DEVICE_NAME) + LIST(GET Intrepid2_TEST_ETI_DEVICE ${I} ETI_DEVICE) + FOREACH(J RANGE ${ETI_VALUETYPE_COUNT}) + LIST(GET Intrepid2_TEST_ETI_VALUETYPE_NAME ${J} ETI_VALUETYPE_NAME) + LIST(GET Intrepid2_TEST_ETI_VALUETYPE ${J} ETI_VALUETYPE) + LIST(GET Intrepid2_TEST_ETI_SACADO ${J} ETI_SACADO) + FOREACH(ETI_FILE IN LISTS Intrepid2_TEST_ETI_FILE) + SET(ETI_NAME "${ETI_FILE}_${ETI_DEVICE_NAME}_${ETI_VALUETYPE_NAME}") + MESSAGE(STATUS "Generating TEST: HCURL_WEDGE_I1_FEM ${ETI_NAME}.cpp") + CONFIGURE_FILE(eti/${ETI_FILE}_ETI.in ${ETI_NAME}.cpp) + + TRIBITS_ADD_EXECUTABLE_AND_TEST( + ${ETI_NAME} + SOURCES ${ETI_NAME}.cpp + ARGS PrintItAll + NUM_MPI_PROCS 1 + PASS_REGULAR_EXPRESSION "TEST PASSED" + ADD_DIR_TO_NAME + ) + + ENDFOREACH() + ENDFOREACH() +ENDFOREACH() + + diff --git a/packages/intrepid2/unit-test/Discretization/Basis/HCURL_WEDGE_I1_FEM/eti/test_02_ETI.in b/packages/intrepid2/unit-test/Discretization/Basis/HCURL_WEDGE_I1_FEM/eti/test_02_ETI.in new file mode 100644 index 000000000000..1b963155651c --- /dev/null +++ b/packages/intrepid2/unit-test/Discretization/Basis/HCURL_WEDGE_I1_FEM/eti/test_02_ETI.in @@ -0,0 +1,52 @@ +// @HEADER +// ***************************************************************************** +// Intrepid2 Package +// +// Copyright 2007 NTESS and the Intrepid2 contributors. +// SPDX-License-Identifier: BSD-3-Clause +// ***************************************************************************** +// @HEADER + +/** \file test_01.cpp + \brief Unit test of Intrepid2::Basis_HCURL_WEDGE_I1_FEM team-level getValues. + \author Kyungjoo Kim +*/ + +#include "Kokkos_Core.hpp" + +#define ETI_SACADO @ETI_SACADO@ +#if (ETI_SACADO != 0) /// SACADO +#include "Kokkos_ViewFactory.hpp" +#include "Sacado.hpp" +#endif + +#if (ETI_SACADO == 0) /// double double +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__) +#elif (ETI_SACADO == 11 /* SFAD SFAD */ || ETI_SACADO == 33 /* DFAD DFAD */) +constexpr int num_deriv = 3; +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#elif (ETI_SACADO == 23) +constexpr int num_deriv = 3; +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#elif (ETI_SACADO == 20) +constexpr int num_deriv = 2; +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__) +#endif + +#include "test_02.hpp" + +int main(int argc, char *argv[]) { + + const bool verbose = (argc-1) > 0; + Kokkos::initialize(); + + Intrepid2::Test::HCURL_WEDGE_I1_FEM_Test02<@ETI_VALUETYPE@,@ETI_DEVICE@>(verbose); + + Kokkos::finalize(); + return 0; +} + diff --git a/packages/intrepid2/unit-test/Discretization/Basis/HCURL_WEDGE_I1_FEM/test_02.hpp b/packages/intrepid2/unit-test/Discretization/Basis/HCURL_WEDGE_I1_FEM/test_02.hpp new file mode 100644 index 000000000000..de75f4cf2d72 --- /dev/null +++ b/packages/intrepid2/unit-test/Discretization/Basis/HCURL_WEDGE_I1_FEM/test_02.hpp @@ -0,0 +1,188 @@ +// @HEADER +// ***************************************************************************** +// Intrepid2 Package +// +// Copyright 2007 NTESS and the Intrepid2 contributors. +// SPDX-License-Identifier: BSD-3-Clause +// ***************************************************************************** +// @HEADER + +/** \file test_02.hpp + \brief Unit tests for the Intrepid2::HCURL_WEDGE_I1_FEM class. + \author Created by Kyungjoo Kim, Mauro Perego + */ + + +#include "Intrepid2_config.h" +#include "Kokkos_Random.hpp" +#ifdef HAVE_INTREPID2_DEBUG +#define INTREPID2_TEST_FOR_DEBUG_ABORT_OVERRIDE_TO_CONTINUE +#endif + +#include "Intrepid2_Types.hpp" +#include "Intrepid2_Utils.hpp" + +#include "Intrepid2_HCURL_WEDGE_I1_FEM.hpp" +#include "packages/intrepid2/unit-test/Discretization/Basis/Setup.hpp" + +namespace Intrepid2 { + + namespace Test { + + // This test evaluates the basis functions at a set of points on a batch of cells using the team-level getValues, + // and compares the results with those obtained using the classic getValues function. + template + int HCURL_WEDGE_I1_FEM_Test02(const bool verbose) { + + //! Setup test output stream. + Teuchos::RCP outStream = setup_output_stream( + verbose, "HCURL_WEDGE_I1_FEM, Test 2", {} + ); + + *outStream + << "\n" + << "===============================================================================\n" + << "| Testing Team-level Implemntation of getValues |\n" + << "===============================================================================\n"; + + using DeviceSpaceType = typename DeviceType::execution_space; + Kokkos::print_configuration(std::cout, false); + + int errorFlag = 0; + + try { + using BasisType = Basis_HCURL_WEDGE_I1_FEM; + auto basisPtr = Teuchos::rcp(new BasisType()); + + + const int ncells = 5, npts = 10, ndim = 3; + Kokkos::DynRankView ConstructWithLabelOutView(outputValuesA, ncells, basisPtr->getCardinality(), npts, ndim); + Kokkos::DynRankView ConstructWithLabelOutView(outputValuesB, basisPtr->getCardinality(), npts, ndim); + + Kokkos::DynRankView ConstructWithLabelOutView(outputCurlsA, ncells, basisPtr->getCardinality(), npts, ndim); + Kokkos::DynRankView ConstructWithLabelOutView(outputCurlsB, basisPtr->getCardinality(), npts, ndim); + + Kokkos::DynRankView ConstructWithLabelPointView(point, 1); + + using ScalarType = typename ScalarTraits::scalar_type; + + Kokkos::View inputPointsViewToUseRandom("inputPoints", npts*ndim*get_dimension_scalar(point)); + auto vcprop = Kokkos::common_view_alloc_prop(point); + Kokkos::DynRankView inputPoints (Kokkos::view_wrap(inputPointsViewToUseRandom.data(), vcprop), npts, ndim); + + // random values between (0,1) + Kokkos::Random_XorShift64_Pool random(13718); + Kokkos::fill_random(inputPointsViewToUseRandom, random, 1.0); + + + *outStream << "Computing values and curls for " << ncells << " cells and " << npts << " points using team-level getValues function" <(*basisPtr); + auto basisRawPtr_device = basisPtr_device.get(); + + int scratch_space_level =1; + const int vectorSize = getVectorSizeForHierarchicalParallelism(); + Kokkos::TeamPolicy teamPolicy(ncells, Kokkos::AUTO,vectorSize); + + { //compute values + auto functor = KOKKOS_LAMBDA (typename Kokkos::TeamPolicy::member_type team_member) { + auto valsACell = Kokkos::subview(outputValuesA, team_member.league_rank(), Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL()); + basisRawPtr_device->getValues(valsACell, inputPoints, OPERATOR_VALUE, team_member, team_member.team_scratch(scratch_space_level)); + }; + + //Get the required size of the scratch space per team and per thread. + int perThreadSpaceSize(0), perTeamSpaceSize(0); + basisPtr->getScratchSpaceSize(perTeamSpaceSize,perThreadSpaceSize,inputPoints, OPERATOR_VALUE); + teamPolicy.set_scratch_size(scratch_space_level, Kokkos::PerTeam(perTeamSpaceSize), Kokkos::PerThread(perThreadSpaceSize)); + + Kokkos::parallel_for (teamPolicy,functor); + } + + { //compute curls + auto functor = KOKKOS_LAMBDA (typename Kokkos::TeamPolicy::member_type team_member) { + auto curlsACell = Kokkos::subview(outputCurlsA, team_member.league_rank(), Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL()); + basisRawPtr_device->getValues(curlsACell, inputPoints, OPERATOR_CURL, team_member, team_member.team_scratch(scratch_space_level)); + }; + + //Get the required size of the scratch space per team and per thread. + int perThreadSpaceSize(0), perTeamSpaceSize(0); + basisPtr->getScratchSpaceSize(perTeamSpaceSize,perThreadSpaceSize,inputPoints, OPERATOR_CURL); + teamPolicy.set_scratch_size(scratch_space_level, Kokkos::PerTeam(perTeamSpaceSize), Kokkos::PerThread(perThreadSpaceSize)); + + Kokkos::parallel_for (teamPolicy,functor); + } + } + + *outStream << "Computing values and curls for " << npts << " points using high-level getValues function" <getValues(outputValuesB, inputPoints, OPERATOR_VALUE); + basisPtr->getValues(outputCurlsB, inputPoints, OPERATOR_CURL); + + *outStream << "Comparing values and curls on host" <(); + for (size_t ic=0;ic tol) { + ++errorFlag; + std::cout << ", ic: " << ic << ", i: " << i << ", j: " << j + << ", val A: [" << outputValuesA_Host(ic,i,j,0) << ", " << outputValuesA_Host(ic,i,j,1) << "]" + << ", val B: [" << outputValuesB_Host(i,j,0) << ", " << outputValuesB_Host(i,j,1) << "]" + << ", |diff|: " << diff + << ", tol: " << tol + << std::endl; + } + } + } + + { + // compare curls + const auto outputCurlsA_Host = Kokkos::create_mirror_view(outputCurlsA); Kokkos::deep_copy(outputCurlsA_Host, outputCurlsA); + const auto outputCurlsB_Host = Kokkos::create_mirror_view(outputCurlsB); Kokkos::deep_copy(outputCurlsB_Host, outputCurlsB); + + OutValueType diff = 0; + auto tol = epsilon(); + for (size_t ic=0;ic tol) { + ++errorFlag; + std::cout << ", ic: " << ic << ", i: " << i << ", j: " << j + << ", curls A: [" << outputCurlsA_Host(ic,i,j,0)<< ", " << outputCurlsA_Host(ic,i,j,1) << ", " << outputCurlsA_Host(ic,i,j,2) << "]" + << ", curls B: [" << outputCurlsB_Host(i,j,0) << ", " << outputCurlsB_Host(i,j,1)<< ", " << outputCurlsB_Host(i,j,2) << "]" + << ", |diff|: " << diff + << ", tol: " << tol + << std::endl; + } + } + } + } catch (std::exception &err) { + std::cout << "UNEXPECTED ERROR !!! ----------------------------------------------------------\n"; + std::cout << err.what() << '\n'; + std::cout << "-------------------------------------------------------------------------------" << "\n\n"; + errorFlag = -1000; + }; + + if (errorFlag != 0) + std::cout << "End Result: TEST FAILED\n"; + else + std::cout << "End Result: TEST PASSED\n"; + + return errorFlag; + } + } +} diff --git a/packages/intrepid2/unit-test/Discretization/Basis/HDIV_HEX_I1_FEM/CMakeLists.txt b/packages/intrepid2/unit-test/Discretization/Basis/HDIV_HEX_I1_FEM/CMakeLists.txt index fd4d688a591d..3fb8fc747f9c 100644 --- a/packages/intrepid2/unit-test/Discretization/Basis/HDIV_HEX_I1_FEM/CMakeLists.txt +++ b/packages/intrepid2/unit-test/Discretization/Basis/HDIV_HEX_I1_FEM/CMakeLists.txt @@ -1,13 +1,18 @@ TRIBITS_INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}) + +# test +SET(Intrepid2_TEST_ETI_FILE "test_01") + # value types SET(Intrepid2_TEST_ETI_VALUETYPE_NAME "") SET(Intrepid2_TEST_ETI_VALUETYPE "") +SET(Intrepid2_TEST_ETI_SACADO "") LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE_NAME "DOUBLE") LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE "double") LIST(APPEND Intrepid2_TEST_ETI_SACADO "0") - + IF (HAVE_INTREPID2_SACADO) # LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE_NAME "DFAD_DOUBLE") # LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE "Sacado::Fad::DFad") @@ -17,9 +22,7 @@ ENDIF() LIST(LENGTH Intrepid2_TEST_ETI_VALUETYPE_NAME ETI_VALUETYPE_COUNT) MATH(EXPR ETI_VALUETYPE_COUNT "${ETI_VALUETYPE_COUNT}-1") -# Host test -SET(Intrepid2_TEST_ETI_FILE "test_01") - +# device SET(Intrepid2_TEST_ETI_DEVICE_NAME "") SET(Intrepid2_TEST_ETI_DEVICE "") IF(Kokkos_ENABLE_SERIAL) @@ -68,3 +71,76 @@ FOREACH(I RANGE ${ETI_DEVICE_COUNT}) ENDFOREACH() ENDFOREACH() + + + +# test +SET(Intrepid2_TEST_ETI_FILE "test_02") + +# value types +SET(Intrepid2_TEST_ETI_VALUETYPE_NAME "") +SET(Intrepid2_TEST_ETI_VALUETYPE "") +SET(Intrepid2_TEST_ETI_SACADO "") + +LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE_NAME "DOUBLE_DOUBLE") +LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE "double,double") +LIST(APPEND Intrepid2_TEST_ETI_SACADO "0") + +IF (HAVE_INTREPID2_SACADO) + LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE_NAME "DFAD_DFAD") + LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE "Sacado::Fad::DFad,Sacado::Fad::DFad ") + LIST(APPEND Intrepid2_TEST_ETI_SACADO "33") +ENDIF() + +LIST(LENGTH Intrepid2_TEST_ETI_VALUETYPE_NAME ETI_VALUETYPE_COUNT) +MATH(EXPR ETI_VALUETYPE_COUNT "${ETI_VALUETYPE_COUNT}-1") + +# device +SET(Intrepid2_TEST_ETI_DEVICE_NAME "") +SET(Intrepid2_TEST_ETI_DEVICE "") +IF(Kokkos_ENABLE_SERIAL) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "Serial") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() +IF(Kokkos_ENABLE_OPENMP) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "OpenMP") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() +IF(Kokkos_ENABLE_CUDA) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "CUDA") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() +IF(Kokkos_ENABLE_HIP) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "HIP") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() + +LIST(LENGTH Intrepid2_TEST_ETI_DEVICE_NAME ETI_DEVICE_COUNT) +MATH(EXPR ETI_DEVICE_COUNT "${ETI_DEVICE_COUNT}-1") + +FOREACH(I RANGE ${ETI_DEVICE_COUNT}) + LIST(GET Intrepid2_TEST_ETI_DEVICE_NAME ${I} ETI_DEVICE_NAME) + LIST(GET Intrepid2_TEST_ETI_DEVICE ${I} ETI_DEVICE) + FOREACH(J RANGE ${ETI_VALUETYPE_COUNT}) + LIST(GET Intrepid2_TEST_ETI_VALUETYPE_NAME ${J} ETI_VALUETYPE_NAME) + LIST(GET Intrepid2_TEST_ETI_VALUETYPE ${J} ETI_VALUETYPE) + LIST(GET Intrepid2_TEST_ETI_SACADO ${J} ETI_SACADO) + FOREACH(ETI_FILE IN LISTS Intrepid2_TEST_ETI_FILE) + SET(ETI_NAME "${ETI_FILE}_${ETI_DEVICE_NAME}_${ETI_VALUETYPE_NAME}") + MESSAGE(STATUS "Generating TEST: HDIV_HEX_I1_FEM ${ETI_NAME}.cpp") + CONFIGURE_FILE(eti/${ETI_FILE}_ETI.in ${ETI_NAME}.cpp) + + TRIBITS_ADD_EXECUTABLE_AND_TEST( + ${ETI_NAME} + SOURCES ${ETI_NAME}.cpp + ARGS PrintItAll + NUM_MPI_PROCS 1 + PASS_REGULAR_EXPRESSION "TEST PASSED" + ADD_DIR_TO_NAME + ) + + ENDFOREACH() + ENDFOREACH() +ENDFOREACH() + + diff --git a/packages/intrepid2/unit-test/Discretization/Basis/HDIV_HEX_I1_FEM/eti/test_02_ETI.in b/packages/intrepid2/unit-test/Discretization/Basis/HDIV_HEX_I1_FEM/eti/test_02_ETI.in new file mode 100644 index 000000000000..ab24cfec247d --- /dev/null +++ b/packages/intrepid2/unit-test/Discretization/Basis/HDIV_HEX_I1_FEM/eti/test_02_ETI.in @@ -0,0 +1,52 @@ +// @HEADER +// ***************************************************************************** +// Intrepid2 Package +// +// Copyright 2007 NTESS and the Intrepid2 contributors. +// SPDX-License-Identifier: BSD-3-Clause +// ***************************************************************************** +// @HEADER + +/** \file test_01.cpp + \brief Unit test of Intrepid2::Basis_HDIV_HEX_I1_FEM team-level getValues. + \author Kyungjoo Kim +*/ + +#include "Kokkos_Core.hpp" + +#define ETI_SACADO @ETI_SACADO@ +#if (ETI_SACADO != 0) /// SACADO +#include "Kokkos_ViewFactory.hpp" +#include "Sacado.hpp" +#endif + +#if (ETI_SACADO == 0) /// double double +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__) +#elif (ETI_SACADO == 11 /* SFAD SFAD */ || ETI_SACADO == 33 /* DFAD DFAD */) +constexpr int num_deriv = 3; +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#elif (ETI_SACADO == 23) +constexpr int num_deriv = 3; +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#elif (ETI_SACADO == 20) +constexpr int num_deriv = 2; +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__) +#endif + +#include "test_02.hpp" + +int main(int argc, char *argv[]) { + + const bool verbose = (argc-1) > 0; + Kokkos::initialize(); + + Intrepid2::Test::HDIV_HEX_I1_FEM_Test02<@ETI_VALUETYPE@,@ETI_DEVICE@>(verbose); + + Kokkos::finalize(); + return 0; +} + diff --git a/packages/intrepid2/unit-test/Discretization/Basis/HDIV_HEX_I1_FEM/test_02.hpp b/packages/intrepid2/unit-test/Discretization/Basis/HDIV_HEX_I1_FEM/test_02.hpp new file mode 100644 index 000000000000..fb05ad186945 --- /dev/null +++ b/packages/intrepid2/unit-test/Discretization/Basis/HDIV_HEX_I1_FEM/test_02.hpp @@ -0,0 +1,186 @@ +// @HEADER +// ***************************************************************************** +// Intrepid2 Package +// +// Copyright 2007 NTESS and the Intrepid2 contributors. +// SPDX-License-Identifier: BSD-3-Clause +// ***************************************************************************** +// @HEADER + +/** \file test_02.hpp + \brief Unit tests for the Intrepid2::HDIV_HEX_I1_FEM class. + \author Created by Kyungjoo Kim, Mauro Perego + */ + + +#include "Intrepid2_config.h" +#include "Kokkos_Random.hpp" +#ifdef HAVE_INTREPID2_DEBUG +#define INTREPID2_TEST_FOR_DEBUG_ABORT_OVERRIDE_TO_CONTINUE +#endif + +#include "Intrepid2_Types.hpp" +#include "Intrepid2_Utils.hpp" + +#include "Intrepid2_HDIV_HEX_I1_FEM.hpp" +#include "packages/intrepid2/unit-test/Discretization/Basis/Setup.hpp" + +namespace Intrepid2 { + + namespace Test { + + // This test evaluates the basis functions at a set of points on a batch of cells using the team-level getValues, + // and compares the results with those obtained using the classic getValues function. + template + int HDIV_HEX_I1_FEM_Test02(const bool verbose) { + + //! Setup test output stream. + Teuchos::RCP outStream = setup_output_stream( + verbose, "HDIV_HEX_I1_FEM, Test 2", {} + ); + + *outStream + << "\n" + << "===============================================================================\n" + << "| Testing Team-level Implemntation of getValues |\n" + << "===============================================================================\n"; + + using DeviceSpaceType = typename DeviceType::execution_space; + Kokkos::print_configuration(std::cout, false); + + int errorFlag = 0; + + try { + using BasisType = Basis_HDIV_HEX_I1_FEM; + auto basisPtr = Teuchos::rcp(new BasisType()); + + + const int ncells = 5, npts = 10, ndim = 3; + Kokkos::DynRankView ConstructWithLabelOutView(outputValuesA, ncells, basisPtr->getCardinality(), npts, ndim); + Kokkos::DynRankView ConstructWithLabelOutView(outputValuesB, basisPtr->getCardinality(), npts, ndim); + + Kokkos::DynRankView ConstructWithLabelOutView(outputDivergencesA, ncells, basisPtr->getCardinality(), npts); + Kokkos::DynRankView ConstructWithLabelOutView(outputDivergencesB, basisPtr->getCardinality(), npts); + + Kokkos::DynRankView ConstructWithLabelPointView(point, 1); + + using ScalarType = typename ScalarTraits::scalar_type; + + Kokkos::View inputPointsViewToUseRandom("inputPoints", npts*ndim*get_dimension_scalar(point)); + auto vcprop = Kokkos::common_view_alloc_prop(point); + Kokkos::DynRankView inputPoints (Kokkos::view_wrap(inputPointsViewToUseRandom.data(), vcprop), npts, ndim); + + // random values between (0,1) + Kokkos::Random_XorShift64_Pool random(13718); + Kokkos::fill_random(inputPointsViewToUseRandom, random, 1.0); + + + *outStream << "Computing values and divergences for " << ncells << " cells and " << npts << " points using team-level getValues function" <(*basisPtr); + auto basisRawPtr_device = basisPtr_device.get(); + + int scratch_space_level =1; + const int vectorSize = getVectorSizeForHierarchicalParallelism(); + Kokkos::TeamPolicy teamPolicy(ncells, Kokkos::AUTO,vectorSize); + + { //compute values + auto functor = KOKKOS_LAMBDA (typename Kokkos::TeamPolicy::member_type team_member) { + auto valsACell = Kokkos::subview(outputValuesA, team_member.league_rank(), Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL()); + basisRawPtr_device->getValues(valsACell, inputPoints, OPERATOR_VALUE, team_member, team_member.team_scratch(scratch_space_level)); + }; + + //Get the required size of the scratch space per team and per thread. + int perThreadSpaceSize(0), perTeamSpaceSize(0); + basisPtr->getScratchSpaceSize(perTeamSpaceSize,perThreadSpaceSize,inputPoints, OPERATOR_VALUE); + teamPolicy.set_scratch_size(scratch_space_level, Kokkos::PerTeam(perTeamSpaceSize), Kokkos::PerThread(perThreadSpaceSize)); + + Kokkos::parallel_for (teamPolicy,functor); + } + + { //compute divergences + auto functor = KOKKOS_LAMBDA (typename Kokkos::TeamPolicy::member_type team_member) { + auto divergencesACell = Kokkos::subview(outputDivergencesA, team_member.league_rank(), Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL()); + basisRawPtr_device->getValues(divergencesACell, inputPoints, OPERATOR_DIV, team_member, team_member.team_scratch(scratch_space_level)); + }; + + //Get the required size of the scratch space per team and per thread. + int perThreadSpaceSize(0), perTeamSpaceSize(0); + basisPtr->getScratchSpaceSize(perTeamSpaceSize,perThreadSpaceSize,inputPoints, OPERATOR_DIV); + teamPolicy.set_scratch_size(scratch_space_level, Kokkos::PerTeam(perTeamSpaceSize), Kokkos::PerThread(perThreadSpaceSize)); + + Kokkos::parallel_for (teamPolicy,functor); + } + } + + *outStream << "Computing values and divergences for " << npts << " points using high-level getValues function" <getValues(outputValuesB, inputPoints, OPERATOR_VALUE); + basisPtr->getValues(outputDivergencesB, inputPoints, OPERATOR_DIV); + + *outStream << "Comparing values and divergences on host" <(); + for (size_t ic=0;ic tol) { + ++errorFlag; + std::cout << ", ic: " << ic << ", i: " << i << ", j: " << j + << ", val A: [" << outputValuesA_Host(ic,i,j,0) << ", " << outputValuesA_Host(ic,i,j,1) << ", " << outputValuesA_Host(ic,i,j,2) << "]" + << ", val B: [" << outputValuesB_Host(i,j,0) << ", " << outputValuesB_Host(i,j,1) << ", " << outputValuesB_Host(i,j,2) << "]" + << ", |diff|: " << diff + << ", tol: " << tol + << std::endl; + } + } + } + + { + // compare divergences + const auto outputDivergencesA_Host = Kokkos::create_mirror_view(outputDivergencesA); Kokkos::deep_copy(outputDivergencesA_Host, outputDivergencesA); + const auto outputDivergencesB_Host = Kokkos::create_mirror_view(outputDivergencesB); Kokkos::deep_copy(outputDivergencesB_Host, outputDivergencesB); + + OutValueType diff = 0; + auto tol = epsilon(); + for (size_t ic=0;ic tol) { + ++errorFlag; + std::cout << ", ic: " << ic << ", i: " << i << ", j: " << j + << ", divergence A: " << outputDivergencesA_Host(ic,i,j) + << ", divergence B: " << outputDivergencesB_Host(i,j) + << ", |diff|: " << diff + << ", tol: " << tol + << std::endl; + } + } + } + } catch (std::exception &err) { + std::cout << "UNEXPECTED ERROR !!! ----------------------------------------------------------\n"; + std::cout << err.what() << '\n'; + std::cout << "-------------------------------------------------------------------------------" << "\n\n"; + errorFlag = -1000; + }; + + if (errorFlag != 0) + std::cout << "End Result: TEST FAILED\n"; + else + std::cout << "End Result: TEST PASSED\n"; + + return errorFlag; + } + } +} diff --git a/packages/intrepid2/unit-test/Discretization/Basis/HDIV_HEX_In_FEM/CMakeLists.txt b/packages/intrepid2/unit-test/Discretization/Basis/HDIV_HEX_In_FEM/CMakeLists.txt index a0e677500751..7a81181c8403 100644 --- a/packages/intrepid2/unit-test/Discretization/Basis/HDIV_HEX_In_FEM/CMakeLists.txt +++ b/packages/intrepid2/unit-test/Discretization/Basis/HDIV_HEX_In_FEM/CMakeLists.txt @@ -1,8 +1,13 @@ TRIBITS_INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}) + +# test +SET(Intrepid2_TEST_ETI_FILE "test_01") + # value types SET(Intrepid2_TEST_ETI_VALUETYPE_NAME "") SET(Intrepid2_TEST_ETI_VALUETYPE "") +SET(Intrepid2_TEST_ETI_SACADO "") LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE_NAME "DOUBLE_DOUBLE") LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE "double,double") @@ -32,9 +37,80 @@ ENDIF() LIST(LENGTH Intrepid2_TEST_ETI_VALUETYPE_NAME ETI_VALUETYPE_COUNT) MATH(EXPR ETI_VALUETYPE_COUNT "${ETI_VALUETYPE_COUNT}-1") +# device +SET(Intrepid2_TEST_ETI_DEVICE_NAME "") +SET(Intrepid2_TEST_ETI_DEVICE "") +IF(Kokkos_ENABLE_SERIAL) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "Serial") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() +IF(Kokkos_ENABLE_OPENMP) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "OpenMP") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() +IF(Kokkos_ENABLE_CUDA) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "CUDA") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() +IF(Kokkos_ENABLE_HIP) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "HIP") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() + +LIST(LENGTH Intrepid2_TEST_ETI_DEVICE_NAME ETI_DEVICE_COUNT) +MATH(EXPR ETI_DEVICE_COUNT "${ETI_DEVICE_COUNT}-1") + +FOREACH(I RANGE ${ETI_DEVICE_COUNT}) + LIST(GET Intrepid2_TEST_ETI_DEVICE_NAME ${I} ETI_DEVICE_NAME) + LIST(GET Intrepid2_TEST_ETI_DEVICE ${I} ETI_DEVICE) + #MESSAGE(STATUS "Generating TEST HDIV_HEX_In_FEM for ${ETI_DEVICE_NAME} with ${ETI_DEVICE}") + FOREACH(J RANGE ${ETI_VALUETYPE_COUNT}) + LIST(GET Intrepid2_TEST_ETI_VALUETYPE_NAME ${J} ETI_VALUETYPE_NAME) + LIST(GET Intrepid2_TEST_ETI_VALUETYPE ${J} ETI_VALUETYPE) + LIST(GET Intrepid2_TEST_ETI_SACADO ${J} ETI_SACADO) + FOREACH(ETI_FILE IN LISTS Intrepid2_TEST_ETI_FILE) + SET(ETI_NAME "${ETI_FILE}_${ETI_DEVICE_NAME}_${ETI_VALUETYPE_NAME}") + MESSAGE(STATUS "Generating TEST: HDIV_HEX_In_FEM ${ETI_NAME}.cpp") + CONFIGURE_FILE(eti/${ETI_FILE}_ETI.in ${ETI_NAME}.cpp) + + TRIBITS_ADD_EXECUTABLE_AND_TEST( + ${ETI_NAME} + SOURCES ${ETI_NAME}.cpp + ARGS PrintItAll + NUM_MPI_PROCS 1 + PASS_REGULAR_EXPRESSION "TEST PASSED" + ADD_DIR_TO_NAME + ) + + ENDFOREACH() + ENDFOREACH() +ENDFOREACH() + + + + # test -SET(Intrepid2_TEST_ETI_FILE "test_01") +SET(Intrepid2_TEST_ETI_FILE "test_02") +# value types +SET(Intrepid2_TEST_ETI_VALUETYPE_NAME "") +SET(Intrepid2_TEST_ETI_VALUETYPE "") +SET(Intrepid2_TEST_ETI_SACADO "") + +LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE_NAME "DOUBLE_DOUBLE") +LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE "double,double") +LIST(APPEND Intrepid2_TEST_ETI_SACADO "0") + +IF (HAVE_INTREPID2_SACADO) + LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE_NAME "DFAD_DFAD") + LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE "Sacado::Fad::DFad,Sacado::Fad::DFad ") + LIST(APPEND Intrepid2_TEST_ETI_SACADO "33") +ENDIF() + +LIST(LENGTH Intrepid2_TEST_ETI_VALUETYPE_NAME ETI_VALUETYPE_COUNT) +MATH(EXPR ETI_VALUETYPE_COUNT "${ETI_VALUETYPE_COUNT}-1") + +# device SET(Intrepid2_TEST_ETI_DEVICE_NAME "") SET(Intrepid2_TEST_ETI_DEVICE "") IF(Kokkos_ENABLE_SERIAL) @@ -60,7 +136,6 @@ MATH(EXPR ETI_DEVICE_COUNT "${ETI_DEVICE_COUNT}-1") FOREACH(I RANGE ${ETI_DEVICE_COUNT}) LIST(GET Intrepid2_TEST_ETI_DEVICE_NAME ${I} ETI_DEVICE_NAME) LIST(GET Intrepid2_TEST_ETI_DEVICE ${I} ETI_DEVICE) - #MESSAGE(STATUS "Generating TEST HDIV_HEX_In_FEM for ${ETI_DEVICE_NAME} with ${ETI_DEVICE}") FOREACH(J RANGE ${ETI_VALUETYPE_COUNT}) LIST(GET Intrepid2_TEST_ETI_VALUETYPE_NAME ${J} ETI_VALUETYPE_NAME) LIST(GET Intrepid2_TEST_ETI_VALUETYPE ${J} ETI_VALUETYPE) diff --git a/packages/intrepid2/unit-test/Discretization/Basis/HDIV_HEX_In_FEM/eti/test_02_ETI.in b/packages/intrepid2/unit-test/Discretization/Basis/HDIV_HEX_In_FEM/eti/test_02_ETI.in new file mode 100644 index 000000000000..71b715c78833 --- /dev/null +++ b/packages/intrepid2/unit-test/Discretization/Basis/HDIV_HEX_In_FEM/eti/test_02_ETI.in @@ -0,0 +1,52 @@ +// @HEADER +// ***************************************************************************** +// Intrepid2 Package +// +// Copyright 2007 NTESS and the Intrepid2 contributors. +// SPDX-License-Identifier: BSD-3-Clause +// ***************************************************************************** +// @HEADER + +/** \file test_01.cpp + \brief Unit test of Intrepid2::Basis_HDIV_HEX_In_FEM team-level getValues. + \author Kyungjoo Kim +*/ + +#include "Kokkos_Core.hpp" + +#define ETI_SACADO @ETI_SACADO@ +#if (ETI_SACADO != 0) /// SACADO +#include "Kokkos_ViewFactory.hpp" +#include "Sacado.hpp" +#endif + +#if (ETI_SACADO == 0) /// double double +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__) +#elif (ETI_SACADO == 11 /* SFAD SFAD */ || ETI_SACADO == 33 /* DFAD DFAD */) +constexpr int num_deriv = 3; +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#elif (ETI_SACADO == 23) +constexpr int num_deriv = 3; +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#elif (ETI_SACADO == 20) +constexpr int num_deriv = 2; +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__) +#endif + +#include "test_02.hpp" + +int main(int argc, char *argv[]) { + + const bool verbose = (argc-1) > 0; + Kokkos::initialize(); + + Intrepid2::Test::HDIV_HEX_In_FEM_Test02<@ETI_VALUETYPE@,@ETI_DEVICE@>(verbose); + + Kokkos::finalize(); + return 0; +} + diff --git a/packages/intrepid2/unit-test/Discretization/Basis/HDIV_HEX_In_FEM/test_02.hpp b/packages/intrepid2/unit-test/Discretization/Basis/HDIV_HEX_In_FEM/test_02.hpp new file mode 100644 index 000000000000..61c3d844f5dd --- /dev/null +++ b/packages/intrepid2/unit-test/Discretization/Basis/HDIV_HEX_In_FEM/test_02.hpp @@ -0,0 +1,190 @@ +// @HEADER +// ***************************************************************************** +// Intrepid2 Package +// +// Copyright 2007 NTESS and the Intrepid2 contributors. +// SPDX-License-Identifier: BSD-3-Clause +// ***************************************************************************** +// @HEADER + +/** \file test_02.hpp + \brief Unit tests for the Intrepid2::HDIV_HEX_In_FEM class. + \author Created by Kyungjoo Kim, Mauro Perego + */ + + +#include "Intrepid2_config.h" +#include "Kokkos_Random.hpp" +#ifdef HAVE_INTREPID2_DEBUG +#define INTREPID2_TEST_FOR_DEBUG_ABORT_OVERRIDE_TO_CONTINUE +#endif + +#include "Intrepid2_Types.hpp" +#include "Intrepid2_Utils.hpp" + +#include "Intrepid2_HDIV_HEX_In_FEM.hpp" +#include "packages/intrepid2/unit-test/Discretization/Basis/Setup.hpp" + +namespace Intrepid2 { + + namespace Test { + + // This test evaluates the basis functions at a set of points on a batch of cells using the team-level getValues, + // and compares the results with those obtained using the classic getValues function. + + template + int HDIV_HEX_In_FEM_Test02(const bool verbose) { + + //! Setup test output stream. + Teuchos::RCP outStream = setup_output_stream( + verbose, "HDIV_HEX_In_FEM, Test 2", {} + ); + + *outStream + << "\n" + << "===============================================================================\n" + << "| Testing Team-level Implemntation of getValues |\n" + << "===============================================================================\n"; + + using DeviceSpaceType = typename DeviceType::execution_space; + Kokkos::print_configuration(std::cout, false); + + int errorFlag = 0; + constexpr int maxOrder = 9; + try { + for (int order=1;order<=maxOrder;++order) { + using BasisType = Basis_HDIV_HEX_In_FEM; + auto basisPtr = Teuchos::rcp(new BasisType(order)); + + const int ncells = 5, npts = 10, ndim = 3; + Kokkos::DynRankView ConstructWithLabelOutView(outputValuesA, ncells, basisPtr->getCardinality(), npts, ndim); + Kokkos::DynRankView ConstructWithLabelOutView(outputValuesB, basisPtr->getCardinality(), npts, ndim); + + Kokkos::DynRankView ConstructWithLabelOutView(outputDivergencesA, ncells, basisPtr->getCardinality(), npts); + Kokkos::DynRankView ConstructWithLabelOutView(outputDivergencesB, basisPtr->getCardinality(), npts); + + Kokkos::DynRankView ConstructWithLabelPointView(point, 1); + + using ScalarType = typename ScalarTraits::scalar_type; + + Kokkos::View inputPointsViewToUseRandom("inputPoints", npts*ndim*get_dimension_scalar(point)); + auto vcprop = Kokkos::common_view_alloc_prop(point); + Kokkos::DynRankView inputPoints (Kokkos::view_wrap(inputPointsViewToUseRandom.data(), vcprop), npts, ndim); + + // random values between (0,1) + Kokkos::Random_XorShift64_Pool random(13718); + Kokkos::fill_random(inputPointsViewToUseRandom, random, 1.0); + + + *outStream << "Order: " << order << ": Computing values and divergences for " << ncells << " cells and " << npts << " points using team-level getValues function" <(*basisPtr); + auto basisRawPtr_device = basisPtr_device.get(); + + int scratch_space_level =1; + const int vectorSize = getVectorSizeForHierarchicalParallelism(); + Kokkos::TeamPolicy teamPolicy(ncells, Kokkos::AUTO,vectorSize); + + { //compute values + auto functor = KOKKOS_LAMBDA (typename Kokkos::TeamPolicy::member_type team_member) { + auto valsACell = Kokkos::subview(outputValuesA, team_member.league_rank(), Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL()); + basisRawPtr_device->getValues(valsACell, inputPoints, OPERATOR_VALUE, team_member, team_member.team_scratch(scratch_space_level)); + }; + + //Get the required size of the scratch space per team and per thread. + int perThreadSpaceSize(0), perTeamSpaceSize(0); + basisPtr->getScratchSpaceSize(perTeamSpaceSize,perThreadSpaceSize,inputPoints, OPERATOR_VALUE); + teamPolicy.set_scratch_size(scratch_space_level, Kokkos::PerTeam(perTeamSpaceSize), Kokkos::PerThread(perThreadSpaceSize)); + + Kokkos::parallel_for (teamPolicy,functor); + } + + { //compute divergences + auto functor = KOKKOS_LAMBDA (typename Kokkos::TeamPolicy::member_type team_member) { + auto divergencesACell = Kokkos::subview(outputDivergencesA, team_member.league_rank(), Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL()); + basisRawPtr_device->getValues(divergencesACell, inputPoints, OPERATOR_DIV, team_member, team_member.team_scratch(scratch_space_level)); + }; + + //Get the required size of the scratch space per team and per thread. + int perThreadSpaceSize(0), perTeamSpaceSize(0); + basisPtr->getScratchSpaceSize(perTeamSpaceSize,perThreadSpaceSize,inputPoints, OPERATOR_DIV); + teamPolicy.set_scratch_size(scratch_space_level, Kokkos::PerTeam(perTeamSpaceSize), Kokkos::PerThread(perThreadSpaceSize)); + + Kokkos::parallel_for (teamPolicy,functor); + } + } + + *outStream << "Order: " << order << ": Computing values and divergences for " << npts << " points using high-level getValues function" <getValues(outputValuesB, inputPoints, OPERATOR_VALUE); + basisPtr->getValues(outputDivergencesB, inputPoints, OPERATOR_DIV); + + *outStream << "Order: " << order << ": Comparing values and divergences on host" <(); + for (size_t ic=0;ic tol) { + ++errorFlag; + std::cout << " order: " << order + << ", ic: " << ic << ", i: " << i << ", j: " << j + << ", val A: [" << outputValuesA_Host(ic,i,j,0) << ", " << outputValuesA_Host(ic,i,j,1) << ", " << outputValuesA_Host(ic,i,j,2) << "]" + << ", val B: [" << outputValuesB_Host(i,j,0) << ", " << outputValuesB_Host(i,j,1) << ", " << outputValuesB_Host(i,j,2) << "]" + << ", |diff|: " << diff + << ", tol: " << tol + << std::endl; + } + } + } + + { + // compare divergences + const auto outputDivergencesA_Host = Kokkos::create_mirror_view(outputDivergencesA); Kokkos::deep_copy(outputDivergencesA_Host, outputDivergencesA); + const auto outputDivergencesB_Host = Kokkos::create_mirror_view(outputDivergencesB); Kokkos::deep_copy(outputDivergencesB_Host, outputDivergencesB); + + OutValueType diff = 0; + auto tol = epsilon(); + for (size_t ic=0;ic tol) { + ++errorFlag; + std::cout << " order: " << order + << ", ic: " << ic << ", i: " << i << ", j: " << j + << ", divergence A: " << outputDivergencesA_Host(ic,i,j) + << ", divergence B: " << outputDivergencesB_Host(i,j) + << ", |diff|: " << diff + << ", tol: " << tol + << std::endl; + } + } + } + } + } catch (std::exception &err) { + std::cout << "UNEXPECTED ERROR !!! ----------------------------------------------------------\n"; + std::cout << err.what() << '\n'; + std::cout << "-------------------------------------------------------------------------------" << "\n\n"; + errorFlag = -1000; + }; + + if (errorFlag != 0) + std::cout << "End Result: TEST FAILED\n"; + else + std::cout << "End Result: TEST PASSED\n"; + + return errorFlag; + } + } +} diff --git a/packages/intrepid2/unit-test/Discretization/Basis/HDIV_QUAD_I1_FEM/CMakeLists.txt b/packages/intrepid2/unit-test/Discretization/Basis/HDIV_QUAD_I1_FEM/CMakeLists.txt index 5900fa72e32a..b21760f88ec4 100644 --- a/packages/intrepid2/unit-test/Discretization/Basis/HDIV_QUAD_I1_FEM/CMakeLists.txt +++ b/packages/intrepid2/unit-test/Discretization/Basis/HDIV_QUAD_I1_FEM/CMakeLists.txt @@ -1,13 +1,18 @@ TRIBITS_INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}) + +# test +SET(Intrepid2_TEST_ETI_FILE "test_01") + # value types SET(Intrepid2_TEST_ETI_VALUETYPE_NAME "") SET(Intrepid2_TEST_ETI_VALUETYPE "") +SET(Intrepid2_TEST_ETI_SACADO "") LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE_NAME "DOUBLE") LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE "double") LIST(APPEND Intrepid2_TEST_ETI_SACADO "0") - + IF (HAVE_INTREPID2_SACADO) # LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE_NAME "DFAD_DOUBLE") # LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE "Sacado::Fad::DFad") @@ -17,9 +22,7 @@ ENDIF() LIST(LENGTH Intrepid2_TEST_ETI_VALUETYPE_NAME ETI_VALUETYPE_COUNT) MATH(EXPR ETI_VALUETYPE_COUNT "${ETI_VALUETYPE_COUNT}-1") -# Host test -SET(Intrepid2_TEST_ETI_FILE "test_01") - +# device SET(Intrepid2_TEST_ETI_DEVICE_NAME "") SET(Intrepid2_TEST_ETI_DEVICE "") IF(Kokkos_ENABLE_SERIAL) @@ -68,3 +71,76 @@ FOREACH(I RANGE ${ETI_DEVICE_COUNT}) ENDFOREACH() ENDFOREACH() + + + +# test +SET(Intrepid2_TEST_ETI_FILE "test_02") + +# value types +SET(Intrepid2_TEST_ETI_VALUETYPE_NAME "") +SET(Intrepid2_TEST_ETI_VALUETYPE "") +SET(Intrepid2_TEST_ETI_SACADO "") + +LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE_NAME "DOUBLE_DOUBLE") +LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE "double,double") +LIST(APPEND Intrepid2_TEST_ETI_SACADO "0") + +IF (HAVE_INTREPID2_SACADO) + LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE_NAME "DFAD_DFAD") + LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE "Sacado::Fad::DFad,Sacado::Fad::DFad ") + LIST(APPEND Intrepid2_TEST_ETI_SACADO "33") +ENDIF() + +LIST(LENGTH Intrepid2_TEST_ETI_VALUETYPE_NAME ETI_VALUETYPE_COUNT) +MATH(EXPR ETI_VALUETYPE_COUNT "${ETI_VALUETYPE_COUNT}-1") + +# device +SET(Intrepid2_TEST_ETI_DEVICE_NAME "") +SET(Intrepid2_TEST_ETI_DEVICE "") +IF(Kokkos_ENABLE_SERIAL) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "Serial") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() +IF(Kokkos_ENABLE_OPENMP) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "OpenMP") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() +IF(Kokkos_ENABLE_CUDA) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "CUDA") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() +IF(Kokkos_ENABLE_HIP) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "HIP") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() + +LIST(LENGTH Intrepid2_TEST_ETI_DEVICE_NAME ETI_DEVICE_COUNT) +MATH(EXPR ETI_DEVICE_COUNT "${ETI_DEVICE_COUNT}-1") + +FOREACH(I RANGE ${ETI_DEVICE_COUNT}) + LIST(GET Intrepid2_TEST_ETI_DEVICE_NAME ${I} ETI_DEVICE_NAME) + LIST(GET Intrepid2_TEST_ETI_DEVICE ${I} ETI_DEVICE) + FOREACH(J RANGE ${ETI_VALUETYPE_COUNT}) + LIST(GET Intrepid2_TEST_ETI_VALUETYPE_NAME ${J} ETI_VALUETYPE_NAME) + LIST(GET Intrepid2_TEST_ETI_VALUETYPE ${J} ETI_VALUETYPE) + LIST(GET Intrepid2_TEST_ETI_SACADO ${J} ETI_SACADO) + FOREACH(ETI_FILE IN LISTS Intrepid2_TEST_ETI_FILE) + SET(ETI_NAME "${ETI_FILE}_${ETI_DEVICE_NAME}_${ETI_VALUETYPE_NAME}") + MESSAGE(STATUS "Generating TEST: HDIV_QUAD_I1_FEM ${ETI_NAME}.cpp") + CONFIGURE_FILE(eti/${ETI_FILE}_ETI.in ${ETI_NAME}.cpp) + + TRIBITS_ADD_EXECUTABLE_AND_TEST( + ${ETI_NAME} + SOURCES ${ETI_NAME}.cpp + ARGS PrintItAll + NUM_MPI_PROCS 1 + PASS_REGULAR_EXPRESSION "TEST PASSED" + ADD_DIR_TO_NAME + ) + + ENDFOREACH() + ENDFOREACH() +ENDFOREACH() + + diff --git a/packages/intrepid2/unit-test/Discretization/Basis/HDIV_QUAD_I1_FEM/eti/test_02_ETI.in b/packages/intrepid2/unit-test/Discretization/Basis/HDIV_QUAD_I1_FEM/eti/test_02_ETI.in new file mode 100644 index 000000000000..5e1eb4c2dc79 --- /dev/null +++ b/packages/intrepid2/unit-test/Discretization/Basis/HDIV_QUAD_I1_FEM/eti/test_02_ETI.in @@ -0,0 +1,52 @@ +// @HEADER +// ***************************************************************************** +// Intrepid2 Package +// +// Copyright 2007 NTESS and the Intrepid2 contributors. +// SPDX-License-Identifier: BSD-3-Clause +// ***************************************************************************** +// @HEADER + +/** \file test_01.cpp + \brief Unit test of Intrepid2::Basis_HDIV_QUAD_I1_FEM team-level getValues. + \author Kyungjoo Kim +*/ + +#include "Kokkos_Core.hpp" + +#define ETI_SACADO @ETI_SACADO@ +#if (ETI_SACADO != 0) /// SACADO +#include "Kokkos_ViewFactory.hpp" +#include "Sacado.hpp" +#endif + +#if (ETI_SACADO == 0) /// double double +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__) +#elif (ETI_SACADO == 11 /* SFAD SFAD */ || ETI_SACADO == 33 /* DFAD DFAD */) +constexpr int num_deriv = 3; +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#elif (ETI_SACADO == 23) +constexpr int num_deriv = 3; +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#elif (ETI_SACADO == 20) +constexpr int num_deriv = 2; +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__) +#endif + +#include "test_02.hpp" + +int main(int argc, char *argv[]) { + + const bool verbose = (argc-1) > 0; + Kokkos::initialize(); + + Intrepid2::Test::HDIV_QUAD_I1_FEM_Test02<@ETI_VALUETYPE@,@ETI_DEVICE@>(verbose); + + Kokkos::finalize(); + return 0; +} + diff --git a/packages/intrepid2/unit-test/Discretization/Basis/HDIV_QUAD_I1_FEM/test_02.hpp b/packages/intrepid2/unit-test/Discretization/Basis/HDIV_QUAD_I1_FEM/test_02.hpp new file mode 100644 index 000000000000..a811df7230c7 --- /dev/null +++ b/packages/intrepid2/unit-test/Discretization/Basis/HDIV_QUAD_I1_FEM/test_02.hpp @@ -0,0 +1,185 @@ +// @HEADER +// ***************************************************************************** +// Intrepid2 Package +// +// Copyright 2007 NTESS and the Intrepid2 contributors. +// SPDX-License-Identifier: BSD-3-Clause +// ***************************************************************************** +// @HEADER + +/** \file test_02.hpp + \brief Unit tests for the Intrepid2::HDIV_QUAD_I1_FEM class. + \author Created by Kyungjoo Kim, Mauro Perego + */ + + +#include "Intrepid2_config.h" +#include "Kokkos_Random.hpp" +#ifdef HAVE_INTREPID2_DEBUG +#define INTREPID2_TEST_FOR_DEBUG_ABORT_OVERRIDE_TO_CONTINUE +#endif + +#include "Intrepid2_Types.hpp" +#include "Intrepid2_Utils.hpp" + +#include "Intrepid2_HDIV_QUAD_I1_FEM.hpp" +#include "packages/intrepid2/unit-test/Discretization/Basis/Setup.hpp" + +namespace Intrepid2 { + + namespace Test { + + // This test evaluates the basis functions at a set of points on a batch of cells using the team-level getValues, + // and compares the results with those obtained using the classic getValues function. + template + int HDIV_QUAD_I1_FEM_Test02(const bool verbose) { + + //! Setup test output stream. + Teuchos::RCP outStream = setup_output_stream( + verbose, "HDIV_QUAD_I1_FEM, Test 2", {} + ); + + *outStream + << "\n" + << "===============================================================================\n" + << "| Testing Team-level Implemntation of getValues |\n" + << "===============================================================================\n"; + + using DeviceSpaceType = typename DeviceType::execution_space; + Kokkos::print_configuration(std::cout, false); + + int errorFlag = 0; + + try { + using BasisType = Basis_HDIV_QUAD_I1_FEM; + auto basisPtr = Teuchos::rcp(new BasisType()); + + const int ncells = 5, npts = 10, ndim = 2; + Kokkos::DynRankView ConstructWithLabelOutView(outputValuesA, ncells, basisPtr->getCardinality(), npts, ndim); + Kokkos::DynRankView ConstructWithLabelOutView(outputValuesB, basisPtr->getCardinality(), npts, ndim); + + Kokkos::DynRankView ConstructWithLabelOutView(outputDivergencesA, ncells, basisPtr->getCardinality(), npts); + Kokkos::DynRankView ConstructWithLabelOutView(outputDivergencesB, basisPtr->getCardinality(), npts); + + Kokkos::DynRankView ConstructWithLabelPointView(point, 1); + + using ScalarType = typename ScalarTraits::scalar_type; + + Kokkos::View inputPointsViewToUseRandom("inputPoints", npts*ndim*get_dimension_scalar(point)); + auto vcprop = Kokkos::common_view_alloc_prop(point); + Kokkos::DynRankView inputPoints (Kokkos::view_wrap(inputPointsViewToUseRandom.data(), vcprop), npts, ndim); + + // random values between (0,1) + Kokkos::Random_XorShift64_Pool random(13718); + Kokkos::fill_random(inputPointsViewToUseRandom, random, 1.0); + + + *outStream << "Computing values and divergences for " << ncells << " cells and " << npts << " points using team-level getValues function" <(*basisPtr); + auto basisRawPtr_device = basisPtr_device.get(); + + int scratch_space_level =1; + const int vectorSize = getVectorSizeForHierarchicalParallelism(); + Kokkos::TeamPolicy teamPolicy(ncells, Kokkos::AUTO,vectorSize); + + { //compute values + auto functor = KOKKOS_LAMBDA (typename Kokkos::TeamPolicy::member_type team_member) { + auto valsACell = Kokkos::subview(outputValuesA, team_member.league_rank(), Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL()); + basisRawPtr_device->getValues(valsACell, inputPoints, OPERATOR_VALUE, team_member, team_member.team_scratch(scratch_space_level)); + }; + + //Get the required size of the scratch space per team and per thread. + int perThreadSpaceSize(0), perTeamSpaceSize(0); + basisPtr->getScratchSpaceSize(perTeamSpaceSize,perThreadSpaceSize,inputPoints, OPERATOR_VALUE); + teamPolicy.set_scratch_size(scratch_space_level, Kokkos::PerTeam(perTeamSpaceSize), Kokkos::PerThread(perThreadSpaceSize)); + + Kokkos::parallel_for (teamPolicy,functor); + } + + { //compute divergences + auto functor = KOKKOS_LAMBDA (typename Kokkos::TeamPolicy::member_type team_member) { + auto divergencesACell = Kokkos::subview(outputDivergencesA, team_member.league_rank(), Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL()); + basisRawPtr_device->getValues(divergencesACell, inputPoints, OPERATOR_DIV, team_member, team_member.team_scratch(scratch_space_level)); + }; + + //Get the required size of the scratch space per team and per thread. + int perThreadSpaceSize(0), perTeamSpaceSize(0); + basisPtr->getScratchSpaceSize(perTeamSpaceSize,perThreadSpaceSize,inputPoints, OPERATOR_DIV); + teamPolicy.set_scratch_size(scratch_space_level, Kokkos::PerTeam(perTeamSpaceSize), Kokkos::PerThread(perThreadSpaceSize)); + + Kokkos::parallel_for (teamPolicy,functor); + } + } + + *outStream << "Computing values and divergences for " << npts << " points using high-level getValues function" <getValues(outputValuesB, inputPoints, OPERATOR_VALUE); + basisPtr->getValues(outputDivergencesB, inputPoints, OPERATOR_DIV); + + *outStream << "Comparing values and divergences on host" <(); + for (size_t ic=0;ic tol) { + ++errorFlag; + std::cout << ", ic: " << ic << ", i: " << i << ", j: " << j + << ", val A: [" << outputValuesA_Host(ic,i,j,0) << ", " << outputValuesA_Host(ic,i,j,1) << "]" + << ", val B: [" << outputValuesB_Host(i,j,0) << ", " << outputValuesB_Host(i,j,1) << "]" + << ", |diff|: " << diff + << ", tol: " << tol + << std::endl; + } + } + } + + { + // compare divergences + const auto outputDivergencesA_Host = Kokkos::create_mirror_view(outputDivergencesA); Kokkos::deep_copy(outputDivergencesA_Host, outputDivergencesA); + const auto outputDivergencesB_Host = Kokkos::create_mirror_view(outputDivergencesB); Kokkos::deep_copy(outputDivergencesB_Host, outputDivergencesB); + + OutValueType diff = 0; + auto tol = epsilon(); + for (size_t ic=0;ic tol) { + ++errorFlag; + std::cout << ", ic: " << ic << ", i: " << i << ", j: " << j + << ", divergence A: " << outputDivergencesA_Host(ic,i,j) + << ", divergence B: " << outputDivergencesB_Host(i,j) + << ", |diff|: " << diff + << ", tol: " << tol + << std::endl; + } + } + } + } catch (std::exception &err) { + std::cout << "UNEXPECTED ERROR !!! ----------------------------------------------------------\n"; + std::cout << err.what() << '\n'; + std::cout << "-------------------------------------------------------------------------------" << "\n\n"; + errorFlag = -1000; + }; + + if (errorFlag != 0) + std::cout << "End Result: TEST FAILED\n"; + else + std::cout << "End Result: TEST PASSED\n"; + + return errorFlag; + } + } +} diff --git a/packages/intrepid2/unit-test/Discretization/Basis/HDIV_QUAD_In_FEM/CMakeLists.txt b/packages/intrepid2/unit-test/Discretization/Basis/HDIV_QUAD_In_FEM/CMakeLists.txt index 59d15e7c716c..cdc2989d6036 100644 --- a/packages/intrepid2/unit-test/Discretization/Basis/HDIV_QUAD_In_FEM/CMakeLists.txt +++ b/packages/intrepid2/unit-test/Discretization/Basis/HDIV_QUAD_In_FEM/CMakeLists.txt @@ -1,8 +1,13 @@ TRIBITS_INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}) + +# test +SET(Intrepid2_TEST_ETI_FILE "test_01") + # value types SET(Intrepid2_TEST_ETI_VALUETYPE_NAME "") SET(Intrepid2_TEST_ETI_VALUETYPE "") +SET(Intrepid2_TEST_ETI_SACADO "") LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE_NAME "DOUBLE_DOUBLE") LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE "double,double") @@ -32,9 +37,80 @@ ENDIF() LIST(LENGTH Intrepid2_TEST_ETI_VALUETYPE_NAME ETI_VALUETYPE_COUNT) MATH(EXPR ETI_VALUETYPE_COUNT "${ETI_VALUETYPE_COUNT}-1") +# device +SET(Intrepid2_TEST_ETI_DEVICE_NAME "") +SET(Intrepid2_TEST_ETI_DEVICE "") +IF(Kokkos_ENABLE_SERIAL) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "Serial") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() +IF(Kokkos_ENABLE_OPENMP) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "OpenMP") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() +IF(Kokkos_ENABLE_CUDA) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "CUDA") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() +IF(Kokkos_ENABLE_HIP) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "HIP") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() + +LIST(LENGTH Intrepid2_TEST_ETI_DEVICE_NAME ETI_DEVICE_COUNT) +MATH(EXPR ETI_DEVICE_COUNT "${ETI_DEVICE_COUNT}-1") + +FOREACH(I RANGE ${ETI_DEVICE_COUNT}) + LIST(GET Intrepid2_TEST_ETI_DEVICE_NAME ${I} ETI_DEVICE_NAME) + LIST(GET Intrepid2_TEST_ETI_DEVICE ${I} ETI_DEVICE) + #MESSAGE(STATUS "Generating TEST HDIV_QUAD_In_FEM for ${ETI_DEVICE_NAME} with ${ETI_DEVICE}") + FOREACH(J RANGE ${ETI_VALUETYPE_COUNT}) + LIST(GET Intrepid2_TEST_ETI_VALUETYPE_NAME ${J} ETI_VALUETYPE_NAME) + LIST(GET Intrepid2_TEST_ETI_VALUETYPE ${J} ETI_VALUETYPE) + LIST(GET Intrepid2_TEST_ETI_SACADO ${J} ETI_SACADO) + FOREACH(ETI_FILE IN LISTS Intrepid2_TEST_ETI_FILE) + SET(ETI_NAME "${ETI_FILE}_${ETI_DEVICE_NAME}_${ETI_VALUETYPE_NAME}") + MESSAGE(STATUS "Generating TEST: HDIV_QUAD_In_FEM ${ETI_NAME}.cpp") + CONFIGURE_FILE(eti/${ETI_FILE}_ETI.in ${ETI_NAME}.cpp) + + TRIBITS_ADD_EXECUTABLE_AND_TEST( + ${ETI_NAME} + SOURCES ${ETI_NAME}.cpp + ARGS PrintItAll + NUM_MPI_PROCS 1 + PASS_REGULAR_EXPRESSION "TEST PASSED" + ADD_DIR_TO_NAME + ) + + ENDFOREACH() + ENDFOREACH() +ENDFOREACH() + + + + # test -SET(Intrepid2_TEST_ETI_FILE "test_01") +SET(Intrepid2_TEST_ETI_FILE "test_02") +# value types +SET(Intrepid2_TEST_ETI_VALUETYPE_NAME "") +SET(Intrepid2_TEST_ETI_VALUETYPE "") +SET(Intrepid2_TEST_ETI_SACADO "") + +LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE_NAME "DOUBLE_DOUBLE") +LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE "double,double") +LIST(APPEND Intrepid2_TEST_ETI_SACADO "0") + +IF (HAVE_INTREPID2_SACADO) + LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE_NAME "DFAD_DFAD") + LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE "Sacado::Fad::DFad,Sacado::Fad::DFad ") + LIST(APPEND Intrepid2_TEST_ETI_SACADO "33") +ENDIF() + +LIST(LENGTH Intrepid2_TEST_ETI_VALUETYPE_NAME ETI_VALUETYPE_COUNT) +MATH(EXPR ETI_VALUETYPE_COUNT "${ETI_VALUETYPE_COUNT}-1") + +# device SET(Intrepid2_TEST_ETI_DEVICE_NAME "") SET(Intrepid2_TEST_ETI_DEVICE "") IF(Kokkos_ENABLE_SERIAL) @@ -60,7 +136,6 @@ MATH(EXPR ETI_DEVICE_COUNT "${ETI_DEVICE_COUNT}-1") FOREACH(I RANGE ${ETI_DEVICE_COUNT}) LIST(GET Intrepid2_TEST_ETI_DEVICE_NAME ${I} ETI_DEVICE_NAME) LIST(GET Intrepid2_TEST_ETI_DEVICE ${I} ETI_DEVICE) - #MESSAGE(STATUS "Generating TEST HDIV_QUAD_In_FEM for ${ETI_DEVICE_NAME} with ${ETI_DEVICE}") FOREACH(J RANGE ${ETI_VALUETYPE_COUNT}) LIST(GET Intrepid2_TEST_ETI_VALUETYPE_NAME ${J} ETI_VALUETYPE_NAME) LIST(GET Intrepid2_TEST_ETI_VALUETYPE ${J} ETI_VALUETYPE) diff --git a/packages/intrepid2/unit-test/Discretization/Basis/HDIV_QUAD_In_FEM/eti/test_02_ETI.in b/packages/intrepid2/unit-test/Discretization/Basis/HDIV_QUAD_In_FEM/eti/test_02_ETI.in new file mode 100644 index 000000000000..328d40fda920 --- /dev/null +++ b/packages/intrepid2/unit-test/Discretization/Basis/HDIV_QUAD_In_FEM/eti/test_02_ETI.in @@ -0,0 +1,52 @@ +// @HEADER +// ***************************************************************************** +// Intrepid2 Package +// +// Copyright 2007 NTESS and the Intrepid2 contributors. +// SPDX-License-Identifier: BSD-3-Clause +// ***************************************************************************** +// @HEADER + +/** \file test_01.cpp + \brief Unit test of Intrepid2::Basis_HDIV_QUAD_In_FEM team-level getValues. + \author Kyungjoo Kim +*/ + +#include "Kokkos_Core.hpp" + +#define ETI_SACADO @ETI_SACADO@ +#if (ETI_SACADO != 0) /// SACADO +#include "Kokkos_ViewFactory.hpp" +#include "Sacado.hpp" +#endif + +#if (ETI_SACADO == 0) /// double double +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__) +#elif (ETI_SACADO == 11 /* SFAD SFAD */ || ETI_SACADO == 33 /* DFAD DFAD */) +constexpr int num_deriv = 3; +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#elif (ETI_SACADO == 23) +constexpr int num_deriv = 3; +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#elif (ETI_SACADO == 20) +constexpr int num_deriv = 2; +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__) +#endif + +#include "test_02.hpp" + +int main(int argc, char *argv[]) { + + const bool verbose = (argc-1) > 0; + Kokkos::initialize(); + + Intrepid2::Test::HDIV_QUAD_In_FEM_Test02<@ETI_VALUETYPE@,@ETI_DEVICE@>(verbose); + + Kokkos::finalize(); + return 0; +} + diff --git a/packages/intrepid2/unit-test/Discretization/Basis/HDIV_QUAD_In_FEM/test_02.hpp b/packages/intrepid2/unit-test/Discretization/Basis/HDIV_QUAD_In_FEM/test_02.hpp new file mode 100644 index 000000000000..529007a97787 --- /dev/null +++ b/packages/intrepid2/unit-test/Discretization/Basis/HDIV_QUAD_In_FEM/test_02.hpp @@ -0,0 +1,190 @@ +// @HEADER +// ***************************************************************************** +// Intrepid2 Package +// +// Copyright 2007 NTESS and the Intrepid2 contributors. +// SPDX-License-Identifier: BSD-3-Clause +// ***************************************************************************** +// @HEADER + +/** \file test_02.hpp + \brief Unit tests for the Intrepid2::HDIV_QUAD_In_FEM class. + \author Created by Kyungjoo Kim, Mauro Perego + */ + + +#include "Intrepid2_config.h" +#include "Kokkos_Random.hpp" +#ifdef HAVE_INTREPID2_DEBUG +#define INTREPID2_TEST_FOR_DEBUG_ABORT_OVERRIDE_TO_CONTINUE +#endif + +#include "Intrepid2_Types.hpp" +#include "Intrepid2_Utils.hpp" + +#include "Intrepid2_HDIV_QUAD_In_FEM.hpp" +#include "packages/intrepid2/unit-test/Discretization/Basis/Setup.hpp" + +namespace Intrepid2 { + + namespace Test { + + // This test evaluates the basis functions at a set of points on a batch of cells using the team-level getValues, + // and compares the results with those obtained using the classic getValues function. + template + int HDIV_QUAD_In_FEM_Test02(const bool verbose) { + + //! Setup test output stream. + Teuchos::RCP outStream = setup_output_stream( + verbose, "HDIV_QUAD_In_FEM, Test 2", {} + ); + + *outStream + << "\n" + << "===============================================================================\n" + << "| Testing Team-level Implemntation of getValues |\n" + << "===============================================================================\n"; + + using DeviceSpaceType = typename DeviceType::execution_space; + Kokkos::print_configuration(std::cout, false); + + int errorFlag = 0; + constexpr int maxOrder = 9; + try { + for (int order=1;order<=maxOrder;++order) { + using BasisType = Basis_HDIV_QUAD_In_FEM; + auto basisPtr = Teuchos::rcp(new BasisType(order)); + + + const int ncells = 5, npts = 10, ndim = 2; + Kokkos::DynRankView ConstructWithLabelOutView(outputValuesA, ncells, basisPtr->getCardinality(), npts, ndim); + Kokkos::DynRankView ConstructWithLabelOutView(outputValuesB, basisPtr->getCardinality(), npts, ndim); + + Kokkos::DynRankView ConstructWithLabelOutView(outputDivergencesA, ncells, basisPtr->getCardinality(), npts); + Kokkos::DynRankView ConstructWithLabelOutView(outputDivergencesB, basisPtr->getCardinality(), npts); + + Kokkos::DynRankView ConstructWithLabelPointView(point, 1); + + using ScalarType = typename ScalarTraits::scalar_type; + + Kokkos::View inputPointsViewToUseRandom("inputPoints", npts*ndim*get_dimension_scalar(point)); + auto vcprop = Kokkos::common_view_alloc_prop(point); + Kokkos::DynRankView inputPoints (Kokkos::view_wrap(inputPointsViewToUseRandom.data(), vcprop), npts, ndim); + + // random values between (0,1) + Kokkos::Random_XorShift64_Pool random(13718); + Kokkos::fill_random(inputPointsViewToUseRandom, random, 1.0); + + + *outStream << "Order: " << order << ": Computing values and divergences for " << ncells << " cells and " << npts << " points using team-level getValues function" <(*basisPtr); + auto basisRawPtr_device = basisPtr_device.get(); + + int scratch_space_level =1; + const int vectorSize = getVectorSizeForHierarchicalParallelism(); + Kokkos::TeamPolicy teamPolicy(ncells, Kokkos::AUTO,vectorSize); + + { //compute values + auto functor = KOKKOS_LAMBDA (typename Kokkos::TeamPolicy::member_type team_member) { + auto valsACell = Kokkos::subview(outputValuesA, team_member.league_rank(), Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL()); + basisRawPtr_device->getValues(valsACell, inputPoints, OPERATOR_VALUE, team_member, team_member.team_scratch(scratch_space_level)); + }; + + //Get the required size of the scratch space per team and per thread. + int perThreadSpaceSize(0), perTeamSpaceSize(0); + basisPtr->getScratchSpaceSize(perTeamSpaceSize,perThreadSpaceSize,inputPoints, OPERATOR_VALUE); + teamPolicy.set_scratch_size(scratch_space_level, Kokkos::PerTeam(perTeamSpaceSize), Kokkos::PerThread(perThreadSpaceSize)); + + Kokkos::parallel_for (teamPolicy,functor); + } + + { //compute divergences + auto functor = KOKKOS_LAMBDA (typename Kokkos::TeamPolicy::member_type team_member) { + auto divergencesACell = Kokkos::subview(outputDivergencesA, team_member.league_rank(), Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL()); + basisRawPtr_device->getValues(divergencesACell, inputPoints, OPERATOR_DIV, team_member, team_member.team_scratch(scratch_space_level)); + }; + + //Get the required size of the scratch space per team and per thread. + int perThreadSpaceSize(0), perTeamSpaceSize(0); + basisPtr->getScratchSpaceSize(perTeamSpaceSize,perThreadSpaceSize,inputPoints, OPERATOR_DIV); + teamPolicy.set_scratch_size(scratch_space_level, Kokkos::PerTeam(perTeamSpaceSize), Kokkos::PerThread(perThreadSpaceSize)); + + Kokkos::parallel_for (teamPolicy,functor); + } + } + + *outStream << "Order: " << order << ": Computing values and divergences for " << npts << " points using high-level getValues function" <getValues(outputValuesB, inputPoints, OPERATOR_VALUE); + basisPtr->getValues(outputDivergencesB, inputPoints, OPERATOR_DIV); + + *outStream << "Order: " << order << ": Comparing values and divergences on host" <(); + for (size_t ic=0;ic tol) { + ++errorFlag; + std::cout << " order: " << order + << ", ic: " << ic << ", i: " << i << ", j: " << j + << ", val A: [" << outputValuesA_Host(ic,i,j,0) << ", " << outputValuesA_Host(ic,i,j,1) << "]" + << ", val B: [" << outputValuesB_Host(i,j,0) << ", " << outputValuesB_Host(i,j,1) << "]" + << ", |diff|: " << diff + << ", tol: " << tol + << std::endl; + } + } + } + + { + // compare divergences + const auto outputDivergencesA_Host = Kokkos::create_mirror_view(outputDivergencesA); Kokkos::deep_copy(outputDivergencesA_Host, outputDivergencesA); + const auto outputDivergencesB_Host = Kokkos::create_mirror_view(outputDivergencesB); Kokkos::deep_copy(outputDivergencesB_Host, outputDivergencesB); + + OutValueType diff = 0; + auto tol = epsilon(); + for (size_t ic=0;ic tol) { + ++errorFlag; + std::cout << " order: " << order + << ", ic: " << ic << ", i: " << i << ", j: " << j + << ", divergence A: " << outputDivergencesA_Host(ic,i,j) + << ", divergence B: " << outputDivergencesB_Host(i,j) + << ", |diff|: " << diff + << ", tol: " << tol + << std::endl; + } + } + } + } + } catch (std::exception &err) { + std::cout << "UNEXPECTED ERROR !!! ----------------------------------------------------------\n"; + std::cout << err.what() << '\n'; + std::cout << "-------------------------------------------------------------------------------" << "\n\n"; + errorFlag = -1000; + }; + + if (errorFlag != 0) + std::cout << "End Result: TEST FAILED\n"; + else + std::cout << "End Result: TEST PASSED\n"; + + return errorFlag; + } + } +} diff --git a/packages/intrepid2/unit-test/Discretization/Basis/HDIV_TET_I1_FEM/CMakeLists.txt b/packages/intrepid2/unit-test/Discretization/Basis/HDIV_TET_I1_FEM/CMakeLists.txt index ea49b4cde715..6b8c89a459f9 100644 --- a/packages/intrepid2/unit-test/Discretization/Basis/HDIV_TET_I1_FEM/CMakeLists.txt +++ b/packages/intrepid2/unit-test/Discretization/Basis/HDIV_TET_I1_FEM/CMakeLists.txt @@ -1,13 +1,18 @@ TRIBITS_INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}) + +# test +SET(Intrepid2_TEST_ETI_FILE "test_01") + # value types SET(Intrepid2_TEST_ETI_VALUETYPE_NAME "") SET(Intrepid2_TEST_ETI_VALUETYPE "") +SET(Intrepid2_TEST_ETI_SACADO "") LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE_NAME "DOUBLE") LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE "double") LIST(APPEND Intrepid2_TEST_ETI_SACADO "0") - + IF (HAVE_INTREPID2_SACADO) # LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE_NAME "DFAD_DOUBLE") # LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE "Sacado::Fad::DFad") @@ -17,9 +22,7 @@ ENDIF() LIST(LENGTH Intrepid2_TEST_ETI_VALUETYPE_NAME ETI_VALUETYPE_COUNT) MATH(EXPR ETI_VALUETYPE_COUNT "${ETI_VALUETYPE_COUNT}-1") -# Host test -SET(Intrepid2_TEST_ETI_FILE "test_01") - +# device SET(Intrepid2_TEST_ETI_DEVICE_NAME "") SET(Intrepid2_TEST_ETI_DEVICE "") IF(Kokkos_ENABLE_SERIAL) @@ -68,3 +71,76 @@ FOREACH(I RANGE ${ETI_DEVICE_COUNT}) ENDFOREACH() ENDFOREACH() + + + +# test +SET(Intrepid2_TEST_ETI_FILE "test_02") + +# value types +SET(Intrepid2_TEST_ETI_VALUETYPE_NAME "") +SET(Intrepid2_TEST_ETI_VALUETYPE "") +SET(Intrepid2_TEST_ETI_SACADO "") + +LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE_NAME "DOUBLE_DOUBLE") +LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE "double,double") +LIST(APPEND Intrepid2_TEST_ETI_SACADO "0") + +IF (HAVE_INTREPID2_SACADO) + LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE_NAME "DFAD_DFAD") + LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE "Sacado::Fad::DFad,Sacado::Fad::DFad ") + LIST(APPEND Intrepid2_TEST_ETI_SACADO "33") +ENDIF() + +LIST(LENGTH Intrepid2_TEST_ETI_VALUETYPE_NAME ETI_VALUETYPE_COUNT) +MATH(EXPR ETI_VALUETYPE_COUNT "${ETI_VALUETYPE_COUNT}-1") + +# device +SET(Intrepid2_TEST_ETI_DEVICE_NAME "") +SET(Intrepid2_TEST_ETI_DEVICE "") +IF(Kokkos_ENABLE_SERIAL) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "Serial") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() +IF(Kokkos_ENABLE_OPENMP) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "OpenMP") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() +IF(Kokkos_ENABLE_CUDA) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "CUDA") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() +IF(Kokkos_ENABLE_HIP) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "HIP") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() + +LIST(LENGTH Intrepid2_TEST_ETI_DEVICE_NAME ETI_DEVICE_COUNT) +MATH(EXPR ETI_DEVICE_COUNT "${ETI_DEVICE_COUNT}-1") + +FOREACH(I RANGE ${ETI_DEVICE_COUNT}) + LIST(GET Intrepid2_TEST_ETI_DEVICE_NAME ${I} ETI_DEVICE_NAME) + LIST(GET Intrepid2_TEST_ETI_DEVICE ${I} ETI_DEVICE) + FOREACH(J RANGE ${ETI_VALUETYPE_COUNT}) + LIST(GET Intrepid2_TEST_ETI_VALUETYPE_NAME ${J} ETI_VALUETYPE_NAME) + LIST(GET Intrepid2_TEST_ETI_VALUETYPE ${J} ETI_VALUETYPE) + LIST(GET Intrepid2_TEST_ETI_SACADO ${J} ETI_SACADO) + FOREACH(ETI_FILE IN LISTS Intrepid2_TEST_ETI_FILE) + SET(ETI_NAME "${ETI_FILE}_${ETI_DEVICE_NAME}_${ETI_VALUETYPE_NAME}") + MESSAGE(STATUS "Generating TEST: HDIV_TET_I1_FEM ${ETI_NAME}.cpp") + CONFIGURE_FILE(eti/${ETI_FILE}_ETI.in ${ETI_NAME}.cpp) + + TRIBITS_ADD_EXECUTABLE_AND_TEST( + ${ETI_NAME} + SOURCES ${ETI_NAME}.cpp + ARGS PrintItAll + NUM_MPI_PROCS 1 + PASS_REGULAR_EXPRESSION "TEST PASSED" + ADD_DIR_TO_NAME + ) + + ENDFOREACH() + ENDFOREACH() +ENDFOREACH() + + diff --git a/packages/intrepid2/unit-test/Discretization/Basis/HDIV_TET_I1_FEM/eti/test_02_ETI.in b/packages/intrepid2/unit-test/Discretization/Basis/HDIV_TET_I1_FEM/eti/test_02_ETI.in new file mode 100644 index 000000000000..72f12aed7a9b --- /dev/null +++ b/packages/intrepid2/unit-test/Discretization/Basis/HDIV_TET_I1_FEM/eti/test_02_ETI.in @@ -0,0 +1,52 @@ +// @HEADER +// ***************************************************************************** +// Intrepid2 Package +// +// Copyright 2007 NTESS and the Intrepid2 contributors. +// SPDX-License-Identifier: BSD-3-Clause +// ***************************************************************************** +// @HEADER + +/** \file test_01.cpp + \brief Unit test of Intrepid2::Basis_HDIV_TET_I1_FEM team-level getValues. + \author Kyungjoo Kim +*/ + +#include "Kokkos_Core.hpp" + +#define ETI_SACADO @ETI_SACADO@ +#if (ETI_SACADO != 0) /// SACADO +#include "Kokkos_ViewFactory.hpp" +#include "Sacado.hpp" +#endif + +#if (ETI_SACADO == 0) /// double double +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__) +#elif (ETI_SACADO == 11 /* SFAD SFAD */ || ETI_SACADO == 33 /* DFAD DFAD */) +constexpr int num_deriv = 3; +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#elif (ETI_SACADO == 23) +constexpr int num_deriv = 3; +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#elif (ETI_SACADO == 20) +constexpr int num_deriv = 2; +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__) +#endif + +#include "test_02.hpp" + +int main(int argc, char *argv[]) { + + const bool verbose = (argc-1) > 0; + Kokkos::initialize(); + + Intrepid2::Test::HDIV_TET_I1_FEM_Test02<@ETI_VALUETYPE@,@ETI_DEVICE@>(verbose); + + Kokkos::finalize(); + return 0; +} + diff --git a/packages/intrepid2/unit-test/Discretization/Basis/HDIV_TET_I1_FEM/test_02.hpp b/packages/intrepid2/unit-test/Discretization/Basis/HDIV_TET_I1_FEM/test_02.hpp new file mode 100644 index 000000000000..2da333826892 --- /dev/null +++ b/packages/intrepid2/unit-test/Discretization/Basis/HDIV_TET_I1_FEM/test_02.hpp @@ -0,0 +1,185 @@ +// @HEADER +// ***************************************************************************** +// Intrepid2 Package +// +// Copyright 2007 NTESS and the Intrepid2 contributors. +// SPDX-License-Identifier: BSD-3-Clause +// ***************************************************************************** +// @HEADER + +/** \file test_02.hpp + \brief Unit tests for the Intrepid2::HDIV_TET_I1_FEM class. + \author Created by Kyungjoo Kim, Mauro Perego + */ + + +#include "Intrepid2_config.h" +#include "Kokkos_Random.hpp" +#ifdef HAVE_INTREPID2_DEBUG +#define INTREPID2_TEST_FOR_DEBUG_ABORT_OVERRIDE_TO_CONTINUE +#endif + +#include "Intrepid2_Types.hpp" +#include "Intrepid2_Utils.hpp" + +#include "Intrepid2_HDIV_TET_I1_FEM.hpp" +#include "packages/intrepid2/unit-test/Discretization/Basis/Setup.hpp" + +namespace Intrepid2 { + + namespace Test { + + // This test evaluates the basis functions at a set of points on a batch of cells using the team-level getValues, + // and compares the results with those obtained using the classic getValues function. + template + int HDIV_TET_I1_FEM_Test02(const bool verbose) { + + //! Setup test output stream. + Teuchos::RCP outStream = setup_output_stream( + verbose, "HDIV_TET_I1_FEM, Test 2", {} + ); + + *outStream + << "\n" + << "===============================================================================\n" + << "| Testing Team-level Implemntation of getValues |\n" + << "===============================================================================\n"; + + using DeviceSpaceType = typename DeviceType::execution_space; + Kokkos::print_configuration(std::cout, false); + + int errorFlag = 0; + + try { + using BasisType = Basis_HDIV_TET_I1_FEM; + auto basisPtr = Teuchos::rcp(new BasisType()); + + const int ncells = 5, npts = 10, ndim = 3; + Kokkos::DynRankView ConstructWithLabelOutView(outputValuesA, ncells, basisPtr->getCardinality(), npts, ndim); + Kokkos::DynRankView ConstructWithLabelOutView(outputValuesB, basisPtr->getCardinality(), npts, ndim); + + Kokkos::DynRankView ConstructWithLabelOutView(outputDivergencesA, ncells, basisPtr->getCardinality(), npts); + Kokkos::DynRankView ConstructWithLabelOutView(outputDivergencesB, basisPtr->getCardinality(), npts); + + Kokkos::DynRankView ConstructWithLabelPointView(point, 1); + + using ScalarType = typename ScalarTraits::scalar_type; + + Kokkos::View inputPointsViewToUseRandom("inputPoints", npts*ndim*get_dimension_scalar(point)); + auto vcprop = Kokkos::common_view_alloc_prop(point); + Kokkos::DynRankView inputPoints (Kokkos::view_wrap(inputPointsViewToUseRandom.data(), vcprop), npts, ndim); + + // random values between (0,1) + Kokkos::Random_XorShift64_Pool random(13718); + Kokkos::fill_random(inputPointsViewToUseRandom, random, 1.0); + + + *outStream << "Computing values and divergences for " << ncells << " cells and " << npts << " points using team-level getValues function" <(*basisPtr); + auto basisRawPtr_device = basisPtr_device.get(); + + int scratch_space_level =1; + const int vectorSize = getVectorSizeForHierarchicalParallelism(); + Kokkos::TeamPolicy teamPolicy(ncells, Kokkos::AUTO,vectorSize); + + { //compute values + auto functor = KOKKOS_LAMBDA (typename Kokkos::TeamPolicy::member_type team_member) { + auto valsACell = Kokkos::subview(outputValuesA, team_member.league_rank(), Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL()); + basisRawPtr_device->getValues(valsACell, inputPoints, OPERATOR_VALUE, team_member, team_member.team_scratch(scratch_space_level)); + }; + + //Get the required size of the scratch space per team and per thread. + int perThreadSpaceSize(0), perTeamSpaceSize(0); + basisPtr->getScratchSpaceSize(perTeamSpaceSize,perThreadSpaceSize,inputPoints, OPERATOR_VALUE); + teamPolicy.set_scratch_size(scratch_space_level, Kokkos::PerTeam(perTeamSpaceSize), Kokkos::PerThread(perThreadSpaceSize)); + + Kokkos::parallel_for (teamPolicy,functor); + } + + { //compute divergences + auto functor = KOKKOS_LAMBDA (typename Kokkos::TeamPolicy::member_type team_member) { + auto divergencesACell = Kokkos::subview(outputDivergencesA, team_member.league_rank(), Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL()); + basisRawPtr_device->getValues(divergencesACell, inputPoints, OPERATOR_DIV, team_member, team_member.team_scratch(scratch_space_level)); + }; + + //Get the required size of the scratch space per team and per thread. + int perThreadSpaceSize(0), perTeamSpaceSize(0); + basisPtr->getScratchSpaceSize(perTeamSpaceSize,perThreadSpaceSize,inputPoints, OPERATOR_DIV); + teamPolicy.set_scratch_size(scratch_space_level, Kokkos::PerTeam(perTeamSpaceSize), Kokkos::PerThread(perThreadSpaceSize)); + + Kokkos::parallel_for (teamPolicy,functor); + } + } + + *outStream << "Computing values and divergences for " << npts << " points using high-level getValues function" <getValues(outputValuesB, inputPoints, OPERATOR_VALUE); + basisPtr->getValues(outputDivergencesB, inputPoints, OPERATOR_DIV); + + *outStream << "Comparing values and divergences on host" <(); + for (size_t ic=0;ic tol) { + ++errorFlag; + std::cout << ", ic: " << ic << ", i: " << i << ", j: " << j + << ", val A: [" << outputValuesA_Host(ic,i,j,0) << ", " << outputValuesA_Host(ic,i,j,1) << ", " << outputValuesA_Host(ic,i,j,2) << "]" + << ", val B: [" << outputValuesB_Host(i,j,0) << ", " << outputValuesB_Host(i,j,1) << ", " << outputValuesB_Host(i,j,2) << "]" + << ", |diff|: " << diff + << ", tol: " << tol + << std::endl; + } + } + } + + { + // compare divergences + const auto outputDivergencesA_Host = Kokkos::create_mirror_view(outputDivergencesA); Kokkos::deep_copy(outputDivergencesA_Host, outputDivergencesA); + const auto outputDivergencesB_Host = Kokkos::create_mirror_view(outputDivergencesB); Kokkos::deep_copy(outputDivergencesB_Host, outputDivergencesB); + + OutValueType diff = 0; + auto tol = epsilon(); + for (size_t ic=0;ic tol) { + ++errorFlag; + std::cout << ", ic: " << ic << ", i: " << i << ", j: " << j + << ", divergence A: " << outputDivergencesA_Host(ic,i,j) + << ", divergence B: " << outputDivergencesB_Host(i,j) + << ", |diff|: " << diff + << ", tol: " << tol + << std::endl; + } + } + } + } catch (std::exception &err) { + std::cout << "UNEXPECTED ERROR !!! ----------------------------------------------------------\n"; + std::cout << err.what() << '\n'; + std::cout << "-------------------------------------------------------------------------------" << "\n\n"; + errorFlag = -1000; + }; + + if (errorFlag != 0) + std::cout << "End Result: TEST FAILED\n"; + else + std::cout << "End Result: TEST PASSED\n"; + + return errorFlag; + } + } +} diff --git a/packages/intrepid2/unit-test/Discretization/Basis/HDIV_TET_In_FEM/CMakeLists.txt b/packages/intrepid2/unit-test/Discretization/Basis/HDIV_TET_In_FEM/CMakeLists.txt index 264ce7c056ff..f4a2093e0e4f 100644 --- a/packages/intrepid2/unit-test/Discretization/Basis/HDIV_TET_In_FEM/CMakeLists.txt +++ b/packages/intrepid2/unit-test/Discretization/Basis/HDIV_TET_In_FEM/CMakeLists.txt @@ -1,8 +1,13 @@ TRIBITS_INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}) + +# test +SET(Intrepid2_TEST_ETI_FILE "test_01") + # value types SET(Intrepid2_TEST_ETI_VALUETYPE_NAME "") SET(Intrepid2_TEST_ETI_VALUETYPE "") +SET(Intrepid2_TEST_ETI_SACADO "") LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE_NAME "DOUBLE_DOUBLE") LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE "double,double") @@ -32,9 +37,80 @@ ENDIF() LIST(LENGTH Intrepid2_TEST_ETI_VALUETYPE_NAME ETI_VALUETYPE_COUNT) MATH(EXPR ETI_VALUETYPE_COUNT "${ETI_VALUETYPE_COUNT}-1") +# device +SET(Intrepid2_TEST_ETI_DEVICE_NAME "") +SET(Intrepid2_TEST_ETI_DEVICE "") +IF(Kokkos_ENABLE_SERIAL) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "Serial") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() +IF(Kokkos_ENABLE_OPENMP) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "OpenMP") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() +IF(Kokkos_ENABLE_CUDA) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "CUDA") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() +IF(Kokkos_ENABLE_HIP) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "HIP") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() + +LIST(LENGTH Intrepid2_TEST_ETI_DEVICE_NAME ETI_DEVICE_COUNT) +MATH(EXPR ETI_DEVICE_COUNT "${ETI_DEVICE_COUNT}-1") + +FOREACH(I RANGE ${ETI_DEVICE_COUNT}) + LIST(GET Intrepid2_TEST_ETI_DEVICE_NAME ${I} ETI_DEVICE_NAME) + LIST(GET Intrepid2_TEST_ETI_DEVICE ${I} ETI_DEVICE) + #MESSAGE(STATUS "Generating TEST HDIV_TET_In_FEM for ${ETI_DEVICE_NAME} with ${ETI_DEVICE}") + FOREACH(J RANGE ${ETI_VALUETYPE_COUNT}) + LIST(GET Intrepid2_TEST_ETI_VALUETYPE_NAME ${J} ETI_VALUETYPE_NAME) + LIST(GET Intrepid2_TEST_ETI_VALUETYPE ${J} ETI_VALUETYPE) + LIST(GET Intrepid2_TEST_ETI_SACADO ${J} ETI_SACADO) + FOREACH(ETI_FILE IN LISTS Intrepid2_TEST_ETI_FILE) + SET(ETI_NAME "${ETI_FILE}_${ETI_DEVICE_NAME}_${ETI_VALUETYPE_NAME}") + MESSAGE(STATUS "Generating TEST: HDIV_TET_In_FEM ${ETI_NAME}.cpp") + CONFIGURE_FILE(eti/${ETI_FILE}_ETI.in ${ETI_NAME}.cpp) + + TRIBITS_ADD_EXECUTABLE_AND_TEST( + ${ETI_NAME} + SOURCES ${ETI_NAME}.cpp + ARGS PrintItAll + NUM_MPI_PROCS 1 + PASS_REGULAR_EXPRESSION "TEST PASSED" + ADD_DIR_TO_NAME + ) + + ENDFOREACH() + ENDFOREACH() +ENDFOREACH() + + + + # test -SET(Intrepid2_TEST_ETI_FILE "test_01") +SET(Intrepid2_TEST_ETI_FILE "test_02") +# value types +SET(Intrepid2_TEST_ETI_VALUETYPE_NAME "") +SET(Intrepid2_TEST_ETI_VALUETYPE "") +SET(Intrepid2_TEST_ETI_SACADO "") + +LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE_NAME "DOUBLE_DOUBLE") +LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE "double,double") +LIST(APPEND Intrepid2_TEST_ETI_SACADO "0") + +IF (HAVE_INTREPID2_SACADO) + LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE_NAME "DFAD_DFAD") + LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE "Sacado::Fad::DFad,Sacado::Fad::DFad ") + LIST(APPEND Intrepid2_TEST_ETI_SACADO "33") +ENDIF() + +LIST(LENGTH Intrepid2_TEST_ETI_VALUETYPE_NAME ETI_VALUETYPE_COUNT) +MATH(EXPR ETI_VALUETYPE_COUNT "${ETI_VALUETYPE_COUNT}-1") + +# device SET(Intrepid2_TEST_ETI_DEVICE_NAME "") SET(Intrepid2_TEST_ETI_DEVICE "") IF(Kokkos_ENABLE_SERIAL) @@ -60,7 +136,6 @@ MATH(EXPR ETI_DEVICE_COUNT "${ETI_DEVICE_COUNT}-1") FOREACH(I RANGE ${ETI_DEVICE_COUNT}) LIST(GET Intrepid2_TEST_ETI_DEVICE_NAME ${I} ETI_DEVICE_NAME) LIST(GET Intrepid2_TEST_ETI_DEVICE ${I} ETI_DEVICE) - #MESSAGE(STATUS "Generating TEST HDIV_TET_In_FEM for ${ETI_DEVICE_NAME} with ${ETI_DEVICE}") FOREACH(J RANGE ${ETI_VALUETYPE_COUNT}) LIST(GET Intrepid2_TEST_ETI_VALUETYPE_NAME ${J} ETI_VALUETYPE_NAME) LIST(GET Intrepid2_TEST_ETI_VALUETYPE ${J} ETI_VALUETYPE) diff --git a/packages/intrepid2/unit-test/Discretization/Basis/HDIV_TET_In_FEM/eti/test_02_ETI.in b/packages/intrepid2/unit-test/Discretization/Basis/HDIV_TET_In_FEM/eti/test_02_ETI.in new file mode 100644 index 000000000000..c08e06044acf --- /dev/null +++ b/packages/intrepid2/unit-test/Discretization/Basis/HDIV_TET_In_FEM/eti/test_02_ETI.in @@ -0,0 +1,52 @@ +// @HEADER +// ***************************************************************************** +// Intrepid2 Package +// +// Copyright 2007 NTESS and the Intrepid2 contributors. +// SPDX-License-Identifier: BSD-3-Clause +// ***************************************************************************** +// @HEADER + +/** \file test_01.cpp + \brief Unit test of Intrepid2::Basis_HDIV_TET_In_FEM team-level getValues. + \author Kyungjoo Kim +*/ + +#include "Kokkos_Core.hpp" + +#define ETI_SACADO @ETI_SACADO@ +#if (ETI_SACADO != 0) /// SACADO +#include "Kokkos_ViewFactory.hpp" +#include "Sacado.hpp" +#endif + +#if (ETI_SACADO == 0) /// double double +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__) +#elif (ETI_SACADO == 11 /* SFAD SFAD */ || ETI_SACADO == 33 /* DFAD DFAD */) +constexpr int num_deriv = 3; +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#elif (ETI_SACADO == 23) +constexpr int num_deriv = 3; +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#elif (ETI_SACADO == 20) +constexpr int num_deriv = 2; +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__) +#endif + +#include "test_02.hpp" + +int main(int argc, char *argv[]) { + + const bool verbose = (argc-1) > 0; + Kokkos::initialize(); + + Intrepid2::Test::HDIV_TET_In_FEM_Test02<@ETI_VALUETYPE@,@ETI_DEVICE@>(verbose); + + Kokkos::finalize(); + return 0; +} + diff --git a/packages/intrepid2/unit-test/Discretization/Basis/HDIV_TET_In_FEM/test_02.hpp b/packages/intrepid2/unit-test/Discretization/Basis/HDIV_TET_In_FEM/test_02.hpp new file mode 100644 index 000000000000..6186dd1fb4bc --- /dev/null +++ b/packages/intrepid2/unit-test/Discretization/Basis/HDIV_TET_In_FEM/test_02.hpp @@ -0,0 +1,190 @@ +// @HEADER +// ***************************************************************************** +// Intrepid2 Package +// +// Copyright 2007 NTESS and the Intrepid2 contributors. +// SPDX-License-Identifier: BSD-3-Clause +// ***************************************************************************** +// @HEADER + +/** \file test_02.hpp + \brief Unit tests for the Intrepid2::HDIV_TET_In_FEM class. + \author Created by Kyungjoo Kim, Mauro Perego + */ + + +#include "Intrepid2_config.h" +#include "Kokkos_Random.hpp" +#ifdef HAVE_INTREPID2_DEBUG +#define INTREPID2_TEST_FOR_DEBUG_ABORT_OVERRIDE_TO_CONTINUE +#endif + +#include "Intrepid2_Types.hpp" +#include "Intrepid2_Utils.hpp" + +#include "Intrepid2_HDIV_TET_In_FEM.hpp" +#include "packages/intrepid2/unit-test/Discretization/Basis/Setup.hpp" + +namespace Intrepid2 { + + namespace Test { + + // This test evaluates the basis functions at a set of points on a batch of cells using the team-level getValues, + // and compares the results with those obtained using the classic getValues function. + template + int HDIV_TET_In_FEM_Test02(const bool verbose) { + + //! Setup test output stream. + Teuchos::RCP outStream = setup_output_stream( + verbose, "HDIV_TET_In_FEM, Test 2", {} + ); + + *outStream + << "\n" + << "===============================================================================\n" + << "| Testing Team-level Implemntation of getValues |\n" + << "===============================================================================\n"; + + using DeviceSpaceType = typename DeviceType::execution_space; + Kokkos::print_configuration(std::cout, false); + + int errorFlag = 0; + constexpr int maxOrder = 7; + try { + for (int order=1;order<=maxOrder;++order) { + using BasisType = Basis_HDIV_TET_In_FEM; + auto basisPtr = Teuchos::rcp(new BasisType(order)); + + const int ncells = 5, npts = 10, ndim = 3; + Kokkos::DynRankView ConstructWithLabelOutView(outputValuesA, ncells, basisPtr->getCardinality(), npts, ndim); + Kokkos::DynRankView ConstructWithLabelOutView(outputValuesB, basisPtr->getCardinality(), npts, ndim); + + Kokkos::DynRankView ConstructWithLabelOutView(outputDivergencesA, ncells, basisPtr->getCardinality(), npts); + Kokkos::DynRankView ConstructWithLabelOutView(outputDivergencesB, basisPtr->getCardinality(), npts); + + Kokkos::DynRankView ConstructWithLabelPointView(point, 1); + + using ScalarType = typename ScalarTraits::scalar_type; + + Kokkos::View inputPointsViewToUseRandom("inputPoints", npts*ndim*get_dimension_scalar(point)); + auto vcprop = Kokkos::common_view_alloc_prop(point); + Kokkos::DynRankView inputPoints (Kokkos::view_wrap(inputPointsViewToUseRandom.data(), vcprop), npts, ndim); + + // random values between (0,1) + Kokkos::Random_XorShift64_Pool random(13718); + Kokkos::fill_random(inputPointsViewToUseRandom, random, 1.0); + + + *outStream << "Order: " << order << ": Computing values and divergences for " << ncells << " cells and " << npts << " points using team-level getValues function" <(*basisPtr); + auto basisRawPtr_device = basisPtr_device.get(); + + int scratch_space_level =1; + const int vectorSize = getVectorSizeForHierarchicalParallelism(); + Kokkos::TeamPolicy teamPolicy(ncells, Kokkos::AUTO,vectorSize); + + { //compute values + auto functor = KOKKOS_LAMBDA (typename Kokkos::TeamPolicy::member_type team_member) { + auto valsACell = Kokkos::subview(outputValuesA, team_member.league_rank(), Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL()); + basisRawPtr_device->getValues(valsACell, inputPoints, OPERATOR_VALUE, team_member, team_member.team_scratch(scratch_space_level)); + }; + + //Get the required size of the scratch space per team and per thread. + int perThreadSpaceSize(0), perTeamSpaceSize(0); + basisPtr->getScratchSpaceSize(perTeamSpaceSize,perThreadSpaceSize,inputPoints, OPERATOR_VALUE); + teamPolicy.set_scratch_size(scratch_space_level, Kokkos::PerTeam(perTeamSpaceSize), Kokkos::PerThread(perThreadSpaceSize)); + + Kokkos::parallel_for (teamPolicy,functor); + } + + { //compute divergences + auto functor = KOKKOS_LAMBDA (typename Kokkos::TeamPolicy::member_type team_member) { + auto divergencesACell = Kokkos::subview(outputDivergencesA, team_member.league_rank(), Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL()); + basisRawPtr_device->getValues(divergencesACell, inputPoints, OPERATOR_DIV, team_member, team_member.team_scratch(scratch_space_level)); + }; + + //Get the required size of the scratch space per team and per thread. + int perThreadSpaceSize(0), perTeamSpaceSize(0); + basisPtr->getScratchSpaceSize(perTeamSpaceSize,perThreadSpaceSize,inputPoints, OPERATOR_DIV); + teamPolicy.set_scratch_size(scratch_space_level, Kokkos::PerTeam(perTeamSpaceSize), Kokkos::PerThread(perThreadSpaceSize)); + + Kokkos::parallel_for (teamPolicy,functor); + } + } + + *outStream << "Order: " << order << ": Computing values and divergences for " << npts << " points using high-level getValues function" <getValues(outputValuesB, inputPoints, OPERATOR_VALUE); + basisPtr->getValues(outputDivergencesB, inputPoints, OPERATOR_DIV); + + *outStream << "Order: " << order << ": Comparing values and divergences on host" <(); + for (size_t ic=0;ic tol) { + ++errorFlag; + std::cout << " order: " << order + << ", ic: " << ic << ", i: " << i << ", j: " << j + << ", val A: [" << outputValuesA_Host(ic,i,j,0) << ", " << outputValuesA_Host(ic,i,j,1) << ", " << outputValuesA_Host(ic,i,j,2) << "]" + << ", val B: [" << outputValuesB_Host(i,j,0) << ", " << outputValuesB_Host(i,j,1) << ", " << outputValuesB_Host(i,j,2) << "]" + << ", |diff|: " << diff + << ", tol: " << tol + << std::endl; + } + } + } + + { + // compare divergences + const auto outputDivergencesA_Host = Kokkos::create_mirror_view(outputDivergencesA); Kokkos::deep_copy(outputDivergencesA_Host, outputDivergencesA); + const auto outputDivergencesB_Host = Kokkos::create_mirror_view(outputDivergencesB); Kokkos::deep_copy(outputDivergencesB_Host, outputDivergencesB); + + OutValueType diff = 0; + //Note, a PR release-debug serial build shows substantially higher errors (possibly due to operation rearrangements). Need to investigate more. + auto tol = 1e6*epsilon(); + for (size_t ic=0;ic tol) { + ++errorFlag; + std::cout << " order: " << order + << ", ic: " << ic << ", i: " << i << ", j: " << j + << ", divergence A: " << outputDivergencesA_Host(ic,i,j) + << ", divergence B: " << outputDivergencesB_Host(i,j) + << ", |diff|: " << diff + << ", tol: " << tol + << std::endl; + } + } + } + } + } catch (std::exception &err) { + std::cout << "UNEXPECTED ERROR !!! ----------------------------------------------------------\n"; + std::cout << err.what() << '\n'; + std::cout << "-------------------------------------------------------------------------------" << "\n\n"; + errorFlag = -1000; + }; + + if (errorFlag != 0) + std::cout << "End Result: TEST FAILED\n"; + else + std::cout << "End Result: TEST PASSED\n"; + + return errorFlag; + } + } +} diff --git a/packages/intrepid2/unit-test/Discretization/Basis/HDIV_TRI_I1_FEM/CMakeLists.txt b/packages/intrepid2/unit-test/Discretization/Basis/HDIV_TRI_I1_FEM/CMakeLists.txt index 4f47ee20c141..581f594311e0 100644 --- a/packages/intrepid2/unit-test/Discretization/Basis/HDIV_TRI_I1_FEM/CMakeLists.txt +++ b/packages/intrepid2/unit-test/Discretization/Basis/HDIV_TRI_I1_FEM/CMakeLists.txt @@ -1,13 +1,18 @@ TRIBITS_INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}) + +# test +SET(Intrepid2_TEST_ETI_FILE "test_01") + # value types SET(Intrepid2_TEST_ETI_VALUETYPE_NAME "") SET(Intrepid2_TEST_ETI_VALUETYPE "") +SET(Intrepid2_TEST_ETI_SACADO "") LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE_NAME "DOUBLE") LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE "double") LIST(APPEND Intrepid2_TEST_ETI_SACADO "0") - + IF (HAVE_INTREPID2_SACADO) # LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE_NAME "DFAD_DOUBLE") # LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE "Sacado::Fad::DFad") @@ -17,9 +22,7 @@ ENDIF() LIST(LENGTH Intrepid2_TEST_ETI_VALUETYPE_NAME ETI_VALUETYPE_COUNT) MATH(EXPR ETI_VALUETYPE_COUNT "${ETI_VALUETYPE_COUNT}-1") -# Host test -SET(Intrepid2_TEST_ETI_FILE "test_01") - +# device SET(Intrepid2_TEST_ETI_DEVICE_NAME "") SET(Intrepid2_TEST_ETI_DEVICE "") IF(Kokkos_ENABLE_SERIAL) @@ -68,3 +71,76 @@ FOREACH(I RANGE ${ETI_DEVICE_COUNT}) ENDFOREACH() ENDFOREACH() + + + +# test +SET(Intrepid2_TEST_ETI_FILE "test_02") + +# value types +SET(Intrepid2_TEST_ETI_VALUETYPE_NAME "") +SET(Intrepid2_TEST_ETI_VALUETYPE "") +SET(Intrepid2_TEST_ETI_SACADO "") + +LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE_NAME "DOUBLE_DOUBLE") +LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE "double,double") +LIST(APPEND Intrepid2_TEST_ETI_SACADO "0") + +IF (HAVE_INTREPID2_SACADO) + LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE_NAME "DFAD_DFAD") + LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE "Sacado::Fad::DFad,Sacado::Fad::DFad ") + LIST(APPEND Intrepid2_TEST_ETI_SACADO "33") +ENDIF() + +LIST(LENGTH Intrepid2_TEST_ETI_VALUETYPE_NAME ETI_VALUETYPE_COUNT) +MATH(EXPR ETI_VALUETYPE_COUNT "${ETI_VALUETYPE_COUNT}-1") + +# device +SET(Intrepid2_TEST_ETI_DEVICE_NAME "") +SET(Intrepid2_TEST_ETI_DEVICE "") +IF(Kokkos_ENABLE_SERIAL) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "Serial") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() +IF(Kokkos_ENABLE_OPENMP) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "OpenMP") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() +IF(Kokkos_ENABLE_CUDA) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "CUDA") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() +IF(Kokkos_ENABLE_HIP) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "HIP") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() + +LIST(LENGTH Intrepid2_TEST_ETI_DEVICE_NAME ETI_DEVICE_COUNT) +MATH(EXPR ETI_DEVICE_COUNT "${ETI_DEVICE_COUNT}-1") + +FOREACH(I RANGE ${ETI_DEVICE_COUNT}) + LIST(GET Intrepid2_TEST_ETI_DEVICE_NAME ${I} ETI_DEVICE_NAME) + LIST(GET Intrepid2_TEST_ETI_DEVICE ${I} ETI_DEVICE) + FOREACH(J RANGE ${ETI_VALUETYPE_COUNT}) + LIST(GET Intrepid2_TEST_ETI_VALUETYPE_NAME ${J} ETI_VALUETYPE_NAME) + LIST(GET Intrepid2_TEST_ETI_VALUETYPE ${J} ETI_VALUETYPE) + LIST(GET Intrepid2_TEST_ETI_SACADO ${J} ETI_SACADO) + FOREACH(ETI_FILE IN LISTS Intrepid2_TEST_ETI_FILE) + SET(ETI_NAME "${ETI_FILE}_${ETI_DEVICE_NAME}_${ETI_VALUETYPE_NAME}") + MESSAGE(STATUS "Generating TEST: HDIV_TRI_I1_FEM ${ETI_NAME}.cpp") + CONFIGURE_FILE(eti/${ETI_FILE}_ETI.in ${ETI_NAME}.cpp) + + TRIBITS_ADD_EXECUTABLE_AND_TEST( + ${ETI_NAME} + SOURCES ${ETI_NAME}.cpp + ARGS PrintItAll + NUM_MPI_PROCS 1 + PASS_REGULAR_EXPRESSION "TEST PASSED" + ADD_DIR_TO_NAME + ) + + ENDFOREACH() + ENDFOREACH() +ENDFOREACH() + + diff --git a/packages/intrepid2/unit-test/Discretization/Basis/HDIV_TRI_I1_FEM/eti/test_02_ETI.in b/packages/intrepid2/unit-test/Discretization/Basis/HDIV_TRI_I1_FEM/eti/test_02_ETI.in new file mode 100644 index 000000000000..99b3fb273163 --- /dev/null +++ b/packages/intrepid2/unit-test/Discretization/Basis/HDIV_TRI_I1_FEM/eti/test_02_ETI.in @@ -0,0 +1,52 @@ +// @HEADER +// ***************************************************************************** +// Intrepid2 Package +// +// Copyright 2007 NTESS and the Intrepid2 contributors. +// SPDX-License-Identifier: BSD-3-Clause +// ***************************************************************************** +// @HEADER + +/** \file test_01.cpp + \brief Unit test of Intrepid2::Basis_HDIV_TRI_I1_FEM team-level getValues. + \author Kyungjoo Kim +*/ + +#include "Kokkos_Core.hpp" + +#define ETI_SACADO @ETI_SACADO@ +#if (ETI_SACADO != 0) /// SACADO +#include "Kokkos_ViewFactory.hpp" +#include "Sacado.hpp" +#endif + +#if (ETI_SACADO == 0) /// double double +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__) +#elif (ETI_SACADO == 11 /* SFAD SFAD */ || ETI_SACADO == 33 /* DFAD DFAD */) +constexpr int num_deriv = 3; +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#elif (ETI_SACADO == 23) +constexpr int num_deriv = 3; +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#elif (ETI_SACADO == 20) +constexpr int num_deriv = 2; +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__) +#endif + +#include "test_02.hpp" + +int main(int argc, char *argv[]) { + + const bool verbose = (argc-1) > 0; + Kokkos::initialize(); + + Intrepid2::Test::HDIV_TRI_I1_FEM_Test02<@ETI_VALUETYPE@,@ETI_DEVICE@>(verbose); + + Kokkos::finalize(); + return 0; +} + diff --git a/packages/intrepid2/unit-test/Discretization/Basis/HDIV_TRI_I1_FEM/test_02.hpp b/packages/intrepid2/unit-test/Discretization/Basis/HDIV_TRI_I1_FEM/test_02.hpp new file mode 100644 index 000000000000..15b4152a781a --- /dev/null +++ b/packages/intrepid2/unit-test/Discretization/Basis/HDIV_TRI_I1_FEM/test_02.hpp @@ -0,0 +1,185 @@ +// @HEADER +// ***************************************************************************** +// Intrepid2 Package +// +// Copyright 2007 NTESS and the Intrepid2 contributors. +// SPDX-License-Identifier: BSD-3-Clause +// ***************************************************************************** +// @HEADER + +/** \file test_02.hpp + \brief Unit tests for the Intrepid2::HDIV_TRI_I1_FEM class. + \author Created by Kyungjoo Kim, Mauro Perego + */ + + +#include "Intrepid2_config.h" +#include "Kokkos_Random.hpp" +#ifdef HAVE_INTREPID2_DEBUG +#define INTREPID2_TEST_FOR_DEBUG_ABORT_OVERRIDE_TO_CONTINUE +#endif + +#include "Intrepid2_Types.hpp" +#include "Intrepid2_Utils.hpp" + +#include "Intrepid2_HDIV_TRI_I1_FEM.hpp" +#include "packages/intrepid2/unit-test/Discretization/Basis/Setup.hpp" + +namespace Intrepid2 { + + namespace Test { + + // This test evaluates the basis functions at a set of points on a batch of cells using the team-level getValues, + // and compares the results with those obtained using the classic getValues function. + template + int HDIV_TRI_I1_FEM_Test02(const bool verbose) { + + //! Setup test output stream. + Teuchos::RCP outStream = setup_output_stream( + verbose, "HDIV_TRI_I1_FEM, Test 2", {} + ); + + *outStream + << "\n" + << "===============================================================================\n" + << "| Testing Team-level Implemntation of getValues |\n" + << "===============================================================================\n"; + + using DeviceSpaceType = typename DeviceType::execution_space; + Kokkos::print_configuration(std::cout, false); + + int errorFlag = 0; + + try { + using BasisType = Basis_HDIV_TRI_I1_FEM; + auto basisPtr = Teuchos::rcp(new BasisType()); + + const int ncells = 5, npts = 10, ndim = 2; + Kokkos::DynRankView ConstructWithLabelOutView(outputValuesA, ncells, basisPtr->getCardinality(), npts, ndim); + Kokkos::DynRankView ConstructWithLabelOutView(outputValuesB, basisPtr->getCardinality(), npts, ndim); + + Kokkos::DynRankView ConstructWithLabelOutView(outputDivergencesA, ncells, basisPtr->getCardinality(), npts); + Kokkos::DynRankView ConstructWithLabelOutView(outputDivergencesB, basisPtr->getCardinality(), npts); + + Kokkos::DynRankView ConstructWithLabelPointView(point, 1); + + using ScalarType = typename ScalarTraits::scalar_type; + + Kokkos::View inputPointsViewToUseRandom("inputPoints", npts*ndim*get_dimension_scalar(point)); + auto vcprop = Kokkos::common_view_alloc_prop(point); + Kokkos::DynRankView inputPoints (Kokkos::view_wrap(inputPointsViewToUseRandom.data(), vcprop), npts, ndim); + + // random values between (0,1) + Kokkos::Random_XorShift64_Pool random(13718); + Kokkos::fill_random(inputPointsViewToUseRandom, random, 1.0); + + + *outStream << "Computing values and divergences for " << ncells << " cells and " << npts << " points using team-level getValues function" <(*basisPtr); + auto basisRawPtr_device = basisPtr_device.get(); + + int scratch_space_level =1; + const int vectorSize = getVectorSizeForHierarchicalParallelism(); + Kokkos::TeamPolicy teamPolicy(ncells, Kokkos::AUTO,vectorSize); + + { //compute values + auto functor = KOKKOS_LAMBDA (typename Kokkos::TeamPolicy::member_type team_member) { + auto valsACell = Kokkos::subview(outputValuesA, team_member.league_rank(), Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL()); + basisRawPtr_device->getValues(valsACell, inputPoints, OPERATOR_VALUE, team_member, team_member.team_scratch(scratch_space_level)); + }; + + //Get the required size of the scratch space per team and per thread. + int perThreadSpaceSize(0), perTeamSpaceSize(0); + basisPtr->getScratchSpaceSize(perTeamSpaceSize,perThreadSpaceSize,inputPoints, OPERATOR_VALUE); + teamPolicy.set_scratch_size(scratch_space_level, Kokkos::PerTeam(perTeamSpaceSize), Kokkos::PerThread(perThreadSpaceSize)); + + Kokkos::parallel_for (teamPolicy,functor); + } + + { //compute divergences + auto functor = KOKKOS_LAMBDA (typename Kokkos::TeamPolicy::member_type team_member) { + auto divergencesACell = Kokkos::subview(outputDivergencesA, team_member.league_rank(), Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL()); + basisRawPtr_device->getValues(divergencesACell, inputPoints, OPERATOR_DIV, team_member, team_member.team_scratch(scratch_space_level)); + }; + + //Get the required size of the scratch space per team and per thread. + int perThreadSpaceSize(0), perTeamSpaceSize(0); + basisPtr->getScratchSpaceSize(perTeamSpaceSize,perThreadSpaceSize,inputPoints, OPERATOR_DIV); + teamPolicy.set_scratch_size(scratch_space_level, Kokkos::PerTeam(perTeamSpaceSize), Kokkos::PerThread(perThreadSpaceSize)); + + Kokkos::parallel_for (teamPolicy,functor); + } + } + + *outStream << "Computing values and divergences for " << npts << " points using high-level getValues function" <getValues(outputValuesB, inputPoints, OPERATOR_VALUE); + basisPtr->getValues(outputDivergencesB, inputPoints, OPERATOR_DIV); + + *outStream << "Comparing values and divergences on host" <(); + for (size_t ic=0;ic tol) { + ++errorFlag; + std::cout << ", ic: " << ic << ", i: " << i << ", j: " << j + << ", val A: [" << outputValuesA_Host(ic,i,j,0) << ", " << outputValuesA_Host(ic,i,j,1) << "]" + << ", val B: [" << outputValuesB_Host(i,j,0) << ", " << outputValuesB_Host(i,j,1) << "]" + << ", |diff|: " << diff + << ", tol: " << tol + << std::endl; + } + } + } + + { + // compare divergences + const auto outputDivergencesA_Host = Kokkos::create_mirror_view(outputDivergencesA); Kokkos::deep_copy(outputDivergencesA_Host, outputDivergencesA); + const auto outputDivergencesB_Host = Kokkos::create_mirror_view(outputDivergencesB); Kokkos::deep_copy(outputDivergencesB_Host, outputDivergencesB); + + OutValueType diff = 0; + auto tol = epsilon(); + for (size_t ic=0;ic tol) { + ++errorFlag; + std::cout << ", ic: " << ic << ", i: " << i << ", j: " << j + << ", divergence A: " << outputDivergencesA_Host(ic,i,j) + << ", divergence B: " << outputDivergencesB_Host(i,j) + << ", |diff|: " << diff + << ", tol: " << tol + << std::endl; + } + } + } + } catch (std::exception &err) { + std::cout << "UNEXPECTED ERROR !!! ----------------------------------------------------------\n"; + std::cout << err.what() << '\n'; + std::cout << "-------------------------------------------------------------------------------" << "\n\n"; + errorFlag = -1000; + }; + + if (errorFlag != 0) + std::cout << "End Result: TEST FAILED\n"; + else + std::cout << "End Result: TEST PASSED\n"; + + return errorFlag; + } + } +} diff --git a/packages/intrepid2/unit-test/Discretization/Basis/HDIV_TRI_In_FEM/CMakeLists.txt b/packages/intrepid2/unit-test/Discretization/Basis/HDIV_TRI_In_FEM/CMakeLists.txt index 4f11a0b1e70c..f06b5f1bb859 100644 --- a/packages/intrepid2/unit-test/Discretization/Basis/HDIV_TRI_In_FEM/CMakeLists.txt +++ b/packages/intrepid2/unit-test/Discretization/Basis/HDIV_TRI_In_FEM/CMakeLists.txt @@ -1,8 +1,13 @@ TRIBITS_INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}) + +# test +SET(Intrepid2_TEST_ETI_FILE "test_01") + # value types SET(Intrepid2_TEST_ETI_VALUETYPE_NAME "") SET(Intrepid2_TEST_ETI_VALUETYPE "") +SET(Intrepid2_TEST_ETI_SACADO "") LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE_NAME "DOUBLE_DOUBLE") LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE "double,double") @@ -32,9 +37,80 @@ ENDIF() LIST(LENGTH Intrepid2_TEST_ETI_VALUETYPE_NAME ETI_VALUETYPE_COUNT) MATH(EXPR ETI_VALUETYPE_COUNT "${ETI_VALUETYPE_COUNT}-1") +# device +SET(Intrepid2_TEST_ETI_DEVICE_NAME "") +SET(Intrepid2_TEST_ETI_DEVICE "") +IF(Kokkos_ENABLE_SERIAL) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "Serial") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() +IF(Kokkos_ENABLE_OPENMP) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "OpenMP") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() +IF(Kokkos_ENABLE_CUDA) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "CUDA") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() +IF(Kokkos_ENABLE_HIP) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "HIP") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() + +LIST(LENGTH Intrepid2_TEST_ETI_DEVICE_NAME ETI_DEVICE_COUNT) +MATH(EXPR ETI_DEVICE_COUNT "${ETI_DEVICE_COUNT}-1") + +FOREACH(I RANGE ${ETI_DEVICE_COUNT}) + LIST(GET Intrepid2_TEST_ETI_DEVICE_NAME ${I} ETI_DEVICE_NAME) + LIST(GET Intrepid2_TEST_ETI_DEVICE ${I} ETI_DEVICE) + #MESSAGE(STATUS "Generating TEST HDIV_TRI_In_FEM for ${ETI_DEVICE_NAME} with ${ETI_DEVICE}") + FOREACH(J RANGE ${ETI_VALUETYPE_COUNT}) + LIST(GET Intrepid2_TEST_ETI_VALUETYPE_NAME ${J} ETI_VALUETYPE_NAME) + LIST(GET Intrepid2_TEST_ETI_VALUETYPE ${J} ETI_VALUETYPE) + LIST(GET Intrepid2_TEST_ETI_SACADO ${J} ETI_SACADO) + FOREACH(ETI_FILE IN LISTS Intrepid2_TEST_ETI_FILE) + SET(ETI_NAME "${ETI_FILE}_${ETI_DEVICE_NAME}_${ETI_VALUETYPE_NAME}") + MESSAGE(STATUS "Generating TEST: HDIV_TRI_In_FEM ${ETI_NAME}.cpp") + CONFIGURE_FILE(eti/${ETI_FILE}_ETI.in ${ETI_NAME}.cpp) + + TRIBITS_ADD_EXECUTABLE_AND_TEST( + ${ETI_NAME} + SOURCES ${ETI_NAME}.cpp + ARGS PrintItAll + NUM_MPI_PROCS 1 + PASS_REGULAR_EXPRESSION "TEST PASSED" + ADD_DIR_TO_NAME + ) + + ENDFOREACH() + ENDFOREACH() +ENDFOREACH() + + + + # test -SET(Intrepid2_TEST_ETI_FILE "test_01") +SET(Intrepid2_TEST_ETI_FILE "test_02") +# value types +SET(Intrepid2_TEST_ETI_VALUETYPE_NAME "") +SET(Intrepid2_TEST_ETI_VALUETYPE "") +SET(Intrepid2_TEST_ETI_SACADO "") + +LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE_NAME "DOUBLE_DOUBLE") +LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE "double,double") +LIST(APPEND Intrepid2_TEST_ETI_SACADO "0") + +IF (HAVE_INTREPID2_SACADO) + LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE_NAME "DFAD_DFAD") + LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE "Sacado::Fad::DFad,Sacado::Fad::DFad ") + LIST(APPEND Intrepid2_TEST_ETI_SACADO "33") +ENDIF() + +LIST(LENGTH Intrepid2_TEST_ETI_VALUETYPE_NAME ETI_VALUETYPE_COUNT) +MATH(EXPR ETI_VALUETYPE_COUNT "${ETI_VALUETYPE_COUNT}-1") + +# device SET(Intrepid2_TEST_ETI_DEVICE_NAME "") SET(Intrepid2_TEST_ETI_DEVICE "") IF(Kokkos_ENABLE_SERIAL) @@ -60,7 +136,6 @@ MATH(EXPR ETI_DEVICE_COUNT "${ETI_DEVICE_COUNT}-1") FOREACH(I RANGE ${ETI_DEVICE_COUNT}) LIST(GET Intrepid2_TEST_ETI_DEVICE_NAME ${I} ETI_DEVICE_NAME) LIST(GET Intrepid2_TEST_ETI_DEVICE ${I} ETI_DEVICE) - #MESSAGE(STATUS "Generating TEST HDIV_TRI_In_FEM for ${ETI_DEVICE_NAME} with ${ETI_DEVICE}") FOREACH(J RANGE ${ETI_VALUETYPE_COUNT}) LIST(GET Intrepid2_TEST_ETI_VALUETYPE_NAME ${J} ETI_VALUETYPE_NAME) LIST(GET Intrepid2_TEST_ETI_VALUETYPE ${J} ETI_VALUETYPE) diff --git a/packages/intrepid2/unit-test/Discretization/Basis/HDIV_TRI_In_FEM/eti/test_02_ETI.in b/packages/intrepid2/unit-test/Discretization/Basis/HDIV_TRI_In_FEM/eti/test_02_ETI.in new file mode 100644 index 000000000000..060c322dc641 --- /dev/null +++ b/packages/intrepid2/unit-test/Discretization/Basis/HDIV_TRI_In_FEM/eti/test_02_ETI.in @@ -0,0 +1,52 @@ +// @HEADER +// ***************************************************************************** +// Intrepid2 Package +// +// Copyright 2007 NTESS and the Intrepid2 contributors. +// SPDX-License-Identifier: BSD-3-Clause +// ***************************************************************************** +// @HEADER + +/** \file test_01.cpp + \brief Unit test of Intrepid2::Basis_HDIV_TRI_In_FEM team-level getValues. + \author Kyungjoo Kim +*/ + +#include "Kokkos_Core.hpp" + +#define ETI_SACADO @ETI_SACADO@ +#if (ETI_SACADO != 0) /// SACADO +#include "Kokkos_ViewFactory.hpp" +#include "Sacado.hpp" +#endif + +#if (ETI_SACADO == 0) /// double double +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__) +#elif (ETI_SACADO == 11 /* SFAD SFAD */ || ETI_SACADO == 33 /* DFAD DFAD */) +constexpr int num_deriv = 3; +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#elif (ETI_SACADO == 23) +constexpr int num_deriv = 3; +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#elif (ETI_SACADO == 20) +constexpr int num_deriv = 2; +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__) +#endif + +#include "test_02.hpp" + +int main(int argc, char *argv[]) { + + const bool verbose = (argc-1) > 0; + Kokkos::initialize(); + + Intrepid2::Test::HDIV_TRI_In_FEM_Test02<@ETI_VALUETYPE@,@ETI_DEVICE@>(verbose); + + Kokkos::finalize(); + return 0; +} + diff --git a/packages/intrepid2/unit-test/Discretization/Basis/HDIV_TRI_In_FEM/test_02.hpp b/packages/intrepid2/unit-test/Discretization/Basis/HDIV_TRI_In_FEM/test_02.hpp new file mode 100644 index 000000000000..1d3c940090d7 --- /dev/null +++ b/packages/intrepid2/unit-test/Discretization/Basis/HDIV_TRI_In_FEM/test_02.hpp @@ -0,0 +1,189 @@ +// @HEADER +// ***************************************************************************** +// Intrepid2 Package +// +// Copyright 2007 NTESS and the Intrepid2 contributors. +// SPDX-License-Identifier: BSD-3-Clause +// ***************************************************************************** +// @HEADER + +/** \file test_02.hpp + \brief Unit tests for the Intrepid2::HDIV_TRI_In_FEM class. + \author Created by Kyungjoo Kim, Mauro Perego + */ + + +#include "Intrepid2_config.h" +#include "Kokkos_Random.hpp" +#ifdef HAVE_INTREPID2_DEBUG +#define INTREPID2_TEST_FOR_DEBUG_ABORT_OVERRIDE_TO_CONTINUE +#endif + +#include "Intrepid2_Types.hpp" +#include "Intrepid2_Utils.hpp" + +#include "Intrepid2_HDIV_TRI_In_FEM.hpp" +#include "packages/intrepid2/unit-test/Discretization/Basis/Setup.hpp" + +namespace Intrepid2 { + + namespace Test { + + // This test evaluates the basis functions at a set of points on a batch of cells using the team-level getValues, + // and compares the results with those obtained using the classic getValues function. + template + int HDIV_TRI_In_FEM_Test02(const bool verbose) { + + //! Setup test output stream. + Teuchos::RCP outStream = setup_output_stream( + verbose, "HDIV_TRI_In_FEM, Test 2", {} + ); + + *outStream + << "\n" + << "===============================================================================\n" + << "| Testing Team-level Implemntation of getValues |\n" + << "===============================================================================\n"; + + using DeviceSpaceType = typename DeviceType::execution_space; + Kokkos::print_configuration(std::cout, false); + + int errorFlag = 0; + constexpr int maxOrder = 9; + try { + for (int order=1;order<=maxOrder;++order) { + using BasisType = Basis_HDIV_TRI_In_FEM; + auto basisPtr = Teuchos::rcp(new BasisType(order)); + + const int ncells = 5, npts = 10, ndim = 2; + Kokkos::DynRankView ConstructWithLabelOutView(outputValuesA, ncells, basisPtr->getCardinality(), npts, ndim); + Kokkos::DynRankView ConstructWithLabelOutView(outputValuesB, basisPtr->getCardinality(), npts, ndim); + + Kokkos::DynRankView ConstructWithLabelOutView(outputDivergencesA, ncells, basisPtr->getCardinality(), npts); + Kokkos::DynRankView ConstructWithLabelOutView(outputDivergencesB, basisPtr->getCardinality(), npts); + + Kokkos::DynRankView ConstructWithLabelPointView(point, 1); + + using ScalarType = typename ScalarTraits::scalar_type; + + Kokkos::View inputPointsViewToUseRandom("inputPoints", npts*ndim*get_dimension_scalar(point)); + auto vcprop = Kokkos::common_view_alloc_prop(point); + Kokkos::DynRankView inputPoints (Kokkos::view_wrap(inputPointsViewToUseRandom.data(), vcprop), npts, ndim); + + // random values between (0,1) + Kokkos::Random_XorShift64_Pool random(13718); + Kokkos::fill_random(inputPointsViewToUseRandom, random, 1.0); + + + *outStream << "Order: " << order << ": Computing values and divergences for " << ncells << " cells and " << npts << " points using team-level getValues function" <(*basisPtr); + auto basisRawPtr_device = basisPtr_device.get(); + + int scratch_space_level =1; + const int vectorSize = getVectorSizeForHierarchicalParallelism(); + Kokkos::TeamPolicy teamPolicy(ncells, Kokkos::AUTO,vectorSize); + + { //compute values + auto functor = KOKKOS_LAMBDA (typename Kokkos::TeamPolicy::member_type team_member) { + auto valsACell = Kokkos::subview(outputValuesA, team_member.league_rank(), Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL()); + basisRawPtr_device->getValues(valsACell, inputPoints, OPERATOR_VALUE, team_member, team_member.team_scratch(scratch_space_level)); + }; + + //Get the required size of the scratch space per team and per thread. + int perThreadSpaceSize(0), perTeamSpaceSize(0); + basisPtr->getScratchSpaceSize(perTeamSpaceSize,perThreadSpaceSize,inputPoints, OPERATOR_VALUE); + teamPolicy.set_scratch_size(scratch_space_level, Kokkos::PerTeam(perTeamSpaceSize), Kokkos::PerThread(perThreadSpaceSize)); + + Kokkos::parallel_for (teamPolicy,functor); + } + + { //compute divergences + auto functor = KOKKOS_LAMBDA (typename Kokkos::TeamPolicy::member_type team_member) { + auto divergencesACell = Kokkos::subview(outputDivergencesA, team_member.league_rank(), Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL()); + basisRawPtr_device->getValues(divergencesACell, inputPoints, OPERATOR_DIV, team_member, team_member.team_scratch(scratch_space_level)); + }; + + //Get the required size of the scratch space per team and per thread. + int perThreadSpaceSize(0), perTeamSpaceSize(0); + basisPtr->getScratchSpaceSize(perTeamSpaceSize,perThreadSpaceSize,inputPoints, OPERATOR_DIV); + teamPolicy.set_scratch_size(scratch_space_level, Kokkos::PerTeam(perTeamSpaceSize), Kokkos::PerThread(perThreadSpaceSize)); + + Kokkos::parallel_for (teamPolicy,functor); + } + } + + *outStream << "Order: " << order << ": Computing values and divergences for " << npts << " points using high-level getValues function" <getValues(outputValuesB, inputPoints, OPERATOR_VALUE); + basisPtr->getValues(outputDivergencesB, inputPoints, OPERATOR_DIV); + + *outStream << "Order: " << order << ": Comparing values and divergences on host" <(); + for (size_t ic=0;ic tol) { + ++errorFlag; + std::cout << " order: " << order + << ", ic: " << ic << ", i: " << i << ", j: " << j + << ", val A: [" << outputValuesA_Host(ic,i,j,0) << ", " << outputValuesA_Host(ic,i,j,1) << "]" + << ", val B: [" << outputValuesB_Host(i,j,0) << ", " << outputValuesB_Host(i,j,1) << "]" + << ", |diff|: " << diff + << ", tol: " << tol + << std::endl; + } + } + } + + { + // compare divergences + const auto outputDivergencesA_Host = Kokkos::create_mirror_view(outputDivergencesA); Kokkos::deep_copy(outputDivergencesA_Host, outputDivergencesA); + const auto outputDivergencesB_Host = Kokkos::create_mirror_view(outputDivergencesB); Kokkos::deep_copy(outputDivergencesB_Host, outputDivergencesB); + + OutValueType diff = 0; + auto tol = epsilon(); + for (size_t ic=0;ic tol) { + ++errorFlag; + std::cout << " order: " << order + << ", ic: " << ic << ", i: " << i << ", j: " << j + << ", divergence A: " << outputDivergencesA_Host(ic,i,j) + << ", divergence B: " << outputDivergencesB_Host(i,j) + << ", |diff|: " << diff + << ", tol: " << tol + << std::endl; + } + } + } + } + } catch (std::exception &err) { + std::cout << "UNEXPECTED ERROR !!! ----------------------------------------------------------\n"; + std::cout << err.what() << '\n'; + std::cout << "-------------------------------------------------------------------------------" << "\n\n"; + errorFlag = -1000; + }; + + if (errorFlag != 0) + std::cout << "End Result: TEST FAILED\n"; + else + std::cout << "End Result: TEST PASSED\n"; + + return errorFlag; + } + } +} diff --git a/packages/intrepid2/unit-test/Discretization/Basis/HDIV_WEDGE_I1_FEM/CMakeLists.txt b/packages/intrepid2/unit-test/Discretization/Basis/HDIV_WEDGE_I1_FEM/CMakeLists.txt index 67fcf71311f7..d801c634869e 100644 --- a/packages/intrepid2/unit-test/Discretization/Basis/HDIV_WEDGE_I1_FEM/CMakeLists.txt +++ b/packages/intrepid2/unit-test/Discretization/Basis/HDIV_WEDGE_I1_FEM/CMakeLists.txt @@ -1,8 +1,13 @@ TRIBITS_INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}) + +# test +SET(Intrepid2_TEST_ETI_FILE "test_01") + # value types SET(Intrepid2_TEST_ETI_VALUETYPE_NAME "") SET(Intrepid2_TEST_ETI_VALUETYPE "") +SET(Intrepid2_TEST_ETI_SACADO "") LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE_NAME "DOUBLE") LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE "double") @@ -17,9 +22,7 @@ ENDIF() LIST(LENGTH Intrepid2_TEST_ETI_VALUETYPE_NAME ETI_VALUETYPE_COUNT) MATH(EXPR ETI_VALUETYPE_COUNT "${ETI_VALUETYPE_COUNT}-1") -# Host test -SET(Intrepid2_TEST_ETI_FILE "test_01") - +# device SET(Intrepid2_TEST_ETI_DEVICE_NAME "") SET(Intrepid2_TEST_ETI_DEVICE "") IF(Kokkos_ENABLE_SERIAL) @@ -68,3 +71,75 @@ FOREACH(I RANGE ${ETI_DEVICE_COUNT}) ENDFOREACH() ENDFOREACH() + + + +# test +SET(Intrepid2_TEST_ETI_FILE "test_02") + +# value types +SET(Intrepid2_TEST_ETI_VALUETYPE_NAME "") +SET(Intrepid2_TEST_ETI_VALUETYPE "") +SET(Intrepid2_TEST_ETI_SACADO "") + +LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE_NAME "DOUBLE_DOUBLE") +LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE "double,double") +LIST(APPEND Intrepid2_TEST_ETI_SACADO "0") + +IF (HAVE_INTREPID2_SACADO) + LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE_NAME "DFAD_DFAD") + LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE "Sacado::Fad::DFad,Sacado::Fad::DFad ") + LIST(APPEND Intrepid2_TEST_ETI_SACADO "33") +ENDIF() + +LIST(LENGTH Intrepid2_TEST_ETI_VALUETYPE_NAME ETI_VALUETYPE_COUNT) +MATH(EXPR ETI_VALUETYPE_COUNT "${ETI_VALUETYPE_COUNT}-1") + +# device +SET(Intrepid2_TEST_ETI_DEVICE_NAME "") +SET(Intrepid2_TEST_ETI_DEVICE "") +IF(Kokkos_ENABLE_SERIAL) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "Serial") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() +IF(Kokkos_ENABLE_OPENMP) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "OpenMP") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() +IF(Kokkos_ENABLE_CUDA) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "CUDA") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() +IF(Kokkos_ENABLE_HIP) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "HIP") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() + +LIST(LENGTH Intrepid2_TEST_ETI_DEVICE_NAME ETI_DEVICE_COUNT) +MATH(EXPR ETI_DEVICE_COUNT "${ETI_DEVICE_COUNT}-1") + +FOREACH(I RANGE ${ETI_DEVICE_COUNT}) + LIST(GET Intrepid2_TEST_ETI_DEVICE_NAME ${I} ETI_DEVICE_NAME) + LIST(GET Intrepid2_TEST_ETI_DEVICE ${I} ETI_DEVICE) + FOREACH(J RANGE ${ETI_VALUETYPE_COUNT}) + LIST(GET Intrepid2_TEST_ETI_VALUETYPE_NAME ${J} ETI_VALUETYPE_NAME) + LIST(GET Intrepid2_TEST_ETI_VALUETYPE ${J} ETI_VALUETYPE) + LIST(GET Intrepid2_TEST_ETI_SACADO ${J} ETI_SACADO) + FOREACH(ETI_FILE IN LISTS Intrepid2_TEST_ETI_FILE) + SET(ETI_NAME "${ETI_FILE}_${ETI_DEVICE_NAME}_${ETI_VALUETYPE_NAME}") + MESSAGE(STATUS "Generating TEST: HDIV_WEDGE_In_FEM ${ETI_NAME}.cpp") + CONFIGURE_FILE(eti/${ETI_FILE}_ETI.in ${ETI_NAME}.cpp) + + TRIBITS_ADD_EXECUTABLE_AND_TEST( + ${ETI_NAME} + SOURCES ${ETI_NAME}.cpp + ARGS PrintItAll + NUM_MPI_PROCS 1 + PASS_REGULAR_EXPRESSION "TEST PASSED" + ADD_DIR_TO_NAME + ) + + ENDFOREACH() + ENDFOREACH() +ENDFOREACH() + diff --git a/packages/intrepid2/unit-test/Discretization/Basis/HDIV_WEDGE_I1_FEM/eti/test_02_ETI.in b/packages/intrepid2/unit-test/Discretization/Basis/HDIV_WEDGE_I1_FEM/eti/test_02_ETI.in new file mode 100644 index 000000000000..16906a746c00 --- /dev/null +++ b/packages/intrepid2/unit-test/Discretization/Basis/HDIV_WEDGE_I1_FEM/eti/test_02_ETI.in @@ -0,0 +1,52 @@ +// @HEADER +// ***************************************************************************** +// Intrepid2 Package +// +// Copyright 2007 NTESS and the Intrepid2 contributors. +// SPDX-License-Identifier: BSD-3-Clause +// ***************************************************************************** +// @HEADER + +/** \file test_01.cpp + \brief Unit test of Intrepid2::Basis_HDIV_WEDGE_I1_FEM team-level getValues. + \author Kyungjoo Kim +*/ + +#include "Kokkos_Core.hpp" + +#define ETI_SACADO @ETI_SACADO@ +#if (ETI_SACADO != 0) /// SACADO +#include "Kokkos_ViewFactory.hpp" +#include "Sacado.hpp" +#endif + +#if (ETI_SACADO == 0) /// double double +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__) +#elif (ETI_SACADO == 11 /* SFAD SFAD */ || ETI_SACADO == 33 /* DFAD DFAD */) +constexpr int num_deriv = 3; +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#elif (ETI_SACADO == 23) +constexpr int num_deriv = 3; +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#elif (ETI_SACADO == 20) +constexpr int num_deriv = 2; +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__) +#endif + +#include "test_02.hpp" + +int main(int argc, char *argv[]) { + + const bool verbose = (argc-1) > 0; + Kokkos::initialize(); + + Intrepid2::Test::HDIV_WEDGE_I1_FEM_Test02<@ETI_VALUETYPE@,@ETI_DEVICE@>(verbose); + + Kokkos::finalize(); + return 0; +} + diff --git a/packages/intrepid2/unit-test/Discretization/Basis/HDIV_WEDGE_I1_FEM/test_02.hpp b/packages/intrepid2/unit-test/Discretization/Basis/HDIV_WEDGE_I1_FEM/test_02.hpp new file mode 100644 index 000000000000..c991769a4852 --- /dev/null +++ b/packages/intrepid2/unit-test/Discretization/Basis/HDIV_WEDGE_I1_FEM/test_02.hpp @@ -0,0 +1,185 @@ +// @HEADER +// ***************************************************************************** +// Intrepid2 Package +// +// Copyright 2007 NTESS and the Intrepid2 contributors. +// SPDX-License-Identifier: BSD-3-Clause +// ***************************************************************************** +// @HEADER + +/** \file test_02.hpp + \brief Unit tests for the Intrepid2::HDIV_WEDGE_I1_FEM class. + \author Created by Kyungjoo Kim, Mauro Perego + */ + + +#include "Intrepid2_config.h" +#include "Kokkos_Random.hpp" +#ifdef HAVE_INTREPID2_DEBUG +#define INTREPID2_TEST_FOR_DEBUG_ABORT_OVERRIDE_TO_CONTINUE +#endif + +#include "Intrepid2_Types.hpp" +#include "Intrepid2_Utils.hpp" + +#include "Intrepid2_HDIV_WEDGE_I1_FEM.hpp" +#include "packages/intrepid2/unit-test/Discretization/Basis/Setup.hpp" + +namespace Intrepid2 { + + namespace Test { + + // This test evaluates the basis functions at a set of points on a batch of cells using the team-level getValues, + // and compares the results with those obtained using the classic getValues function. + template + int HDIV_WEDGE_I1_FEM_Test02(const bool verbose) { + + //! Setup test output stream. + Teuchos::RCP outStream = setup_output_stream( + verbose, "HDIV_WEDGE_I1_FEM, Test 2", {} + ); + + *outStream + << "\n" + << "===============================================================================\n" + << "| Testing Team-level Implemntation of getValues |\n" + << "===============================================================================\n"; + + using DeviceSpaceType = typename DeviceType::execution_space; + Kokkos::print_configuration(std::cout, false); + + int errorFlag = 0; + + try { + using BasisType = Basis_HDIV_WEDGE_I1_FEM; + auto basisPtr = Teuchos::rcp(new BasisType()); + + const int ncells = 5, npts = 10, ndim = 3; + Kokkos::DynRankView ConstructWithLabelOutView(outputValuesA, ncells, basisPtr->getCardinality(), npts, ndim); + Kokkos::DynRankView ConstructWithLabelOutView(outputValuesB, basisPtr->getCardinality(), npts, ndim); + + Kokkos::DynRankView ConstructWithLabelOutView(outputDivergencesA, ncells, basisPtr->getCardinality(), npts); + Kokkos::DynRankView ConstructWithLabelOutView(outputDivergencesB, basisPtr->getCardinality(), npts); + + Kokkos::DynRankView ConstructWithLabelPointView(point, 1); + + using ScalarType = typename ScalarTraits::scalar_type; + + Kokkos::View inputPointsViewToUseRandom("inputPoints", npts*ndim*get_dimension_scalar(point)); + auto vcprop = Kokkos::common_view_alloc_prop(point); + Kokkos::DynRankView inputPoints (Kokkos::view_wrap(inputPointsViewToUseRandom.data(), vcprop), npts, ndim); + + // random values between (0,1) + Kokkos::Random_XorShift64_Pool random(13718); + Kokkos::fill_random(inputPointsViewToUseRandom, random, 1.0); + + + *outStream << "Computing values and divergences for " << ncells << " cells and " << npts << " points using team-level getValues function" <(*basisPtr); + auto basisRawPtr_device = basisPtr_device.get(); + + int scratch_space_level =1; + const int vectorSize = getVectorSizeForHierarchicalParallelism(); + Kokkos::TeamPolicy teamPolicy(ncells, Kokkos::AUTO,vectorSize); + + { //compute values + auto functor = KOKKOS_LAMBDA (typename Kokkos::TeamPolicy::member_type team_member) { + auto valsACell = Kokkos::subview(outputValuesA, team_member.league_rank(), Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL()); + basisRawPtr_device->getValues(valsACell, inputPoints, OPERATOR_VALUE, team_member, team_member.team_scratch(scratch_space_level)); + }; + + //Get the required size of the scratch space per team and per thread. + int perThreadSpaceSize(0), perTeamSpaceSize(0); + basisPtr->getScratchSpaceSize(perTeamSpaceSize,perThreadSpaceSize,inputPoints, OPERATOR_VALUE); + teamPolicy.set_scratch_size(scratch_space_level, Kokkos::PerTeam(perTeamSpaceSize), Kokkos::PerThread(perThreadSpaceSize)); + + Kokkos::parallel_for (teamPolicy,functor); + } + + { //compute divergences + auto functor = KOKKOS_LAMBDA (typename Kokkos::TeamPolicy::member_type team_member) { + auto divergencesACell = Kokkos::subview(outputDivergencesA, team_member.league_rank(), Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL()); + basisRawPtr_device->getValues(divergencesACell, inputPoints, OPERATOR_DIV, team_member, team_member.team_scratch(scratch_space_level)); + }; + + //Get the required size of the scratch space per team and per thread. + int perThreadSpaceSize(0), perTeamSpaceSize(0); + basisPtr->getScratchSpaceSize(perTeamSpaceSize,perThreadSpaceSize,inputPoints, OPERATOR_DIV); + teamPolicy.set_scratch_size(scratch_space_level, Kokkos::PerTeam(perTeamSpaceSize), Kokkos::PerThread(perThreadSpaceSize)); + + Kokkos::parallel_for (teamPolicy,functor); + } + } + + *outStream << "Computing values and divergences for " << npts << " points using high-level getValues function" <getValues(outputValuesB, inputPoints, OPERATOR_VALUE); + basisPtr->getValues(outputDivergencesB, inputPoints, OPERATOR_DIV); + + *outStream << "Comparing values and divergences on host" <(); + for (size_t ic=0;ic tol) { + ++errorFlag; + std::cout << ", ic: " << ic << ", i: " << i << ", j: " << j + << ", val A: [" << outputValuesA_Host(ic,i,j,0) << ", " << outputValuesA_Host(ic,i,j,1) << ", " << outputValuesA_Host(ic,i,j,2) << "]" + << ", val B: [" << outputValuesB_Host(i,j,0) << ", " << outputValuesB_Host(i,j,1) << ", " << outputValuesB_Host(i,j,2) << "]" + << ", |diff|: " << diff + << ", tol: " << tol + << std::endl; + } + } + } + + { + // compare divergences + const auto outputDivergencesA_Host = Kokkos::create_mirror_view(outputDivergencesA); Kokkos::deep_copy(outputDivergencesA_Host, outputDivergencesA); + const auto outputDivergencesB_Host = Kokkos::create_mirror_view(outputDivergencesB); Kokkos::deep_copy(outputDivergencesB_Host, outputDivergencesB); + + OutValueType diff = 0; + auto tol = epsilon(); + for (size_t ic=0;ic tol) { + ++errorFlag; + std::cout << ", ic: " << ic << ", i: " << i << ", j: " << j + << ", divergence A: " << outputDivergencesA_Host(ic,i,j) + << ", divergence B: " << outputDivergencesB_Host(i,j) + << ", |diff|: " << diff + << ", tol: " << tol + << std::endl; + } + } + } + } catch (std::exception &err) { + std::cout << "UNEXPECTED ERROR !!! ----------------------------------------------------------\n"; + std::cout << err.what() << '\n'; + std::cout << "-------------------------------------------------------------------------------" << "\n\n"; + errorFlag = -1000; + }; + + if (errorFlag != 0) + std::cout << "End Result: TEST FAILED\n"; + else + std::cout << "End Result: TEST PASSED\n"; + + return errorFlag; + } + } +} diff --git a/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_HEX_C1_FEM/CMakeLists.txt b/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_HEX_C1_FEM/CMakeLists.txt index 88da0999c2ab..4982bd4f8dff 100644 --- a/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_HEX_C1_FEM/CMakeLists.txt +++ b/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_HEX_C1_FEM/CMakeLists.txt @@ -3,6 +3,7 @@ TRIBITS_INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}) # value types SET(Intrepid2_TEST_ETI_VALUETYPE_NAME "") SET(Intrepid2_TEST_ETI_VALUETYPE "") +SET(Intrepid2_TEST_ETI_SACADO "") LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE_NAME "DOUBLE") LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE "double") @@ -67,6 +68,7 @@ SET(Intrepid2_TEST_ETI_FILE "test_01") SET(Intrepid2_TEST_ETI_DEVICE_NAME "") SET(Intrepid2_TEST_ETI_DEVICE "") + IF(Kokkos_ENABLE_CUDA) LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "CUDA") LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") @@ -106,3 +108,75 @@ IF (${ETI_DEVICE_COUNT} GREATER_EQUAL 0) ENDFOREACH() ENDFOREACH() ENDIF() + + + +# test +SET(Intrepid2_TEST_ETI_FILE "test_03") + +# value types +SET(Intrepid2_TEST_ETI_VALUETYPE_NAME "") +SET(Intrepid2_TEST_ETI_VALUETYPE "") +SET(Intrepid2_TEST_ETI_SACADO "") + +LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE_NAME "DOUBLE_DOUBLE") +LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE "double,double") +LIST(APPEND Intrepid2_TEST_ETI_SACADO "0") + +IF (HAVE_INTREPID2_SACADO) + LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE_NAME "DFAD_DFAD") + LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE "Sacado::Fad::DFad,Sacado::Fad::DFad ") + LIST(APPEND Intrepid2_TEST_ETI_SACADO "33") +ENDIF() + +LIST(LENGTH Intrepid2_TEST_ETI_VALUETYPE_NAME ETI_VALUETYPE_COUNT) +MATH(EXPR ETI_VALUETYPE_COUNT "${ETI_VALUETYPE_COUNT}-1") + +# device +SET(Intrepid2_TEST_ETI_DEVICE_NAME "") +SET(Intrepid2_TEST_ETI_DEVICE "") +IF(Kokkos_ENABLE_SERIAL) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "Serial") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() +IF(Kokkos_ENABLE_OPENMP) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "OpenMP") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() +IF(Kokkos_ENABLE_CUDA) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "CUDA") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() +IF(Kokkos_ENABLE_HIP) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "HIP") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() + +LIST(LENGTH Intrepid2_TEST_ETI_DEVICE_NAME ETI_DEVICE_COUNT) +MATH(EXPR ETI_DEVICE_COUNT "${ETI_DEVICE_COUNT}-1") + +FOREACH(I RANGE ${ETI_DEVICE_COUNT}) + LIST(GET Intrepid2_TEST_ETI_DEVICE_NAME ${I} ETI_DEVICE_NAME) + LIST(GET Intrepid2_TEST_ETI_DEVICE ${I} ETI_DEVICE) + #MESSAGE(STATUS "Generating TEST HGRAD_HEX_C1_FEM for ${ETI_DEVICE_NAME} with ${ETI_DEVICE}") + FOREACH(J RANGE ${ETI_VALUETYPE_COUNT}) + LIST(GET Intrepid2_TEST_ETI_VALUETYPE_NAME ${J} ETI_VALUETYPE_NAME) + LIST(GET Intrepid2_TEST_ETI_VALUETYPE ${J} ETI_VALUETYPE) + LIST(GET Intrepid2_TEST_ETI_SACADO ${J} ETI_SACADO) + FOREACH(ETI_FILE IN LISTS Intrepid2_TEST_ETI_FILE) + SET(ETI_NAME "${ETI_FILE}_${ETI_DEVICE_NAME}_${ETI_VALUETYPE_NAME}") + MESSAGE(STATUS "Generating TEST: HGRAD_HEX_C1_FEM ${ETI_NAME}.cpp") + CONFIGURE_FILE(eti/${ETI_FILE}_ETI.in ${ETI_NAME}.cpp) + + TRIBITS_ADD_EXECUTABLE_AND_TEST( + ${ETI_NAME} + SOURCES ${ETI_NAME}.cpp + ARGS PrintItAll + NUM_MPI_PROCS 1 + PASS_REGULAR_EXPRESSION "TEST PASSED" + ADD_DIR_TO_NAME + ) + + ENDFOREACH() + ENDFOREACH() +ENDFOREACH() diff --git a/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_HEX_C1_FEM/eti/test_03_ETI.in b/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_HEX_C1_FEM/eti/test_03_ETI.in new file mode 100644 index 000000000000..a88bf31183c7 --- /dev/null +++ b/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_HEX_C1_FEM/eti/test_03_ETI.in @@ -0,0 +1,52 @@ +// @HEADER +// ***************************************************************************** +// Intrepid2 Package +// +// Copyright 2007 NTESS and the Intrepid2 contributors. +// SPDX-License-Identifier: BSD-3-Clause +// ***************************************************************************** +// @HEADER + +/** \file test_03.cpp + \brief Unit test of Intrepid2::Basis_HGRAD_HEX_C1_FEM team-level getValues. + \author Kyungjoo Kim +*/ + +#include "Kokkos_Core.hpp" + +#define ETI_SACADO @ETI_SACADO@ +#if (ETI_SACADO != 0) /// SACADO +#include "Kokkos_ViewFactory.hpp" +#include "Sacado.hpp" +#endif + +#if (ETI_SACADO == 0) /// double double +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__) +#elif (ETI_SACADO == 11 /* SFAD SFAD */ || ETI_SACADO == 33 /* DFAD DFAD */) +constexpr int num_deriv = 3; +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#elif (ETI_SACADO == 23) +constexpr int num_deriv = 3; +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#elif (ETI_SACADO == 20) +constexpr int num_deriv = 2; +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__) +#endif + +#include "test_03.hpp" + +int main(int argc, char *argv[]) { + + const bool verbose = (argc-1) > 0; + Kokkos::initialize(); + + Intrepid2::Test::HGRAD_HEX_C1_FEM_Test03<@ETI_VALUETYPE@,@ETI_DEVICE@>(verbose); + + Kokkos::finalize(); + return 0; +} + diff --git a/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_HEX_C1_FEM/test_03.hpp b/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_HEX_C1_FEM/test_03.hpp new file mode 100644 index 000000000000..9d326a80cf33 --- /dev/null +++ b/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_HEX_C1_FEM/test_03.hpp @@ -0,0 +1,184 @@ +// @HEADER +// ***************************************************************************** +// Intrepid2 Package +// +// Copyright 2007 NTESS and the Intrepid2 contributors. +// SPDX-License-Identifier: BSD-3-Clause +// ***************************************************************************** +// @HEADER + +/** \file test_03.hpp + \brief Unit tests for the Intrepid2::HGRAD_HEX_C1_FEM class. + \author Created by Kyungjoo Kim, Mauro Perego + */ + + +#include "Intrepid2_config.h" +#include "Kokkos_Random.hpp" +#ifdef HAVE_INTREPID2_DEBUG +#define INTREPID2_TEST_FOR_DEBUG_ABORT_OVERRIDE_TO_CONTINUE +#endif + +#include "Intrepid2_Types.hpp" +#include "Intrepid2_Utils.hpp" + +#include "Intrepid2_HGRAD_HEX_C1_FEM.hpp" +#include "packages/intrepid2/unit-test/Discretization/Basis/Setup.hpp" + +namespace Intrepid2 { + + namespace Test { + + // This test evaluates the basis functions at a set of points on a batch of cells using the team-level getValues, + // and compares the results with those obtained using the classic getValues function. + template + int HGRAD_HEX_C1_FEM_Test03(const bool verbose) { + + //! Setup test output stream. + Teuchos::RCP outStream = setup_output_stream( + verbose, "HGRAD_HEX_C1_FEM, Test 3", {} + ); + + *outStream + << "\n" + << "===============================================================================\n" + << "| Testing Team-level Implemntation of getValues |\n" + << "===============================================================================\n"; + + using DeviceSpaceType = typename DeviceType::execution_space; + Kokkos::print_configuration(std::cout, false); + + int errorFlag = 0; + + try { + using BasisType = Basis_HGRAD_HEX_C1_FEM; + auto basisPtr = Teuchos::rcp(new BasisType()); + + const int ncells = 5, npts = 10, ndim = 3; + Kokkos::DynRankView ConstructWithLabelOutView(outputValuesA, ncells, basisPtr->getCardinality(), npts); + Kokkos::DynRankView ConstructWithLabelOutView(outputValuesB, basisPtr->getCardinality(), npts); + + Kokkos::DynRankView ConstructWithLabelOutView(outputGradsA, ncells, basisPtr->getCardinality(), npts, ndim); + Kokkos::DynRankView ConstructWithLabelOutView(outputGradsB, basisPtr->getCardinality(), npts, ndim); + Kokkos::DynRankView ConstructWithLabelPointView(point, 1); + + using ScalarType = typename ScalarTraits::scalar_type; + + Kokkos::View inputPointsViewToUseRandom("inputPoints", npts*ndim*get_dimension_scalar(point)); + auto vcprop = Kokkos::common_view_alloc_prop(point); + Kokkos::DynRankView inputPoints (Kokkos::view_wrap(inputPointsViewToUseRandom.data(), vcprop), npts, ndim); + + // random values between (0,1) + Kokkos::Random_XorShift64_Pool random(13718); + Kokkos::fill_random(inputPointsViewToUseRandom, random, 1.0); + + + *outStream << "Computing values and gradients for " << ncells << " cells and " << npts << " points using team-level getValues function" <(*basisPtr); + auto basisRawPtr_device = basisPtr_device.get(); + + int scratch_space_level =1; + const int vectorSize = getVectorSizeForHierarchicalParallelism(); + Kokkos::TeamPolicy teamPolicy(ncells, Kokkos::AUTO,vectorSize); + + { //compute values + auto functor = KOKKOS_LAMBDA (typename Kokkos::TeamPolicy::member_type team_member) { + auto valsACell = Kokkos::subview(outputValuesA, team_member.league_rank(), Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL()); + basisRawPtr_device->getValues(valsACell, inputPoints, OPERATOR_VALUE, team_member, team_member.team_scratch(scratch_space_level)); + }; + + //Get the required size of the scratch space per team and per thread. + int perThreadSpaceSize(0), perTeamSpaceSize(0); + basisPtr->getScratchSpaceSize(perTeamSpaceSize,perThreadSpaceSize,inputPoints, OPERATOR_VALUE); + teamPolicy.set_scratch_size(scratch_space_level, Kokkos::PerTeam(perTeamSpaceSize), Kokkos::PerThread(perThreadSpaceSize)); + + Kokkos::parallel_for (teamPolicy,functor); + } + + { //compute gradients + auto functor = KOKKOS_LAMBDA (typename Kokkos::TeamPolicy::member_type team_member) { + auto gradsACell = Kokkos::subview(outputGradsA, team_member.league_rank(), Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL()); + basisRawPtr_device->getValues(gradsACell, inputPoints, OPERATOR_GRAD, team_member, team_member.team_scratch(scratch_space_level)); + }; + + //Get the required size of the scratch space per team and per thread. + int perThreadSpaceSize(0), perTeamSpaceSize(0); + basisPtr->getScratchSpaceSize(perTeamSpaceSize,perThreadSpaceSize,inputPoints, OPERATOR_GRAD); + teamPolicy.set_scratch_size(scratch_space_level, Kokkos::PerTeam(perTeamSpaceSize), Kokkos::PerThread(perThreadSpaceSize)); + + Kokkos::parallel_for (teamPolicy,functor); + } + } + + *outStream << "Computing values and gradients for " << npts << " points using high-level getValues function" <getValues(outputValuesB, inputPoints, OPERATOR_VALUE); + basisPtr->getValues(outputGradsB, inputPoints, OPERATOR_GRAD); + + *outStream << "Comparing values and gradients on host" <(); + for (size_t ic=0;ic tol) { + ++errorFlag; + std::cout << ", ic: " << ic << ", i: " << i << ", j: " << j + << ", val A: " << outputValuesA_Host(ic,i,j) + << ", val B: " << outputValuesB_Host(i,j) + << ", |diff|: " << diff + << ", tol: " << tol + << std::endl; + } + } + } + + { + // compare grads + const auto outputGradsA_Host = Kokkos::create_mirror_view(outputGradsA); Kokkos::deep_copy(outputGradsA_Host, outputGradsA); + const auto outputGradsB_Host = Kokkos::create_mirror_view(outputGradsB); Kokkos::deep_copy(outputGradsB_Host, outputGradsB); + + OutValueType diff = 0; + auto tol = epsilon(); + for (size_t ic=0;ic tol) { + ++errorFlag; + std::cout << ", ic: " << ic << ", i: " << i << ", j: " << j + << ", grads A: [" << outputGradsA_Host(ic,i,j,0) << ", " << outputGradsA_Host(ic,i,j,1) << ", " << outputGradsA_Host(ic,i,j,2) <<"]" + << ", grads B: [" << outputGradsB_Host(i,j,0) << ", " << outputGradsB_Host(i,j,1) << ", " << outputGradsB_Host(i,j,2) <<"]" + << ", |diff|: " << diff + << ", tol: " << tol + << std::endl; + } + } + } + } catch (std::exception &err) { + std::cout << "UNEXPECTED ERROR !!! ----------------------------------------------------------\n"; + std::cout << err.what() << '\n'; + std::cout << "-------------------------------------------------------------------------------" << "\n\n"; + errorFlag = -1000; + }; + + if (errorFlag != 0) + std::cout << "End Result: TEST FAILED\n"; + else + std::cout << "End Result: TEST PASSED\n"; + + return errorFlag; + } + } +} diff --git a/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_HEX_C2_FEM/CMakeLists.txt b/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_HEX_C2_FEM/CMakeLists.txt index a9bfc7f38abb..29e3244386c9 100644 --- a/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_HEX_C2_FEM/CMakeLists.txt +++ b/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_HEX_C2_FEM/CMakeLists.txt @@ -1,8 +1,16 @@ TRIBITS_INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}) + +# test +SET(Intrepid2_TEST_ETI_FILE "") +LIST(APPEND Intrepid2_TEST_ETI_FILE + "test_01" + "test_01_Serendipity") + # value types SET(Intrepid2_TEST_ETI_VALUETYPE_NAME "") SET(Intrepid2_TEST_ETI_VALUETYPE "") +SET(Intrepid2_TEST_ETI_SACADO "") LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE_NAME "DOUBLE") LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE "double") @@ -17,12 +25,80 @@ ENDIF() LIST(LENGTH Intrepid2_TEST_ETI_VALUETYPE_NAME ETI_VALUETYPE_COUNT) MATH(EXPR ETI_VALUETYPE_COUNT "${ETI_VALUETYPE_COUNT}-1") -# Host test -SET(Intrepid2_TEST_ETI_FILE "") -LIST(APPEND Intrepid2_TEST_ETI_FILE - "test_01" - "test_01_Serendipity") +# device +SET(Intrepid2_TEST_ETI_DEVICE_NAME "") +SET(Intrepid2_TEST_ETI_DEVICE "") +IF(Kokkos_ENABLE_SERIAL) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "Serial") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() +IF(Kokkos_ENABLE_OPENMP) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "OpenMP") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() +IF(Kokkos_ENABLE_CUDA) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "CUDA") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() +IF(Kokkos_ENABLE_HIP) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "HIP") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() + +LIST(LENGTH Intrepid2_TEST_ETI_DEVICE_NAME ETI_DEVICE_COUNT) +MATH(EXPR ETI_DEVICE_COUNT "${ETI_DEVICE_COUNT}-1") + +FOREACH(I RANGE ${ETI_DEVICE_COUNT}) + LIST(GET Intrepid2_TEST_ETI_DEVICE_NAME ${I} ETI_DEVICE_NAME) + LIST(GET Intrepid2_TEST_ETI_DEVICE ${I} ETI_DEVICE) + #MESSAGE(STATUS "Generating TEST HGRAD_HEX_C2_FEM for ${ETI_DEVICE_NAME} with ${ETI_DEVICE}") + FOREACH(J RANGE ${ETI_VALUETYPE_COUNT}) + LIST(GET Intrepid2_TEST_ETI_VALUETYPE_NAME ${J} ETI_VALUETYPE_NAME) + LIST(GET Intrepid2_TEST_ETI_VALUETYPE ${J} ETI_VALUETYPE) + LIST(GET Intrepid2_TEST_ETI_SACADO ${J} ETI_SACADO) + FOREACH(ETI_FILE IN LISTS Intrepid2_TEST_ETI_FILE) + SET(ETI_NAME "${ETI_FILE}_${ETI_DEVICE_NAME}_${ETI_VALUETYPE_NAME}") + MESSAGE(STATUS "Generating TEST: HGRAD_HEX_C2_FEM ${ETI_NAME}.cpp") + CONFIGURE_FILE(eti/${ETI_FILE}_ETI.in ${ETI_NAME}.cpp) + + TRIBITS_ADD_EXECUTABLE_AND_TEST( + ${ETI_NAME} + SOURCES ${ETI_NAME}.cpp + ARGS PrintItAll + NUM_MPI_PROCS 1 + PASS_REGULAR_EXPRESSION "TEST PASSED" + ADD_DIR_TO_NAME + ) + + ENDFOREACH() + ENDFOREACH() +ENDFOREACH() + + + + +# test +SET(Intrepid2_TEST_ETI_FILE "test_02") + +# value types +SET(Intrepid2_TEST_ETI_VALUETYPE_NAME "") +SET(Intrepid2_TEST_ETI_VALUETYPE "") +SET(Intrepid2_TEST_ETI_SACADO "") + +LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE_NAME "DOUBLE_DOUBLE") +LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE "double,double") +LIST(APPEND Intrepid2_TEST_ETI_SACADO "0") + +IF (HAVE_INTREPID2_SACADO) + LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE_NAME "DFAD_DFAD") + LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE "Sacado::Fad::DFad,Sacado::Fad::DFad ") + LIST(APPEND Intrepid2_TEST_ETI_SACADO "33") +ENDIF() + +LIST(LENGTH Intrepid2_TEST_ETI_VALUETYPE_NAME ETI_VALUETYPE_COUNT) +MATH(EXPR ETI_VALUETYPE_COUNT "${ETI_VALUETYPE_COUNT}-1") +# device SET(Intrepid2_TEST_ETI_DEVICE_NAME "") SET(Intrepid2_TEST_ETI_DEVICE "") IF(Kokkos_ENABLE_SERIAL) diff --git a/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_HEX_C2_FEM/eti/test_02_ETI.in b/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_HEX_C2_FEM/eti/test_02_ETI.in new file mode 100644 index 000000000000..f10b05aa223e --- /dev/null +++ b/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_HEX_C2_FEM/eti/test_02_ETI.in @@ -0,0 +1,52 @@ +// @HEADER +// ***************************************************************************** +// Intrepid2 Package +// +// Copyright 2007 NTESS and the Intrepid2 contributors. +// SPDX-License-Identifier: BSD-3-Clause +// ***************************************************************************** +// @HEADER + +/** \file test_02.cpp + \brief Unit test of Intrepid2::Basis_HGRAD_HEX_C2_FEM team-level getValues. + \author Kyungjoo Kim +*/ + +#include "Kokkos_Core.hpp" + +#define ETI_SACADO @ETI_SACADO@ +#if (ETI_SACADO != 0) /// SACADO +#include "Kokkos_ViewFactory.hpp" +#include "Sacado.hpp" +#endif + +#if (ETI_SACADO == 0) /// double double +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__) +#elif (ETI_SACADO == 11 /* SFAD SFAD */ || ETI_SACADO == 33 /* DFAD DFAD */) +constexpr int num_deriv = 3; +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#elif (ETI_SACADO == 23) +constexpr int num_deriv = 3; +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#elif (ETI_SACADO == 20) +constexpr int num_deriv = 2; +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__) +#endif + +#include "test_02.hpp" + +int main(int argc, char *argv[]) { + + const bool verbose = (argc-1) > 0; + Kokkos::initialize(); + + Intrepid2::Test::HGRAD_HEX_C2_FEM_Test02<@ETI_VALUETYPE@,@ETI_DEVICE@>(verbose); + + Kokkos::finalize(); + return 0; +} + diff --git a/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_HEX_C2_FEM/test_02.hpp b/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_HEX_C2_FEM/test_02.hpp new file mode 100644 index 000000000000..a29875462280 --- /dev/null +++ b/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_HEX_C2_FEM/test_02.hpp @@ -0,0 +1,184 @@ +// @HEADER +// ***************************************************************************** +// Intrepid2 Package +// +// Copyright 2007 NTESS and the Intrepid2 contributors. +// SPDX-License-Identifier: BSD-3-Clause +// ***************************************************************************** +// @HEADER + +/** \file test_02.hpp + \brief Unit tests for the Intrepid2::HGRAD_HEX_C2_FEM class. + \author Created by Kyungjoo Kim, Mauro Perego + */ + + +#include "Intrepid2_config.h" +#include "Kokkos_Random.hpp" +#ifdef HAVE_INTREPID2_DEBUG +#define INTREPID2_TEST_FOR_DEBUG_ABORT_OVERRIDE_TO_CONTINUE +#endif + +#include "Intrepid2_Types.hpp" +#include "Intrepid2_Utils.hpp" + +#include "Intrepid2_HGRAD_HEX_C2_FEM.hpp" +#include "packages/intrepid2/unit-test/Discretization/Basis/Setup.hpp" + +namespace Intrepid2 { + + namespace Test { + + // This test evaluates the basis functions at a set of points on a batch of cells using the team-level getValues, + // and compares the results with those obtained using the classic getValues function. + template + int HGRAD_HEX_C2_FEM_Test02(const bool verbose) { + + //! Setup test output stream. + Teuchos::RCP outStream = setup_output_stream( + verbose, "HGRAD_HEX_C2_FEM, Test 2", {} + ); + + *outStream + << "\n" + << "===============================================================================\n" + << "| Testing Team-level Implemntation of getValues |\n" + << "===============================================================================\n"; + + using DeviceSpaceType = typename DeviceType::execution_space; + Kokkos::print_configuration(std::cout, false); + + int errorFlag = 0; + + try { + using BasisType = Basis_HGRAD_HEX_C2_FEM; + auto basisPtr = Teuchos::rcp(new BasisType()); + + const int ncells = 5, npts = 10, ndim = 3; + Kokkos::DynRankView ConstructWithLabelOutView(outputValuesA, ncells, basisPtr->getCardinality(), npts); + Kokkos::DynRankView ConstructWithLabelOutView(outputValuesB, basisPtr->getCardinality(), npts); + + Kokkos::DynRankView ConstructWithLabelOutView(outputGradsA, ncells, basisPtr->getCardinality(), npts, ndim); + Kokkos::DynRankView ConstructWithLabelOutView(outputGradsB, basisPtr->getCardinality(), npts, ndim); + Kokkos::DynRankView ConstructWithLabelPointView(point, 1); + + using ScalarType = typename ScalarTraits::scalar_type; + + Kokkos::View inputPointsViewToUseRandom("inputPoints", npts*ndim*get_dimension_scalar(point)); + auto vcprop = Kokkos::common_view_alloc_prop(point); + Kokkos::DynRankView inputPoints (Kokkos::view_wrap(inputPointsViewToUseRandom.data(), vcprop), npts, ndim); + + // random values between (0,1) + Kokkos::Random_XorShift64_Pool random(13718); + Kokkos::fill_random(inputPointsViewToUseRandom, random, 1.0); + + + *outStream << "Computing values and gradients for " << ncells << " cells and " << npts << " points using team-level getValues function" <(*basisPtr); + auto basisRawPtr_device = basisPtr_device.get(); + + int scratch_space_level =1; + const int vectorSize = getVectorSizeForHierarchicalParallelism(); + Kokkos::TeamPolicy teamPolicy(ncells, Kokkos::AUTO,vectorSize); + + { //compute values + auto functor = KOKKOS_LAMBDA (typename Kokkos::TeamPolicy::member_type team_member) { + auto valsACell = Kokkos::subview(outputValuesA, team_member.league_rank(), Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL()); + basisRawPtr_device->getValues(valsACell, inputPoints, OPERATOR_VALUE, team_member, team_member.team_scratch(scratch_space_level)); + }; + + //Get the required size of the scratch space per team and per thread. + int perThreadSpaceSize(0), perTeamSpaceSize(0); + basisPtr->getScratchSpaceSize(perTeamSpaceSize,perThreadSpaceSize,inputPoints, OPERATOR_VALUE); + teamPolicy.set_scratch_size(scratch_space_level, Kokkos::PerTeam(perTeamSpaceSize), Kokkos::PerThread(perThreadSpaceSize)); + + Kokkos::parallel_for (teamPolicy,functor); + } + + { //compute gradients + auto functor = KOKKOS_LAMBDA (typename Kokkos::TeamPolicy::member_type team_member) { + auto gradsACell = Kokkos::subview(outputGradsA, team_member.league_rank(), Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL()); + basisRawPtr_device->getValues(gradsACell, inputPoints, OPERATOR_GRAD, team_member, team_member.team_scratch(scratch_space_level)); + }; + + //Get the required size of the scratch space per team and per thread. + int perThreadSpaceSize(0), perTeamSpaceSize(0); + basisPtr->getScratchSpaceSize(perTeamSpaceSize,perThreadSpaceSize,inputPoints, OPERATOR_GRAD); + teamPolicy.set_scratch_size(scratch_space_level, Kokkos::PerTeam(perTeamSpaceSize), Kokkos::PerThread(perThreadSpaceSize)); + + Kokkos::parallel_for (teamPolicy,functor); + } + } + + *outStream << "Computing values and gradients for " << npts << " points using high-level getValues function" <getValues(outputValuesB, inputPoints, OPERATOR_VALUE); + basisPtr->getValues(outputGradsB, inputPoints, OPERATOR_GRAD); + + *outStream << "Comparing values and gradients on host" <(); + for (size_t ic=0;ic tol) { + ++errorFlag; + std::cout << ", ic: " << ic << ", i: " << i << ", j: " << j + << ", val A: " << outputValuesA_Host(ic,i,j) + << ", val B: " << outputValuesB_Host(i,j) + << ", |diff|: " << diff + << ", tol: " << tol + << std::endl; + } + } + } + + { + // compare grads + const auto outputGradsA_Host = Kokkos::create_mirror_view(outputGradsA); Kokkos::deep_copy(outputGradsA_Host, outputGradsA); + const auto outputGradsB_Host = Kokkos::create_mirror_view(outputGradsB); Kokkos::deep_copy(outputGradsB_Host, outputGradsB); + + OutValueType diff = 0; + auto tol = epsilon(); + for (size_t ic=0;ic tol) { + ++errorFlag; + std::cout << ", ic: " << ic << ", i: " << i << ", j: " << j + << ", grads A: [" << outputGradsA_Host(ic,i,j,0) << ", " << outputGradsA_Host(ic,i,j,1) << ", " << outputGradsA_Host(ic,i,j,2) <<"]" + << ", grads B: [" << outputGradsB_Host(i,j,0) << ", " << outputGradsB_Host(i,j,1) << ", " << outputGradsB_Host(i,j,2) <<"]" + << ", |diff|: " << diff + << ", tol: " << tol + << std::endl; + } + } + } + } catch (std::exception &err) { + std::cout << "UNEXPECTED ERROR !!! ----------------------------------------------------------\n"; + std::cout << err.what() << '\n'; + std::cout << "-------------------------------------------------------------------------------" << "\n\n"; + errorFlag = -1000; + }; + + if (errorFlag != 0) + std::cout << "End Result: TEST FAILED\n"; + else + std::cout << "End Result: TEST PASSED\n"; + + return errorFlag; + } + } +} diff --git a/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_HEX_Cn_FEM/CMakeLists.txt b/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_HEX_Cn_FEM/CMakeLists.txt index 793d773f707f..ba86fece89df 100644 --- a/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_HEX_Cn_FEM/CMakeLists.txt +++ b/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_HEX_Cn_FEM/CMakeLists.txt @@ -7,6 +7,7 @@ SET(Intrepid2_TEST_ETI_FILE "test_01") # value types SET(Intrepid2_TEST_ETI_VALUETYPE_NAME "") SET(Intrepid2_TEST_ETI_VALUETYPE "") +SET(Intrepid2_TEST_ETI_SACADO "") LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE_NAME "DOUBLE_DOUBLE") LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE "double,double") @@ -94,11 +95,18 @@ SET(Intrepid2_TEST_ETI_FILE "test_02") # value types SET(Intrepid2_TEST_ETI_VALUETYPE_NAME "") SET(Intrepid2_TEST_ETI_VALUETYPE "") +SET(Intrepid2_TEST_ETI_SACADO "") LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE_NAME "DOUBLE_DOUBLE") LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE "double,double") LIST(APPEND Intrepid2_TEST_ETI_SACADO "0") +IF (HAVE_INTREPID2_SACADO) + LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE_NAME "DFAD_DFAD") + LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE "Sacado::Fad::DFad,Sacado::Fad::DFad ") + LIST(APPEND Intrepid2_TEST_ETI_SACADO "33") +ENDIF() + LIST(LENGTH Intrepid2_TEST_ETI_VALUETYPE_NAME ETI_VALUETYPE_COUNT) MATH(EXPR ETI_VALUETYPE_COUNT "${ETI_VALUETYPE_COUNT}-1") diff --git a/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_HEX_Cn_FEM/eti/test_01_ETI.in b/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_HEX_Cn_FEM/eti/test_01_ETI.in index 487708632660..25426631d6de 100644 --- a/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_HEX_Cn_FEM/eti/test_01_ETI.in +++ b/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_HEX_Cn_FEM/eti/test_01_ETI.in @@ -28,9 +28,8 @@ constexpr int num_deriv = 10; #define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) #define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) #elif (ETI_SACADO == 23) -constexpr int num_deriv = 9; -constexpr int max_deriv = 10; -#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__, max_deriv+1) +constexpr int num_deriv = 3; +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) #define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) #elif (ETI_SACADO == 20) constexpr int num_deriv = 2; diff --git a/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_HEX_Cn_FEM/eti/test_02_ETI.in b/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_HEX_Cn_FEM/eti/test_02_ETI.in index 6a200d58b21d..d314677fd1db 100644 --- a/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_HEX_Cn_FEM/eti/test_02_ETI.in +++ b/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_HEX_Cn_FEM/eti/test_02_ETI.in @@ -7,22 +7,45 @@ // ***************************************************************************** // @HEADER -/** \file test_01.cpp - \brief Unit test of serial interface Intrepid2::Basis_HGRAD_QUAD_Cn_FEM. +/** \file test_02.cpp + \brief Unit test of Intrepid2::Basis_HGRAD_HEX_Cn_FEM team-level getValues. \author Kyungjoo Kim */ #include "Kokkos_Core.hpp" +#define ETI_SACADO @ETI_SACADO@ +#if (ETI_SACADO != 0) /// SACADO +#include "Kokkos_ViewFactory.hpp" +#include "Sacado.hpp" +#endif + +#if (ETI_SACADO == 0) /// double double +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__) +#elif (ETI_SACADO == 11 /* SFAD SFAD */ || ETI_SACADO == 33 /* DFAD DFAD */) +constexpr int num_deriv = 3; +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#elif (ETI_SACADO == 23) +constexpr int num_deriv = 3; +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#elif (ETI_SACADO == 20) +constexpr int num_deriv = 2; +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__) +#endif + #include "test_02.hpp" int main(int argc, char *argv[]) { + const bool verbose = (argc-1) > 0; Kokkos::initialize(); - { - const bool verbose = (argc-1) > 0; - Intrepid2::Test::HGRAD_HEX_Cn_FEM_Test02<@ETI_VALUETYPE@,@ETI_DEVICE@>(verbose); - } + + Intrepid2::Test::HGRAD_HEX_Cn_FEM_Test02<@ETI_VALUETYPE@,@ETI_DEVICE@>(verbose); + Kokkos::finalize(); return 0; } diff --git a/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_HEX_Cn_FEM/test_02.hpp b/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_HEX_Cn_FEM/test_02.hpp index b98955113bde..e392f1540447 100644 --- a/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_HEX_Cn_FEM/test_02.hpp +++ b/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_HEX_Cn_FEM/test_02.hpp @@ -7,9 +7,9 @@ // ***************************************************************************** // @HEADER -/** \file test_01.hpp +/** \file test_02.hpp \brief Unit tests for the Intrepid2::HGRAD_HEX_Cn_FEM class. - \author Created by P. Bochev, D. Ridzal, K. Peterson, Kyungjoo Kim + \author Created by Kyungjoo Kim, Mauro Perego */ @@ -23,100 +23,151 @@ #include "Intrepid2_Utils.hpp" #include "Intrepid2_HGRAD_HEX_Cn_FEM.hpp" +#include "packages/intrepid2/unit-test/Discretization/Basis/Setup.hpp" namespace Intrepid2 { namespace Test { - // This code provides an example to use serial interface of high order elements + // This test evaluates the basis functions at a set of points on a batch of cells using the team-level getValues, + // and compares the results with those obtained using the classic getValues function. template int HGRAD_HEX_Cn_FEM_Test02(const bool verbose) { + + //! Setup test output stream. + Teuchos::RCP outStream = setup_output_stream( + verbose, "HGRAD_HEX_Cn_FEM, Test 2", {} + ); + + *outStream + << "\n" + << "===============================================================================\n" + << "| Testing Team-level Implemntation of getValues |\n" + << "===============================================================================\n"; + using DeviceSpaceType = typename DeviceType::execution_space; Kokkos::print_configuration(std::cout, false); int errorFlag = 0; - + constexpr int maxOrder = 9; try { - // for higher orders in certain environments, this test can take a while to run in ctest. So we reduce the number of points as we go beyond 10th order. Also, @mperego is replacing this test, so for now we just restrict to the 10 orders we supported until recently. - for (int order=1;order<10;++order) { - Basis_HGRAD_HEX_Cn_FEM basis(order); + for (int order=1;order<=maxOrder;++order) { + using BasisType = Basis_HGRAD_HEX_Cn_FEM; + auto basisPtr = Teuchos::rcp(new BasisType(order)); - // problem setup - // let's say we want to evaluate 1000 points in parallel. output values are stored in outputValuesA and B. - // A is compuated via serial interface and B is computed with top-level interface. - const int npts = 1000, ndim = 3; - Kokkos::DynRankView outputValuesA("outputValuesA", basis.getCardinality(), npts); - Kokkos::DynRankView outputValuesB("outputValuesB", basis.getCardinality(), npts); + const int ncells = 5, npts = 10, ndim = 3; + Kokkos::DynRankView ConstructWithLabelOutView(outputValuesA, ncells, basisPtr->getCardinality(), npts); + Kokkos::DynRankView ConstructWithLabelOutView(outputValuesB, basisPtr->getCardinality(), npts); + + Kokkos::DynRankView ConstructWithLabelOutView(outputGradsA, ncells, basisPtr->getCardinality(), npts, ndim); + Kokkos::DynRankView ConstructWithLabelOutView(outputGradsB, basisPtr->getCardinality(), npts, ndim); + Kokkos::DynRankView ConstructWithLabelPointView(point, 1); + + using ScalarType = typename ScalarTraits::scalar_type; - Kokkos::View inputPointsViewToUseRandom("inputPoints", npts, ndim); - Kokkos::DynRankView inputPoints (inputPointsViewToUseRandom.data(), npts, ndim); + Kokkos::View inputPointsViewToUseRandom("inputPoints", npts*ndim*get_dimension_scalar(point)); + auto vcprop = Kokkos::common_view_alloc_prop(point); + Kokkos::DynRankView inputPoints (Kokkos::view_wrap(inputPointsViewToUseRandom.data(), vcprop), npts, ndim); - // random values between (-1,1) x (-1,1) + // random values between (0,1) Kokkos::Random_XorShift64_Pool random(13718); Kokkos::fill_random(inputPointsViewToUseRandom, random, 1.0); - // compute setup - // we need vinv and workspace - const auto vinv = basis.getVandermondeInverse(); - - // worksize - // workspace per thread is required for serial interface. - // parallel_for with range policy would be good to use stack workspace - // as team policy only can create shared memory - // this part would be tricky as the max size should be determined at compile time - // let's think about this and find out the best practice. for now I use the following. - constexpr int worksize = (Parameters::MaxOrder+1)*4; - - // if you use team policy, worksize can be gathered from the basis object and use - // kokkos shmem_size APIs to create workspace per team or per thread. - //const auto worksize_for_teampolicy = basis.getWorksizePerPoint(OPERATOR_VALUE); - - // extract point range to be evaluated in each thread - typedef Kokkos::pair range_type; - - // parallel execution with serial interface - Kokkos::RangePolicy policy(0, npts); - Kokkos::parallel_for(policy, KOKKOS_LAMBDA(int i) { - // we evaluate a single point - const range_type pointRange = range_type(i,i+1); - - // out (# dofs, # pts), input (# pts, # dims) - auto output = Kokkos::subview(outputValuesA, Kokkos::ALL(), pointRange); - auto input = Kokkos::subview(inputPoints, pointRange, Kokkos::ALL()); + + *outStream << "Order: " << order << ": Computing values and gradients for " << ncells << " cells and " << npts << " points using team-level getValues function" <(*basisPtr); + auto basisRawPtr_device = basisPtr_device.get(); + + int scratch_space_level =1; + const int vectorSize = getVectorSizeForHierarchicalParallelism(); + Kokkos::TeamPolicy teamPolicy(ncells, Kokkos::AUTO,vectorSize); + + { //compute values + auto functor = KOKKOS_LAMBDA (typename Kokkos::TeamPolicy::member_type team_member) { + auto valsACell = Kokkos::subview(outputValuesA, team_member.league_rank(), Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL()); + basisRawPtr_device->getValues(valsACell, inputPoints, OPERATOR_VALUE, team_member, team_member.team_scratch(scratch_space_level)); + }; - // wrap static workspace with a view; serial interface has a template view interface. - // either view or dynrankview with a right size is okay. - OutValueType workbuf[worksize]; - Kokkos::View work(&workbuf[0], worksize); + //Get the required size of the scratch space per team and per thread. + int perThreadSpaceSize(0), perTeamSpaceSize(0); + basisPtr->getScratchSpaceSize(perTeamSpaceSize,perThreadSpaceSize,inputPoints, OPERATOR_VALUE); + teamPolicy.set_scratch_size(scratch_space_level, Kokkos::PerTeam(perTeamSpaceSize), Kokkos::PerThread(perThreadSpaceSize)); + + Kokkos::parallel_for (teamPolicy,functor); + } + + { //compute gradients + auto functor = KOKKOS_LAMBDA (typename Kokkos::TeamPolicy::member_type team_member) { + auto gradsACell = Kokkos::subview(outputGradsA, team_member.league_rank(), Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL()); + basisRawPtr_device->getValues(gradsACell, inputPoints, OPERATOR_GRAD, team_member, team_member.team_scratch(scratch_space_level)); + }; - // evaluate basis using serial interface - Impl::Basis_HGRAD_HEX_Cn_FEM - ::Serial::getValues(output, input, work, vinv); - }); - - // evaluation using high level interface - basis.getValues(outputValuesB, inputPoints, OPERATOR_VALUE); - - // compare - const auto outputValuesA_Host = Kokkos::create_mirror_view(outputValuesA); Kokkos::deep_copy(outputValuesA_Host, outputValuesA); - const auto outputValuesB_Host = Kokkos::create_mirror_view(outputValuesB); Kokkos::deep_copy(outputValuesB_Host, outputValuesB); - - double sum = 0, diff = 0; - for (size_t i=0;i 1.0e-9)) { - std::cout << " order = " << order - << " i = " << i << " j = " << j - << " val A = " << outputValuesA_Host(i,j) - << " val B = " << outputValuesB_Host(i,j) - << " diff = " << (outputValuesA_Host(i,j) - outputValuesB_Host(i,j)) - << std::endl; - } + //Get the required size of the scratch space per team and per thread. + int perThreadSpaceSize(0), perTeamSpaceSize(0); + basisPtr->getScratchSpaceSize(perTeamSpaceSize,perThreadSpaceSize,inputPoints, OPERATOR_GRAD); + teamPolicy.set_scratch_size(scratch_space_level, Kokkos::PerTeam(perTeamSpaceSize), Kokkos::PerThread(perThreadSpaceSize)); + + Kokkos::parallel_for (teamPolicy,functor); } - if (diff/sum > 1.0e-9) { - errorFlag = -1; + } + + *outStream << "Order: " << order << ": Computing values and gradients for " << npts << " points using high-level getValues function" <getValues(outputValuesB, inputPoints, OPERATOR_VALUE); + basisPtr->getValues(outputGradsB, inputPoints, OPERATOR_GRAD); + + *outStream << "Order: " << order << ": Comparing values and gradients on host" <(); + for (size_t ic=0;ic tol) { + ++errorFlag; + std::cout << " order: " << order + << ", ic: " << ic << ", i: " << i << ", j: " << j + << ", val A: " << outputValuesA_Host(ic,i,j) + << ", val B: " << outputValuesB_Host(i,j) + << ", |diff|: " << diff + << ", tol: " << tol + << std::endl; + } + } + } + + { + // compare grads + const auto outputGradsA_Host = Kokkos::create_mirror_view(outputGradsA); Kokkos::deep_copy(outputGradsA_Host, outputGradsA); + const auto outputGradsB_Host = Kokkos::create_mirror_view(outputGradsB); Kokkos::deep_copy(outputGradsB_Host, outputGradsB); + + OutValueType diff = 0; + auto tol = epsilon(); + for (size_t ic=0;ic tol) { + ++errorFlag; + std::cout << " order: " << order + << ", ic: " << ic << ", i: " << i << ", j: " << j + << ", grads A: [" << outputGradsA_Host(ic,i,j,0) << ", " << outputGradsA_Host(ic,i,j,1) << ", " << outputGradsA_Host(ic,i,j,2) <<"]" + << ", grads B: [" << outputGradsB_Host(i,j,0) << ", " << outputGradsB_Host(i,j,1) << ", " << outputGradsB_Host(i,j,2) <<"]" + << ", |diff|: " << diff + << ", tol: " << tol + << std::endl; + } + } } } } catch (std::exception &err) { diff --git a/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_LINE_C1_FEM/CMakeLists.txt b/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_LINE_C1_FEM/CMakeLists.txt index 940d4ad3ebb4..186c0369d09e 100644 --- a/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_LINE_C1_FEM/CMakeLists.txt +++ b/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_LINE_C1_FEM/CMakeLists.txt @@ -1,8 +1,13 @@ TRIBITS_INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}) + +# test +SET(Intrepid2_TEST_ETI_FILE "test_01") + # value types SET(Intrepid2_TEST_ETI_VALUETYPE_NAME "") SET(Intrepid2_TEST_ETI_VALUETYPE "") +SET(Intrepid2_TEST_ETI_SACADO "") LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE_NAME "DOUBLE") LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE "double") @@ -17,9 +22,80 @@ ENDIF() LIST(LENGTH Intrepid2_TEST_ETI_VALUETYPE_NAME ETI_VALUETYPE_COUNT) MATH(EXPR ETI_VALUETYPE_COUNT "${ETI_VALUETYPE_COUNT}-1") -# Host test -SET(Intrepid2_TEST_ETI_FILE "test_01") +# device +SET(Intrepid2_TEST_ETI_DEVICE_NAME "") +SET(Intrepid2_TEST_ETI_DEVICE "") +IF(Kokkos_ENABLE_SERIAL) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "Serial") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() +IF(Kokkos_ENABLE_OPENMP) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "OpenMP") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() +IF(Kokkos_ENABLE_CUDA) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "CUDA") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() +IF(Kokkos_ENABLE_HIP) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "HIP") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() + +LIST(LENGTH Intrepid2_TEST_ETI_DEVICE_NAME ETI_DEVICE_COUNT) +MATH(EXPR ETI_DEVICE_COUNT "${ETI_DEVICE_COUNT}-1") + +FOREACH(I RANGE ${ETI_DEVICE_COUNT}) + LIST(GET Intrepid2_TEST_ETI_DEVICE_NAME ${I} ETI_DEVICE_NAME) + LIST(GET Intrepid2_TEST_ETI_DEVICE ${I} ETI_DEVICE) + # MESSAGE(STATUS "Generating TEST HGRAD_LINE_C1_FEM for ${ETI_DEVICE_NAME} with ${ETI_DEVICE}") + FOREACH(J RANGE ${ETI_VALUETYPE_COUNT}) + LIST(GET Intrepid2_TEST_ETI_VALUETYPE_NAME ${J} ETI_VALUETYPE_NAME) + LIST(GET Intrepid2_TEST_ETI_VALUETYPE ${J} ETI_VALUETYPE) + LIST(GET Intrepid2_TEST_ETI_SACADO ${J} ETI_SACADO) + FOREACH(ETI_FILE IN LISTS Intrepid2_TEST_ETI_FILE) + SET(ETI_NAME "${ETI_FILE}_${ETI_DEVICE_NAME}_${ETI_VALUETYPE_NAME}") + MESSAGE(STATUS "Generating TEST: HGRAD_LINE_C1_FEM ${ETI_NAME}.cpp") + CONFIGURE_FILE(eti/${ETI_FILE}_ETI.in ${ETI_NAME}.cpp) + + TRIBITS_ADD_EXECUTABLE_AND_TEST( + ${ETI_NAME} + SOURCES ${ETI_NAME}.cpp + ARGS PrintItAll + NUM_MPI_PROCS 1 + PASS_REGULAR_EXPRESSION "TEST PASSED" + ADD_DIR_TO_NAME + ) + + ENDFOREACH() + ENDFOREACH() +ENDFOREACH() + + + + +# test +SET(Intrepid2_TEST_ETI_FILE "test_02") + +# value types +SET(Intrepid2_TEST_ETI_VALUETYPE_NAME "") +SET(Intrepid2_TEST_ETI_VALUETYPE "") +SET(Intrepid2_TEST_ETI_SACADO "") + +LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE_NAME "DOUBLE_DOUBLE") +LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE "double,double") +LIST(APPEND Intrepid2_TEST_ETI_SACADO "0") + +IF (HAVE_INTREPID2_SACADO) + LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE_NAME "DFAD_DFAD") + LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE "Sacado::Fad::DFad,Sacado::Fad::DFad ") + LIST(APPEND Intrepid2_TEST_ETI_SACADO "33") +ENDIF() + +LIST(LENGTH Intrepid2_TEST_ETI_VALUETYPE_NAME ETI_VALUETYPE_COUNT) +MATH(EXPR ETI_VALUETYPE_COUNT "${ETI_VALUETYPE_COUNT}-1") +# device SET(Intrepid2_TEST_ETI_DEVICE_NAME "") SET(Intrepid2_TEST_ETI_DEVICE "") IF(Kokkos_ENABLE_SERIAL) diff --git a/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_LINE_C1_FEM/eti/test_02_ETI.in b/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_LINE_C1_FEM/eti/test_02_ETI.in new file mode 100644 index 000000000000..69bb74d6a746 --- /dev/null +++ b/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_LINE_C1_FEM/eti/test_02_ETI.in @@ -0,0 +1,52 @@ +// @HEADER +// ***************************************************************************** +// Intrepid2 Package +// +// Copyright 2007 NTESS and the Intrepid2 contributors. +// SPDX-License-Identifier: BSD-3-Clause +// ***************************************************************************** +// @HEADER + +/** \file test_02.cpp + \brief Unit test of Intrepid2::Basis_HGRAD_LINE_C1_FEM team-level get Values. + \author Kyungjoo Kim +*/ + +#include "Kokkos_Core.hpp" + +#define ETI_SACADO @ETI_SACADO@ +#if (ETI_SACADO != 0) /// SACADO +#include "Kokkos_ViewFactory.hpp" +#include "Sacado.hpp" +#endif + +#if (ETI_SACADO == 0) /// double double +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__) +#elif (ETI_SACADO == 11 /* SFAD SFAD */ || ETI_SACADO == 33 /* DFAD DFAD */) +constexpr int num_deriv = 3; +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#elif (ETI_SACADO == 23) +constexpr int num_deriv = 3; +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#elif (ETI_SACADO == 20) +constexpr int num_deriv = 2; +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__) +#endif + +#include "test_02.hpp" + +int main(int argc, char *argv[]) { + + const bool verbose = (argc-1) > 0; + Kokkos::initialize(); + + Intrepid2::Test::HGRAD_LINE_C1_FEM_Test02<@ETI_VALUETYPE@,@ETI_DEVICE@>(verbose); + + Kokkos::finalize(); + return 0; +} + diff --git a/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_LINE_C1_FEM/test_02.hpp b/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_LINE_C1_FEM/test_02.hpp new file mode 100644 index 000000000000..c0d1db740ce9 --- /dev/null +++ b/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_LINE_C1_FEM/test_02.hpp @@ -0,0 +1,185 @@ +// @HEADER +// ***************************************************************************** +// Intrepid2 Package +// +// Copyright 2007 NTESS and the Intrepid2 contributors. +// SPDX-License-Identifier: BSD-3-Clause +// ***************************************************************************** +// @HEADER + +/** \file test_02.hpp + \brief Unit tests for the Intrepid2::HGRAD_LINE_C1_FEM class. + \author Created by Kyungjoo Kim, Mauro Perego + */ + + +#include "Intrepid2_config.h" +#include "Kokkos_Random.hpp" +#ifdef HAVE_INTREPID2_DEBUG +#define INTREPID2_TEST_FOR_DEBUG_ABORT_OVERRIDE_TO_CONTINUE +#endif + +#include "Intrepid2_Types.hpp" +#include "Intrepid2_Utils.hpp" + +#include "Intrepid2_HGRAD_LINE_C1_FEM.hpp" +#include "packages/intrepid2/unit-test/Discretization/Basis/Setup.hpp" + +namespace Intrepid2 { + + namespace Test { + + template + int HGRAD_LINE_C1_FEM_Test02(const bool verbose) { + + //! Setup test output stream. + Teuchos::RCP outStream = setup_output_stream( + verbose, "HGRAD_LINE_C1_FEM, Test 2", {} + ); + + *outStream + << "\n" + << "===============================================================================\n" + << "| Testing Team-level Implemntation of getValues |\n" + << "===============================================================================\n"; + + using DeviceSpaceType = typename DeviceType::execution_space; + Kokkos::print_configuration(std::cout, false); + + int errorFlag = 0; + + try { + using BasisType = Basis_HGRAD_LINE_C1_FEM; + auto basisPtr = Teuchos::rcp(new BasisType()); + + // problem setup + // let's say we want to evaluate 1000 points in parallel. output values are stored in outputValuesA and B. + // A is compuated via serial interface and B is computed with top-level interface. + const int ncells = 5, npts = 10, ndim = 1; + Kokkos::DynRankView ConstructWithLabelOutView(outputValuesA, ncells, basisPtr->getCardinality(), npts); + Kokkos::DynRankView ConstructWithLabelOutView(outputValuesB, basisPtr->getCardinality(), npts); + + Kokkos::DynRankView ConstructWithLabelOutView(outputGradsA, ncells, basisPtr->getCardinality(), npts, ndim); + Kokkos::DynRankView ConstructWithLabelOutView(outputGradsB, basisPtr->getCardinality(), npts, ndim); + Kokkos::DynRankView ConstructWithLabelPointView(point, 1); + + using ScalarType = typename ScalarTraits::scalar_type; + + Kokkos::View inputPointsViewToUseRandom("inputPoints", npts*ndim*get_dimension_scalar(point)); + auto vcprop = Kokkos::common_view_alloc_prop(point); + Kokkos::DynRankView inputPoints (Kokkos::view_wrap(inputPointsViewToUseRandom.data(), vcprop), npts, ndim); + + // random values between (0,1) + Kokkos::Random_XorShift64_Pool random(13718); + Kokkos::fill_random(inputPointsViewToUseRandom, random, 1.0); + + + *outStream << "Computing values and gradients for " << ncells << " cells and " << npts << " points using team-level getValues function" <(*basisPtr); + auto basisRawPtr_device = basisPtr_device.get(); + + int scratch_space_level =1; + const int vectorSize = getVectorSizeForHierarchicalParallelism(); + Kokkos::TeamPolicy teamPolicy(ncells, Kokkos::AUTO,vectorSize); + + { //compute values + auto functor = KOKKOS_LAMBDA (typename Kokkos::TeamPolicy::member_type team_member) { + auto valsACell = Kokkos::subview(outputValuesA, team_member.league_rank(), Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL()); + basisRawPtr_device->getValues(valsACell, inputPoints, OPERATOR_VALUE, team_member, team_member.team_scratch(scratch_space_level)); + }; + + //Get the required size of the scratch space per team and per thread. + int perThreadSpaceSize(0), perTeamSpaceSize(0); + basisPtr->getScratchSpaceSize(perTeamSpaceSize,perThreadSpaceSize,inputPoints, OPERATOR_VALUE); + teamPolicy.set_scratch_size(scratch_space_level, Kokkos::PerTeam(perTeamSpaceSize), Kokkos::PerThread(perThreadSpaceSize)); + + Kokkos::parallel_for (teamPolicy,functor); + } + + { //compute gradients + auto functor = KOKKOS_LAMBDA (typename Kokkos::TeamPolicy::member_type team_member) { + auto gradsACell = Kokkos::subview(outputGradsA, team_member.league_rank(), Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL()); + basisRawPtr_device->getValues(gradsACell, inputPoints, OPERATOR_GRAD, team_member, team_member.team_scratch(scratch_space_level)); + }; + + //Get the required size of the scratch space per team and per thread. + int perThreadSpaceSize(0), perTeamSpaceSize(0); + basisPtr->getScratchSpaceSize(perTeamSpaceSize,perThreadSpaceSize,inputPoints, OPERATOR_GRAD); + teamPolicy.set_scratch_size(scratch_space_level, Kokkos::PerTeam(perTeamSpaceSize), Kokkos::PerThread(perThreadSpaceSize)); + + Kokkos::parallel_for (teamPolicy,functor); + } + } + + *outStream << "Computing values and gradients for " << npts << " points using high-level getValues function" <getValues(outputValuesB, inputPoints, OPERATOR_VALUE); + basisPtr->getValues(outputGradsB, inputPoints, OPERATOR_GRAD); + + *outStream << "Comparing values and gradients on host" <(); + for (size_t ic=0;ic tol) { + ++errorFlag; + std::cout << ", ic: " << ic << ", i: " << i << ", j: " << j + << ", val A: " << outputValuesA_Host(ic,i,j) + << ", val B: " << outputValuesB_Host(i,j) + << ", |diff|: " << diff + << ", tol: " << tol + << std::endl; + } + } + } + + { + // compare grads + const auto outputGradsA_Host = Kokkos::create_mirror_view(outputGradsA); Kokkos::deep_copy(outputGradsA_Host, outputGradsA); + const auto outputGradsB_Host = Kokkos::create_mirror_view(outputGradsB); Kokkos::deep_copy(outputGradsB_Host, outputGradsB); + + OutValueType diff = 0; + auto tol = epsilon(); + for (size_t ic=0;ic tol) { + ++errorFlag; + std::cout << ", ic: " << ic << ", i: " << i << ", j: " << j + << ", grads A: [" << outputGradsA_Host(ic,i,j,0) << "]" + << ", grads B: [" << outputGradsB_Host(i,j,0) <<"]" + << ", |diff|: " << diff + << ", tol: " << tol + << std::endl; + } + } + } + } catch (std::exception &err) { + std::cout << "UNEXPECTED ERROR !!! ----------------------------------------------------------\n"; + std::cout << err.what() << '\n'; + std::cout << "-------------------------------------------------------------------------------" << "\n\n"; + errorFlag = -1000; + }; + + if (errorFlag != 0) + std::cout << "End Result: TEST FAILED\n"; + else + std::cout << "End Result: TEST PASSED\n"; + + return errorFlag; + } + } +} diff --git a/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_LINE_C2_FEM/CMakeLists.txt b/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_LINE_C2_FEM/CMakeLists.txt index f26e93eb35f6..47fc663ffd89 100644 --- a/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_LINE_C2_FEM/CMakeLists.txt +++ b/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_LINE_C2_FEM/CMakeLists.txt @@ -1,8 +1,13 @@ TRIBITS_INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}) + +# test +SET(Intrepid2_TEST_ETI_FILE "test_01") + # value types SET(Intrepid2_TEST_ETI_VALUETYPE_NAME "") SET(Intrepid2_TEST_ETI_VALUETYPE "") +SET(Intrepid2_TEST_ETI_SACADO "") LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE_NAME "DOUBLE") LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE "double") @@ -17,9 +22,80 @@ ENDIF() LIST(LENGTH Intrepid2_TEST_ETI_VALUETYPE_NAME ETI_VALUETYPE_COUNT) MATH(EXPR ETI_VALUETYPE_COUNT "${ETI_VALUETYPE_COUNT}-1") -# Host test -SET(Intrepid2_TEST_ETI_FILE "test_01") +# device +SET(Intrepid2_TEST_ETI_DEVICE_NAME "") +SET(Intrepid2_TEST_ETI_DEVICE "") +IF(Kokkos_ENABLE_SERIAL) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "Serial") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() +IF(Kokkos_ENABLE_OPENMP) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "OpenMP") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() +IF(Kokkos_ENABLE_CUDA) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "CUDA") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() +IF(Kokkos_ENABLE_HIP) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "HIP") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() + +LIST(LENGTH Intrepid2_TEST_ETI_DEVICE_NAME ETI_DEVICE_COUNT) +MATH(EXPR ETI_DEVICE_COUNT "${ETI_DEVICE_COUNT}-1") + +FOREACH(I RANGE ${ETI_DEVICE_COUNT}) + LIST(GET Intrepid2_TEST_ETI_DEVICE_NAME ${I} ETI_DEVICE_NAME) + LIST(GET Intrepid2_TEST_ETI_DEVICE ${I} ETI_DEVICE) + #MESSAGE(STATUS "Generating TEST HGRAD_LINE_C2_FEM for ${ETI_DEVICE_NAME} with ${ETI_DEVICE}") + FOREACH(J RANGE ${ETI_VALUETYPE_COUNT}) + LIST(GET Intrepid2_TEST_ETI_VALUETYPE_NAME ${J} ETI_VALUETYPE_NAME) + LIST(GET Intrepid2_TEST_ETI_VALUETYPE ${J} ETI_VALUETYPE) + LIST(GET Intrepid2_TEST_ETI_SACADO ${J} ETI_SACADO) + FOREACH(ETI_FILE IN LISTS Intrepid2_TEST_ETI_FILE) + SET(ETI_NAME "${ETI_FILE}_${ETI_DEVICE_NAME}_${ETI_VALUETYPE_NAME}") + MESSAGE(STATUS "Generating TEST: HGRAD_LINE_C2_FEM ${ETI_NAME}.cpp") + CONFIGURE_FILE(eti/${ETI_FILE}_ETI.in ${ETI_NAME}.cpp) + + TRIBITS_ADD_EXECUTABLE_AND_TEST( + ${ETI_NAME} + SOURCES ${ETI_NAME}.cpp + ARGS PrintItAll + NUM_MPI_PROCS 1 + PASS_REGULAR_EXPRESSION "TEST PASSED" + ADD_DIR_TO_NAME + ) + + ENDFOREACH() + ENDFOREACH() +ENDFOREACH() + + + + +# test +SET(Intrepid2_TEST_ETI_FILE "test_02") + +# value types +SET(Intrepid2_TEST_ETI_VALUETYPE_NAME "") +SET(Intrepid2_TEST_ETI_VALUETYPE "") +SET(Intrepid2_TEST_ETI_SACADO "") + +LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE_NAME "DOUBLE_DOUBLE") +LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE "double,double") +LIST(APPEND Intrepid2_TEST_ETI_SACADO "0") + +IF (HAVE_INTREPID2_SACADO) + LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE_NAME "DFAD_DFAD") + LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE "Sacado::Fad::DFad,Sacado::Fad::DFad ") + LIST(APPEND Intrepid2_TEST_ETI_SACADO "33") +ENDIF() + +LIST(LENGTH Intrepid2_TEST_ETI_VALUETYPE_NAME ETI_VALUETYPE_COUNT) +MATH(EXPR ETI_VALUETYPE_COUNT "${ETI_VALUETYPE_COUNT}-1") +# device SET(Intrepid2_TEST_ETI_DEVICE_NAME "") SET(Intrepid2_TEST_ETI_DEVICE "") IF(Kokkos_ENABLE_SERIAL) diff --git a/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_LINE_C2_FEM/eti/test_02_ETI.in b/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_LINE_C2_FEM/eti/test_02_ETI.in new file mode 100644 index 000000000000..76e7d225aa79 --- /dev/null +++ b/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_LINE_C2_FEM/eti/test_02_ETI.in @@ -0,0 +1,52 @@ +// @HEADER +// ***************************************************************************** +// Intrepid2 Package +// +// Copyright 2007 NTESS and the Intrepid2 contributors. +// SPDX-License-Identifier: BSD-3-Clause +// ***************************************************************************** +// @HEADER + +/** \file test_02.cpp + \brief Unit test of Intrepid2::Basis_HGRAD_LINE_C2_FEM team-level get Values. + \author Kyungjoo Kim +*/ + +#include "Kokkos_Core.hpp" + +#define ETI_SACADO @ETI_SACADO@ +#if (ETI_SACADO != 0) /// SACADO +#include "Kokkos_ViewFactory.hpp" +#include "Sacado.hpp" +#endif + +#if (ETI_SACADO == 0) /// double double +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__) +#elif (ETI_SACADO == 11 /* SFAD SFAD */ || ETI_SACADO == 33 /* DFAD DFAD */) +constexpr int num_deriv = 3; +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#elif (ETI_SACADO == 23) +constexpr int num_deriv = 3; +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#elif (ETI_SACADO == 20) +constexpr int num_deriv = 2; +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__) +#endif + +#include "test_02.hpp" + +int main(int argc, char *argv[]) { + + const bool verbose = (argc-1) > 0; + Kokkos::initialize(); + + Intrepid2::Test::HGRAD_LINE_C2_FEM_Test02<@ETI_VALUETYPE@,@ETI_DEVICE@>(verbose); + + Kokkos::finalize(); + return 0; +} + diff --git a/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_LINE_C2_FEM/test_02.hpp b/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_LINE_C2_FEM/test_02.hpp new file mode 100644 index 000000000000..7c40e6e00dd1 --- /dev/null +++ b/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_LINE_C2_FEM/test_02.hpp @@ -0,0 +1,184 @@ +// @HEADER +// ***************************************************************************** +// Intrepid2 Package +// +// Copyright 2007 NTESS and the Intrepid2 contributors. +// SPDX-License-Identifier: BSD-3-Clause +// ***************************************************************************** +// @HEADER + +/** \file test_02.hpp + \brief Unit tests for the Intrepid2::HGRAD_LINE_C2_FEM class. + \author Created by Kyungjoo Kim, Mauro Perego + */ + + +#include "Intrepid2_config.h" +#include "Kokkos_Random.hpp" +#ifdef HAVE_INTREPID2_DEBUG +#define INTREPID2_TEST_FOR_DEBUG_ABORT_OVERRIDE_TO_CONTINUE +#endif + +#include "Intrepid2_Types.hpp" +#include "Intrepid2_Utils.hpp" + +#include "Intrepid2_HGRAD_LINE_C2_FEM.hpp" +#include "packages/intrepid2/unit-test/Discretization/Basis/Setup.hpp" + +namespace Intrepid2 { + + namespace Test { + + // This test evaluates the basis functions at a set of points on a batch of cells using the team-level getValues, + // and compares the results with those obtained using the classic getValues function. + template + int HGRAD_LINE_C2_FEM_Test02(const bool verbose) { + + //! Setup test output stream. + Teuchos::RCP outStream = setup_output_stream( + verbose, "HGRAD_LINE_C2_FEM, Test 2", {} + ); + + *outStream + << "\n" + << "===============================================================================\n" + << "| Testing Team-level Implemntation of getValues |\n" + << "===============================================================================\n"; + + using DeviceSpaceType = typename DeviceType::execution_space; + Kokkos::print_configuration(std::cout, false); + + int errorFlag = 0; + + try { + using BasisType = Basis_HGRAD_LINE_C2_FEM; + auto basisPtr = Teuchos::rcp(new BasisType()); + + const int ncells = 5, npts = 10, ndim = 1; + Kokkos::DynRankView ConstructWithLabelOutView(outputValuesA, ncells, basisPtr->getCardinality(), npts); + Kokkos::DynRankView ConstructWithLabelOutView(outputValuesB, basisPtr->getCardinality(), npts); + + Kokkos::DynRankView ConstructWithLabelOutView(outputGradsA, ncells, basisPtr->getCardinality(), npts, ndim); + Kokkos::DynRankView ConstructWithLabelOutView(outputGradsB, basisPtr->getCardinality(), npts, ndim); + Kokkos::DynRankView ConstructWithLabelPointView(point, 1); + + using ScalarType = typename ScalarTraits::scalar_type; + + Kokkos::View inputPointsViewToUseRandom("inputPoints", npts*ndim*get_dimension_scalar(point)); + auto vcprop = Kokkos::common_view_alloc_prop(point); + Kokkos::DynRankView inputPoints (Kokkos::view_wrap(inputPointsViewToUseRandom.data(), vcprop), npts, ndim); + + // random values between (0,1) + Kokkos::Random_XorShift64_Pool random(13718); + Kokkos::fill_random(inputPointsViewToUseRandom, random, 1.0); + + + *outStream << "Computing values and gradients for " << ncells << " cells and " << npts << " points using team-level getValues function" <(*basisPtr); + auto basisRawPtr_device = basisPtr_device.get(); + + int scratch_space_level =1; + const int vectorSize = getVectorSizeForHierarchicalParallelism(); + Kokkos::TeamPolicy teamPolicy(ncells, Kokkos::AUTO,vectorSize); + + { //compute values + auto functor = KOKKOS_LAMBDA (typename Kokkos::TeamPolicy::member_type team_member) { + auto valsACell = Kokkos::subview(outputValuesA, team_member.league_rank(), Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL()); + basisRawPtr_device->getValues(valsACell, inputPoints, OPERATOR_VALUE, team_member, team_member.team_scratch(scratch_space_level)); + }; + + //Get the required size of the scratch space per team and per thread. + int perThreadSpaceSize(0), perTeamSpaceSize(0); + basisPtr->getScratchSpaceSize(perTeamSpaceSize,perThreadSpaceSize,inputPoints, OPERATOR_VALUE); + teamPolicy.set_scratch_size(scratch_space_level, Kokkos::PerTeam(perTeamSpaceSize), Kokkos::PerThread(perThreadSpaceSize)); + + Kokkos::parallel_for (teamPolicy,functor); + } + + { //compute gradients + auto functor = KOKKOS_LAMBDA (typename Kokkos::TeamPolicy::member_type team_member) { + auto gradsACell = Kokkos::subview(outputGradsA, team_member.league_rank(), Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL()); + basisRawPtr_device->getValues(gradsACell, inputPoints, OPERATOR_GRAD, team_member, team_member.team_scratch(scratch_space_level)); + }; + + //Get the required size of the scratch space per team and per thread. + int perThreadSpaceSize(0), perTeamSpaceSize(0); + basisPtr->getScratchSpaceSize(perTeamSpaceSize,perThreadSpaceSize,inputPoints, OPERATOR_GRAD); + teamPolicy.set_scratch_size(scratch_space_level, Kokkos::PerTeam(perTeamSpaceSize), Kokkos::PerThread(perThreadSpaceSize)); + + Kokkos::parallel_for (teamPolicy,functor); + } + } + + *outStream << "Computing values and gradients for " << npts << " points using high-level getValues function" <getValues(outputValuesB, inputPoints, OPERATOR_VALUE); + basisPtr->getValues(outputGradsB, inputPoints, OPERATOR_GRAD); + + *outStream << "Comparing values and gradients on host" <(); + for (size_t ic=0;ic tol) { + ++errorFlag; + std::cout << ", ic: " << ic << ", i: " << i << ", j: " << j + << ", val A: " << outputValuesA_Host(ic,i,j) + << ", val B: " << outputValuesB_Host(i,j) + << ", |diff|: " << diff + << ", tol: " << tol + << std::endl; + } + } + } + + { + // compare grads + const auto outputGradsA_Host = Kokkos::create_mirror_view(outputGradsA); Kokkos::deep_copy(outputGradsA_Host, outputGradsA); + const auto outputGradsB_Host = Kokkos::create_mirror_view(outputGradsB); Kokkos::deep_copy(outputGradsB_Host, outputGradsB); + + OutValueType diff = 0; + auto tol = epsilon(); + for (size_t ic=0;ic tol) { + ++errorFlag; + std::cout << ", ic: " << ic << ", i: " << i << ", j: " << j + << ", grads A: [" << outputGradsA_Host(ic,i,j,0) << "]" + << ", grads B: [" << outputGradsB_Host(i,j,0) << "]" + << ", |diff|: " << diff + << ", tol: " << tol + << std::endl; + } + } + } + } catch (std::exception &err) { + std::cout << "UNEXPECTED ERROR !!! ----------------------------------------------------------\n"; + std::cout << err.what() << '\n'; + std::cout << "-------------------------------------------------------------------------------" << "\n\n"; + errorFlag = -1000; + }; + + if (errorFlag != 0) + std::cout << "End Result: TEST FAILED\n"; + else + std::cout << "End Result: TEST PASSED\n"; + + return errorFlag; + } + } +} diff --git a/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_LINE_Cn_FEM/CMakeLists.txt b/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_LINE_Cn_FEM/CMakeLists.txt index 40be3eb7ddf0..088e2285ac8f 100644 --- a/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_LINE_Cn_FEM/CMakeLists.txt +++ b/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_LINE_Cn_FEM/CMakeLists.txt @@ -1,8 +1,13 @@ TRIBITS_INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}) + +# test +SET(Intrepid2_TEST_ETI_FILE "test_01") + # value types SET(Intrepid2_TEST_ETI_VALUETYPE_NAME "") SET(Intrepid2_TEST_ETI_VALUETYPE "") +SET(Intrepid2_TEST_ETI_SACADO "") LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE_NAME "DOUBLE_DOUBLE") LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE "double,double") @@ -32,9 +37,80 @@ ENDIF() LIST(LENGTH Intrepid2_TEST_ETI_VALUETYPE_NAME ETI_VALUETYPE_COUNT) MATH(EXPR ETI_VALUETYPE_COUNT "${ETI_VALUETYPE_COUNT}-1") +# device +SET(Intrepid2_TEST_ETI_DEVICE_NAME "") +SET(Intrepid2_TEST_ETI_DEVICE "") +IF(Kokkos_ENABLE_SERIAL) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "Serial") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() +IF(Kokkos_ENABLE_OPENMP) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "OpenMP") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() +IF(Kokkos_ENABLE_CUDA) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "CUDA") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() +IF(Kokkos_ENABLE_HIP) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "HIP") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() + +LIST(LENGTH Intrepid2_TEST_ETI_DEVICE_NAME ETI_DEVICE_COUNT) +MATH(EXPR ETI_DEVICE_COUNT "${ETI_DEVICE_COUNT}-1") + +FOREACH(I RANGE ${ETI_DEVICE_COUNT}) + LIST(GET Intrepid2_TEST_ETI_DEVICE_NAME ${I} ETI_DEVICE_NAME) + LIST(GET Intrepid2_TEST_ETI_DEVICE ${I} ETI_DEVICE) + #MESSAGE(STATUS "Generating TEST HGRAD_LINE_Cn_FEM for ${ETI_DEVICE_NAME} with ${ETI_DEVICE}") + FOREACH(J RANGE ${ETI_VALUETYPE_COUNT}) + LIST(GET Intrepid2_TEST_ETI_VALUETYPE_NAME ${J} ETI_VALUETYPE_NAME) + LIST(GET Intrepid2_TEST_ETI_VALUETYPE ${J} ETI_VALUETYPE) + LIST(GET Intrepid2_TEST_ETI_SACADO ${J} ETI_SACADO) + FOREACH(ETI_FILE IN LISTS Intrepid2_TEST_ETI_FILE) + SET(ETI_NAME "${ETI_FILE}_${ETI_DEVICE_NAME}_${ETI_VALUETYPE_NAME}") + MESSAGE(STATUS "Generating TEST: HGRAD_LINE_Cn_FEM ${ETI_NAME}.cpp") + CONFIGURE_FILE(eti/${ETI_FILE}_ETI.in ${ETI_NAME}.cpp) + + TRIBITS_ADD_EXECUTABLE_AND_TEST( + ${ETI_NAME} + SOURCES ${ETI_NAME}.cpp + ARGS PrintItAll + NUM_MPI_PROCS 1 + PASS_REGULAR_EXPRESSION "TEST PASSED" + ADD_DIR_TO_NAME + ) + + ENDFOREACH() + ENDFOREACH() +ENDFOREACH() + + + + # test -SET(Intrepid2_TEST_ETI_FILE "test_01") +SET(Intrepid2_TEST_ETI_FILE "test_02") + +# value types +SET(Intrepid2_TEST_ETI_VALUETYPE_NAME "") +SET(Intrepid2_TEST_ETI_VALUETYPE "") +SET(Intrepid2_TEST_ETI_SACADO "") + +LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE_NAME "DOUBLE_DOUBLE") +LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE "double,double") +LIST(APPEND Intrepid2_TEST_ETI_SACADO "0") + +IF (HAVE_INTREPID2_SACADO) + LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE_NAME "DFAD_DFAD") + LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE "Sacado::Fad::DFad,Sacado::Fad::DFad ") + LIST(APPEND Intrepid2_TEST_ETI_SACADO "33") +ENDIF() + +LIST(LENGTH Intrepid2_TEST_ETI_VALUETYPE_NAME ETI_VALUETYPE_COUNT) +MATH(EXPR ETI_VALUETYPE_COUNT "${ETI_VALUETYPE_COUNT}-1") +# device SET(Intrepid2_TEST_ETI_DEVICE_NAME "") SET(Intrepid2_TEST_ETI_DEVICE "") IF(Kokkos_ENABLE_SERIAL) diff --git a/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_LINE_Cn_FEM/eti/test_01_ETI.in b/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_LINE_Cn_FEM/eti/test_01_ETI.in index 070fba1f3916..b662965e7493 100644 --- a/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_LINE_Cn_FEM/eti/test_01_ETI.in +++ b/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_LINE_Cn_FEM/eti/test_01_ETI.in @@ -28,10 +28,8 @@ constexpr int num_deriv = 10; #define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) #define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) #elif (ETI_SACADO == 23) -/// Mauro, the master branch uses this derivative dimension which sounds dummy -constexpr int num_deriv = 0; //9; -constexpr int max_deriv = 1; //10; -#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__, max_deriv+1) +constexpr int num_deriv = 3; +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) #define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) #elif (ETI_SACADO == 20) constexpr int num_deriv = 2; diff --git a/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_LINE_Cn_FEM/eti/test_02_ETI.in b/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_LINE_Cn_FEM/eti/test_02_ETI.in new file mode 100644 index 000000000000..2ff629694b47 --- /dev/null +++ b/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_LINE_Cn_FEM/eti/test_02_ETI.in @@ -0,0 +1,52 @@ +// @HEADER +// ***************************************************************************** +// Intrepid2 Package +// +// Copyright 2007 NTESS and the Intrepid2 contributors. +// SPDX-License-Identifier: BSD-3-Clause +// ***************************************************************************** +// @HEADER + +/** \file test_02.cpp + \brief Unit test of Intrepid2::Basis_HGRAD_LINE_Cn_FEM team-level get Values. + \author Kyungjoo Kim +*/ + +#include "Kokkos_Core.hpp" + +#define ETI_SACADO @ETI_SACADO@ +#if (ETI_SACADO != 0) /// SACADO +#include "Kokkos_ViewFactory.hpp" +#include "Sacado.hpp" +#endif + +#if (ETI_SACADO == 0) /// double double +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__) +#elif (ETI_SACADO == 11 /* SFAD SFAD */ || ETI_SACADO == 33 /* DFAD DFAD */) +constexpr int num_deriv = 3; +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#elif (ETI_SACADO == 23) +constexpr int num_deriv = 3; +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#elif (ETI_SACADO == 20) +constexpr int num_deriv = 2; +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__) +#endif + +#include "test_02.hpp" + +int main(int argc, char *argv[]) { + + const bool verbose = (argc-1) > 0; + Kokkos::initialize(); + + Intrepid2::Test::HGRAD_LINE_Cn_FEM_Test02<@ETI_VALUETYPE@,@ETI_DEVICE@>(verbose); + + Kokkos::finalize(); + return 0; +} + diff --git a/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_LINE_Cn_FEM/test_02.hpp b/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_LINE_Cn_FEM/test_02.hpp new file mode 100644 index 000000000000..23dafa935f7e --- /dev/null +++ b/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_LINE_Cn_FEM/test_02.hpp @@ -0,0 +1,188 @@ +// @HEADER +// ***************************************************************************** +// Intrepid2 Package +// +// Copyright 2007 NTESS and the Intrepid2 contributors. +// SPDX-License-Identifier: BSD-3-Clause +// ***************************************************************************** +// @HEADER + +/** \file test_02.hpp + \brief Unit tests for the Intrepid2::HGRAD_LINE_Cn_FEM class. + \author Created by Kyungjoo Kim, Mauro Perego + */ + + +#include "Intrepid2_config.h" +#include "Kokkos_Random.hpp" +#ifdef HAVE_INTREPID2_DEBUG +#define INTREPID2_TEST_FOR_DEBUG_ABORT_OVERRIDE_TO_CONTINUE +#endif + +#include "Intrepid2_Types.hpp" +#include "Intrepid2_Utils.hpp" + +#include "Intrepid2_HGRAD_LINE_Cn_FEM.hpp" +#include "packages/intrepid2/unit-test/Discretization/Basis/Setup.hpp" + +namespace Intrepid2 { + + namespace Test { + + // This test evaluates the basis functions at a set of points on a batch of cells using the team-level getValues, + // and compares the results with those obtained using the classic getValues function.s + template + int HGRAD_LINE_Cn_FEM_Test02(const bool verbose) { + + //! Setup test output stream. + Teuchos::RCP outStream = setup_output_stream( + verbose, "HGRAD_LINE_Cn_FEM, Test 2", {} + ); + + *outStream + << "\n" + << "===============================================================================\n" + << "| Testing Team-level Implemntation of getValues |\n" + << "===============================================================================\n"; + + using DeviceSpaceType = typename DeviceType::execution_space; + Kokkos::print_configuration(std::cout, false); + + int errorFlag = 0; + + try { + for (int order=1;order<=Parameters::MaxOrder;++order) { + using BasisType = Basis_HGRAD_LINE_Cn_FEM; + auto basisPtr = Teuchos::rcp(new BasisType(order)); + + const int ncells = 5, npts = 10, ndim = 1; + Kokkos::DynRankView ConstructWithLabelOutView(outputValuesA, ncells, basisPtr->getCardinality(), npts); + Kokkos::DynRankView ConstructWithLabelOutView(outputValuesB, basisPtr->getCardinality(), npts); + + Kokkos::DynRankView ConstructWithLabelOutView(outputGradsA, ncells, basisPtr->getCardinality(), npts, ndim); + Kokkos::DynRankView ConstructWithLabelOutView(outputGradsB, basisPtr->getCardinality(), npts, ndim); + Kokkos::DynRankView ConstructWithLabelPointView(point, 1); + + using ScalarType = typename ScalarTraits::scalar_type; + + Kokkos::View inputPointsViewToUseRandom("inputPoints", npts*ndim*get_dimension_scalar(point)); + auto vcprop = Kokkos::common_view_alloc_prop(point); + Kokkos::DynRankView inputPoints (Kokkos::view_wrap(inputPointsViewToUseRandom.data(), vcprop), npts, ndim); + + // random values between (0,1) + Kokkos::Random_XorShift64_Pool random(13718); + Kokkos::fill_random(inputPointsViewToUseRandom, random, 1.0); + + + *outStream << "Order: " << order << ": Computing values and gradients for " << ncells << " cells and " << npts << " points using team-level getValues function" <(*basisPtr); + auto basisRawPtr_device = basisPtr_device.get(); + + int scratch_space_level =1; + const int vectorSize = getVectorSizeForHierarchicalParallelism(); + Kokkos::TeamPolicy teamPolicy(ncells, Kokkos::AUTO,vectorSize); + + { //compute values + auto functor = KOKKOS_LAMBDA (typename Kokkos::TeamPolicy::member_type team_member) { + auto valsACell = Kokkos::subview(outputValuesA, team_member.league_rank(), Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL()); + basisRawPtr_device->getValues(valsACell, inputPoints, OPERATOR_VALUE, team_member, team_member.team_scratch(scratch_space_level)); + }; + + //Get the required size of the scratch space per team and per thread. + int perThreadSpaceSize(0), perTeamSpaceSize(0); + basisPtr->getScratchSpaceSize(perTeamSpaceSize,perThreadSpaceSize,inputPoints, OPERATOR_VALUE); + teamPolicy.set_scratch_size(scratch_space_level, Kokkos::PerTeam(perTeamSpaceSize), Kokkos::PerThread(perThreadSpaceSize)); + + Kokkos::parallel_for (teamPolicy,functor); + } + + { //compute gradients + auto functor = KOKKOS_LAMBDA (typename Kokkos::TeamPolicy::member_type team_member) { + auto gradsACell = Kokkos::subview(outputGradsA, team_member.league_rank(), Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL()); + basisRawPtr_device->getValues(gradsACell, inputPoints, OPERATOR_GRAD, team_member, team_member.team_scratch(scratch_space_level)); + }; + + //Get the required size of the scratch space per team and per thread. + int perThreadSpaceSize(0), perTeamSpaceSize(0); + basisPtr->getScratchSpaceSize(perTeamSpaceSize,perThreadSpaceSize,inputPoints, OPERATOR_GRAD); + teamPolicy.set_scratch_size(scratch_space_level, Kokkos::PerTeam(perTeamSpaceSize), Kokkos::PerThread(perThreadSpaceSize)); + + Kokkos::parallel_for (teamPolicy,functor); + } + } + + *outStream << "Order: " << order << ": Computing values and gradients for " << npts << " points using high-level getValues function" <getValues(outputValuesB, inputPoints, OPERATOR_VALUE); + basisPtr->getValues(outputGradsB, inputPoints, OPERATOR_GRAD); + + *outStream << "Order: " << order << ": Comparing values and gradients on host" <(); + for (size_t ic=0;ic tol) { + ++errorFlag; + std::cout << " order: " << order + << ", ic: " << ic << ", i: " << i << ", j: " << j + << ", val A: " << outputValuesA_Host(ic,i,j) + << ", val B: " << outputValuesB_Host(i,j) + << ", |diff|: " << diff + << ", tol: " << tol + << std::endl; + } + } + } + + { + // compare grads + const auto outputGradsA_Host = Kokkos::create_mirror_view(outputGradsA); Kokkos::deep_copy(outputGradsA_Host, outputGradsA); + const auto outputGradsB_Host = Kokkos::create_mirror_view(outputGradsB); Kokkos::deep_copy(outputGradsB_Host, outputGradsB); + + OutValueType diff = 0; + auto tol = epsilon(); + for (size_t ic=0;ic tol) { + ++errorFlag; + std::cout << " order: " << order + << ", ic: " << ic << ", i: " << i << ", j: " << j + << ", grads A: [" << outputGradsA_Host(ic,i,j,0) << "]" + << ", grads B: [" << outputGradsB_Host(i,j,0) << "]" + << ", |diff|: " << diff + << ", tol: " << tol + << std::endl; + } + } + } + } + } catch (std::exception &err) { + std::cout << "UNEXPECTED ERROR !!! ----------------------------------------------------------\n"; + std::cout << err.what() << '\n'; + std::cout << "-------------------------------------------------------------------------------" << "\n\n"; + errorFlag = -1000; + }; + + if (errorFlag != 0) + std::cout << "End Result: TEST FAILED\n"; + else + std::cout << "End Result: TEST PASSED\n"; + + return errorFlag; + } + } +} diff --git a/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_PYR_C1_FEM/CMakeLists.txt b/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_PYR_C1_FEM/CMakeLists.txt index aac1913c1e91..60b3eaa1ed20 100644 --- a/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_PYR_C1_FEM/CMakeLists.txt +++ b/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_PYR_C1_FEM/CMakeLists.txt @@ -1,8 +1,13 @@ TRIBITS_INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}) + +# test +SET(Intrepid2_TEST_ETI_FILE "test_01") + # value types SET(Intrepid2_TEST_ETI_VALUETYPE_NAME "") SET(Intrepid2_TEST_ETI_VALUETYPE "") +SET(Intrepid2_TEST_ETI_SACADO "") LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE_NAME "DOUBLE") LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE "double") @@ -17,9 +22,80 @@ ENDIF() LIST(LENGTH Intrepid2_TEST_ETI_VALUETYPE_NAME ETI_VALUETYPE_COUNT) MATH(EXPR ETI_VALUETYPE_COUNT "${ETI_VALUETYPE_COUNT}-1") -# Host test -SET(Intrepid2_TEST_ETI_FILE "test_01") +# device +SET(Intrepid2_TEST_ETI_DEVICE_NAME "") +SET(Intrepid2_TEST_ETI_DEVICE "") +IF(Kokkos_ENABLE_SERIAL) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "Serial") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() +IF(Kokkos_ENABLE_OPENMP) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "OpenMP") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() +IF(Kokkos_ENABLE_CUDA) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "CUDA") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() +IF(Kokkos_ENABLE_HIP) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "HIP") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() + +LIST(LENGTH Intrepid2_TEST_ETI_DEVICE_NAME ETI_DEVICE_COUNT) +MATH(EXPR ETI_DEVICE_COUNT "${ETI_DEVICE_COUNT}-1") + +FOREACH(I RANGE ${ETI_DEVICE_COUNT}) + LIST(GET Intrepid2_TEST_ETI_DEVICE_NAME ${I} ETI_DEVICE_NAME) + LIST(GET Intrepid2_TEST_ETI_DEVICE ${I} ETI_DEVICE) + #MESSAGE(STATUS "Generating TEST HGRAD_PYR_C1_FEM for ${ETI_DEVICE_NAME} with ${ETI_DEVICE}") + FOREACH(J RANGE ${ETI_VALUETYPE_COUNT}) + LIST(GET Intrepid2_TEST_ETI_VALUETYPE_NAME ${J} ETI_VALUETYPE_NAME) + LIST(GET Intrepid2_TEST_ETI_VALUETYPE ${J} ETI_VALUETYPE) + LIST(GET Intrepid2_TEST_ETI_SACADO ${J} ETI_SACADO) + FOREACH(ETI_FILE IN LISTS Intrepid2_TEST_ETI_FILE) + SET(ETI_NAME "${ETI_FILE}_${ETI_DEVICE_NAME}_${ETI_VALUETYPE_NAME}") + MESSAGE(STATUS "Generating TEST: HGRAD_PYR_C1_FEM ${ETI_NAME}.cpp") + CONFIGURE_FILE(eti/${ETI_FILE}_ETI.in ${ETI_NAME}.cpp) + + TRIBITS_ADD_EXECUTABLE_AND_TEST( + ${ETI_NAME} + SOURCES ${ETI_NAME}.cpp + ARGS PrintItAll + NUM_MPI_PROCS 1 + PASS_REGULAR_EXPRESSION "TEST PASSED" + ADD_DIR_TO_NAME + ) + + ENDFOREACH() + ENDFOREACH() +ENDFOREACH() + + + + +# test +SET(Intrepid2_TEST_ETI_FILE "test_02") + +# value types +SET(Intrepid2_TEST_ETI_VALUETYPE_NAME "") +SET(Intrepid2_TEST_ETI_VALUETYPE "") +SET(Intrepid2_TEST_ETI_SACADO "") + +LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE_NAME "DOUBLE_DOUBLE") +LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE "double,double") +LIST(APPEND Intrepid2_TEST_ETI_SACADO "0") + +IF (HAVE_INTREPID2_SACADO) + LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE_NAME "DFAD_DFAD") + LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE "Sacado::Fad::DFad,Sacado::Fad::DFad ") + LIST(APPEND Intrepid2_TEST_ETI_SACADO "33") +ENDIF() + +LIST(LENGTH Intrepid2_TEST_ETI_VALUETYPE_NAME ETI_VALUETYPE_COUNT) +MATH(EXPR ETI_VALUETYPE_COUNT "${ETI_VALUETYPE_COUNT}-1") +# device SET(Intrepid2_TEST_ETI_DEVICE_NAME "") SET(Intrepid2_TEST_ETI_DEVICE "") IF(Kokkos_ENABLE_SERIAL) diff --git a/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_PYR_C1_FEM/eti/test_02_ETI.in b/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_PYR_C1_FEM/eti/test_02_ETI.in new file mode 100644 index 000000000000..ac8e1393df20 --- /dev/null +++ b/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_PYR_C1_FEM/eti/test_02_ETI.in @@ -0,0 +1,52 @@ +// @HEADER +// ***************************************************************************** +// Intrepid2 Package +// +// Copyright 2007 NTESS and the Intrepid2 contributors. +// SPDX-License-Identifier: BSD-3-Clause +// ***************************************************************************** +// @HEADER + +/** \file test_01.cpp + \brief Unit test of Intrepid2::Basis_HGRAD_PYR_C1_FEM team-level getValues. + \author Kyungjoo Kim +*/ + +#include "Kokkos_Core.hpp" + +#define ETI_SACADO @ETI_SACADO@ +#if (ETI_SACADO != 0) /// SACADO +#include "Kokkos_ViewFactory.hpp" +#include "Sacado.hpp" +#endif + +#if (ETI_SACADO == 0) /// double double +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__) +#elif (ETI_SACADO == 11 /* SFAD SFAD */ || ETI_SACADO == 33 /* DFAD DFAD */) +constexpr int num_deriv = 3; +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#elif (ETI_SACADO == 23) +constexpr int num_deriv = 3; +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#elif (ETI_SACADO == 20) +constexpr int num_deriv = 2; +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__) +#endif + +#include "test_02.hpp" + +int main(int argc, char *argv[]) { + + const bool verbose = (argc-1) > 0; + Kokkos::initialize(); + + Intrepid2::Test::HGRAD_PYR_C1_FEM_Test02<@ETI_VALUETYPE@,@ETI_DEVICE@>(verbose); + + Kokkos::finalize(); + return 0; +} + diff --git a/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_PYR_C1_FEM/test_02.hpp b/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_PYR_C1_FEM/test_02.hpp new file mode 100644 index 000000000000..ae1ba8b9b47d --- /dev/null +++ b/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_PYR_C1_FEM/test_02.hpp @@ -0,0 +1,184 @@ +// @HEADER +// ***************************************************************************** +// Intrepid2 Package +// +// Copyright 2007 NTESS and the Intrepid2 contributors. +// SPDX-License-Identifier: BSD-3-Clause +// ***************************************************************************** +// @HEADER + +/** \file test_02.hpp + \brief Unit tests for the Intrepid2::HGRAD_PYR_C1_FEM class. + \author Created by Kyungjoo Kim, Mauro Perego + */ + + +#include "Intrepid2_config.h" +#include "Kokkos_Random.hpp" +#ifdef HAVE_INTREPID2_DEBUG +#define INTREPID2_TEST_FOR_DEBUG_ABORT_OVERRIDE_TO_CONTINUE +#endif + +#include "Intrepid2_Types.hpp" +#include "Intrepid2_Utils.hpp" + +#include "Intrepid2_HGRAD_PYR_C1_FEM.hpp" +#include "packages/intrepid2/unit-test/Discretization/Basis/Setup.hpp" + +namespace Intrepid2 { + + namespace Test { + + // This test evaluates the basis functions at a set of points on a batch of cells using the team-level getValues, + // and compares the results with those obtained using the classic getValues function. + template + int HGRAD_PYR_C1_FEM_Test02(const bool verbose) { + + //! Setup test output stream. + Teuchos::RCP outStream = setup_output_stream( + verbose, "HGRAD_PYR_C1_FEM, Test 2", {} + ); + + *outStream + << "\n" + << "===============================================================================\n" + << "| Testing Team-level Implemntation of getValues |\n" + << "===============================================================================\n"; + + using DeviceSpaceType = typename DeviceType::execution_space; + Kokkos::print_configuration(std::cout, false); + + int errorFlag = 0; + + try { + using BasisType = Basis_HGRAD_PYR_C1_FEM; + auto basisPtr = Teuchos::rcp(new BasisType()); + + const int ncells = 5, npts = 10, ndim = 3; + Kokkos::DynRankView ConstructWithLabelOutView(outputValuesA, ncells, basisPtr->getCardinality(), npts); + Kokkos::DynRankView ConstructWithLabelOutView(outputValuesB, basisPtr->getCardinality(), npts); + + Kokkos::DynRankView ConstructWithLabelOutView(outputGradsA, ncells, basisPtr->getCardinality(), npts, ndim); + Kokkos::DynRankView ConstructWithLabelOutView(outputGradsB, basisPtr->getCardinality(), npts, ndim); + Kokkos::DynRankView ConstructWithLabelPointView(point, 1); + + using ScalarType = typename ScalarTraits::scalar_type; + + Kokkos::View inputPointsViewToUseRandom("inputPoints", npts*ndim*get_dimension_scalar(point)); + auto vcprop = Kokkos::common_view_alloc_prop(point); + Kokkos::DynRankView inputPoints (Kokkos::view_wrap(inputPointsViewToUseRandom.data(), vcprop), npts, ndim); + + // random values between (0,1) + Kokkos::Random_XorShift64_Pool random(13718); + Kokkos::fill_random(inputPointsViewToUseRandom, random, 1.0); + + + *outStream << "Computing values and gradients for " << ncells << " cells and " << npts << " points using team-level getValues function" <(*basisPtr); + auto basisRawPtr_device = basisPtr_device.get(); + + int scratch_space_level =1; + const int vectorSize = getVectorSizeForHierarchicalParallelism(); + Kokkos::TeamPolicy teamPolicy(ncells, Kokkos::AUTO,vectorSize); + + { //compute values + auto functor = KOKKOS_LAMBDA (typename Kokkos::TeamPolicy::member_type team_member) { + auto valsACell = Kokkos::subview(outputValuesA, team_member.league_rank(), Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL()); + basisRawPtr_device->getValues(valsACell, inputPoints, OPERATOR_VALUE, team_member, team_member.team_scratch(scratch_space_level)); + }; + + //Get the required size of the scratch space per team and per thread. + int perThreadSpaceSize(0), perTeamSpaceSize(0); + basisPtr->getScratchSpaceSize(perTeamSpaceSize,perThreadSpaceSize,inputPoints, OPERATOR_VALUE); + teamPolicy.set_scratch_size(scratch_space_level, Kokkos::PerTeam(perTeamSpaceSize), Kokkos::PerThread(perThreadSpaceSize)); + + Kokkos::parallel_for (teamPolicy,functor); + } + + { //compute gradients + auto functor = KOKKOS_LAMBDA (typename Kokkos::TeamPolicy::member_type team_member) { + auto gradsACell = Kokkos::subview(outputGradsA, team_member.league_rank(), Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL()); + basisRawPtr_device->getValues(gradsACell, inputPoints, OPERATOR_GRAD, team_member, team_member.team_scratch(scratch_space_level)); + }; + + //Get the required size of the scratch space per team and per thread. + int perThreadSpaceSize(0), perTeamSpaceSize(0); + basisPtr->getScratchSpaceSize(perTeamSpaceSize,perThreadSpaceSize,inputPoints, OPERATOR_GRAD); + teamPolicy.set_scratch_size(scratch_space_level, Kokkos::PerTeam(perTeamSpaceSize), Kokkos::PerThread(perThreadSpaceSize)); + + Kokkos::parallel_for (teamPolicy,functor); + } + } + + *outStream << "Computing values and gradients for " << npts << " points using high-level getValues function" <getValues(outputValuesB, inputPoints, OPERATOR_VALUE); + basisPtr->getValues(outputGradsB, inputPoints, OPERATOR_GRAD); + + *outStream << "Comparing values and gradients on host" <(); + for (size_t ic=0;ic tol) { + ++errorFlag; + std::cout << ", ic: " << ic << ", i: " << i << ", j: " << j + << ", val A: " << outputValuesA_Host(ic,i,j) + << ", val B: " << outputValuesB_Host(i,j) + << ", |diff|: " << diff + << ", tol: " << tol + << std::endl; + } + } + } + + { + // compare grads + const auto outputGradsA_Host = Kokkos::create_mirror_view(outputGradsA); Kokkos::deep_copy(outputGradsA_Host, outputGradsA); + const auto outputGradsB_Host = Kokkos::create_mirror_view(outputGradsB); Kokkos::deep_copy(outputGradsB_Host, outputGradsB); + + OutValueType diff = 0; + auto tol = epsilon(); + for (size_t ic=0;ic tol) { + ++errorFlag; + std::cout << ", ic: " << ic << ", i: " << i << ", j: " << j + << ", grads A: [" << outputGradsA_Host(ic,i,j,0) << ", " << outputGradsA_Host(ic,i,j,1) << ", " << outputGradsA_Host(ic,i,j,2) <<"]" + << ", grads B: [" << outputGradsB_Host(i,j,0) << ", " << outputGradsB_Host(i,j,1) << ", " << outputGradsB_Host(i,j,2) <<"]" + << ", |diff|: " << diff + << ", tol: " << tol + << std::endl; + } + } + } + } catch (std::exception &err) { + std::cout << "UNEXPECTED ERROR !!! ----------------------------------------------------------\n"; + std::cout << err.what() << '\n'; + std::cout << "-------------------------------------------------------------------------------" << "\n\n"; + errorFlag = -1000; + }; + + if (errorFlag != 0) + std::cout << "End Result: TEST FAILED\n"; + else + std::cout << "End Result: TEST PASSED\n"; + + return errorFlag; + } + } +} diff --git a/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_PYR_I2_FEM/CMakeLists.txt b/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_PYR_I2_FEM/CMakeLists.txt index fdbf58124c2e..813910ef9f3d 100644 --- a/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_PYR_I2_FEM/CMakeLists.txt +++ b/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_PYR_I2_FEM/CMakeLists.txt @@ -1,8 +1,13 @@ TRIBITS_INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}) + +# test +SET(Intrepid2_TEST_ETI_FILE "test_01") + # value types SET(Intrepid2_TEST_ETI_VALUETYPE_NAME "") SET(Intrepid2_TEST_ETI_VALUETYPE "") +SET(Intrepid2_TEST_ETI_SACADO "") LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE_NAME "DOUBLE") LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE "double") @@ -17,9 +22,7 @@ ENDIF() LIST(LENGTH Intrepid2_TEST_ETI_VALUETYPE_NAME ETI_VALUETYPE_COUNT) MATH(EXPR ETI_VALUETYPE_COUNT "${ETI_VALUETYPE_COUNT}-1") -# Host test -SET(Intrepid2_TEST_ETI_FILE "test_01") - +# device SET(Intrepid2_TEST_ETI_DEVICE_NAME "") SET(Intrepid2_TEST_ETI_DEVICE "") IF(Kokkos_ENABLE_SERIAL) @@ -68,6 +71,79 @@ FOREACH(I RANGE ${ETI_DEVICE_COUNT}) ENDFOREACH() ENDFOREACH() + + + +# test +SET(Intrepid2_TEST_ETI_FILE "test_02") + +# value types +SET(Intrepid2_TEST_ETI_VALUETYPE_NAME "") +SET(Intrepid2_TEST_ETI_VALUETYPE "") +SET(Intrepid2_TEST_ETI_SACADO "") + +LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE_NAME "DOUBLE_DOUBLE") +LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE "double,double") +LIST(APPEND Intrepid2_TEST_ETI_SACADO "0") + +IF (HAVE_INTREPID2_SACADO) + LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE_NAME "DFAD_DFAD") + LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE "Sacado::Fad::DFad,Sacado::Fad::DFad ") + LIST(APPEND Intrepid2_TEST_ETI_SACADO "33") +ENDIF() + +LIST(LENGTH Intrepid2_TEST_ETI_VALUETYPE_NAME ETI_VALUETYPE_COUNT) +MATH(EXPR ETI_VALUETYPE_COUNT "${ETI_VALUETYPE_COUNT}-1") + +# device +SET(Intrepid2_TEST_ETI_DEVICE_NAME "") +SET(Intrepid2_TEST_ETI_DEVICE "") +IF(Kokkos_ENABLE_SERIAL) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "Serial") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() +IF(Kokkos_ENABLE_OPENMP) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "OpenMP") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() +IF(Kokkos_ENABLE_CUDA) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "CUDA") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() +IF(Kokkos_ENABLE_HIP) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "HIP") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() + +LIST(LENGTH Intrepid2_TEST_ETI_DEVICE_NAME ETI_DEVICE_COUNT) +MATH(EXPR ETI_DEVICE_COUNT "${ETI_DEVICE_COUNT}-1") + +FOREACH(I RANGE ${ETI_DEVICE_COUNT}) + LIST(GET Intrepid2_TEST_ETI_DEVICE_NAME ${I} ETI_DEVICE_NAME) + LIST(GET Intrepid2_TEST_ETI_DEVICE ${I} ETI_DEVICE) + #MESSAGE(STATUS "Generating TEST HGRAD_TET_C1_FEM for ${ETI_DEVICE_NAME} with ${ETI_DEVICE}") + FOREACH(J RANGE ${ETI_VALUETYPE_COUNT}) + LIST(GET Intrepid2_TEST_ETI_VALUETYPE_NAME ${J} ETI_VALUETYPE_NAME) + LIST(GET Intrepid2_TEST_ETI_VALUETYPE ${J} ETI_VALUETYPE) + LIST(GET Intrepid2_TEST_ETI_SACADO ${J} ETI_SACADO) + FOREACH(ETI_FILE IN LISTS Intrepid2_TEST_ETI_FILE) + SET(ETI_NAME "${ETI_FILE}_${ETI_DEVICE_NAME}_${ETI_VALUETYPE_NAME}") + MESSAGE(STATUS "Generating TEST: HGRAD_TET_C1_FEM ${ETI_NAME}.cpp") + CONFIGURE_FILE(eti/${ETI_FILE}_ETI.in ${ETI_NAME}.cpp) + + TRIBITS_ADD_EXECUTABLE_AND_TEST( + ${ETI_NAME} + SOURCES ${ETI_NAME}.cpp + ARGS PrintItAll + NUM_MPI_PROCS 1 + PASS_REGULAR_EXPRESSION "TEST PASSED" + ADD_DIR_TO_NAME + ) + + ENDFOREACH() + ENDFOREACH() +ENDFOREACH() + TRIBITS_COPY_FILES_TO_BINARY_DIR(HGRAD_PYR_I2TestDataCopy SOURCE_FILES PYR_I2_D2Vals.dat diff --git a/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_PYR_I2_FEM/eti/test_02_ETI.in b/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_PYR_I2_FEM/eti/test_02_ETI.in new file mode 100644 index 000000000000..b1bc686c303d --- /dev/null +++ b/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_PYR_I2_FEM/eti/test_02_ETI.in @@ -0,0 +1,52 @@ +// @HEADER +// ***************************************************************************** +// Intrepid2 Package +// +// Copyright 2007 NTESS and the Intrepid2 contributors. +// SPDX-License-Identifier: BSD-3-Clause +// ***************************************************************************** +// @HEADER + +/** \file test_01.cpp + \brief Unit test of Intrepid2::Basis_HGRAD_PYR_I2_FEM team-level getValues. + \author Kyungjoo Kim +*/ + +#include "Kokkos_Core.hpp" + +#define ETI_SACADO @ETI_SACADO@ +#if (ETI_SACADO != 0) /// SACADO +#include "Kokkos_ViewFactory.hpp" +#include "Sacado.hpp" +#endif + +#if (ETI_SACADO == 0) /// double double +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__) +#elif (ETI_SACADO == 11 /* SFAD SFAD */ || ETI_SACADO == 33 /* DFAD DFAD */) +constexpr int num_deriv = 3; +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#elif (ETI_SACADO == 23) +constexpr int num_deriv = 3; +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#elif (ETI_SACADO == 20) +constexpr int num_deriv = 2; +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__) +#endif + +#include "test_02.hpp" + +int main(int argc, char *argv[]) { + + const bool verbose = (argc-1) > 0; + Kokkos::initialize(); + + Intrepid2::Test::HGRAD_PYR_I2_FEM_Test02<@ETI_VALUETYPE@,@ETI_DEVICE@>(verbose); + + Kokkos::finalize(); + return 0; +} + diff --git a/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_PYR_I2_FEM/test_02.hpp b/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_PYR_I2_FEM/test_02.hpp new file mode 100644 index 000000000000..39b7903b384a --- /dev/null +++ b/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_PYR_I2_FEM/test_02.hpp @@ -0,0 +1,184 @@ +// @HEADER +// ***************************************************************************** +// Intrepid2 Package +// +// Copyright 2007 NTESS and the Intrepid2 contributors. +// SPDX-License-Identifier: BSD-3-Clause +// ***************************************************************************** +// @HEADER + +/** \file test_02.hpp + \brief Unit tests for the Intrepid2::HGRAD_PYR_I2_FEM class. + \author Created by Kyungjoo Kim, Mauro Perego + */ + + +#include "Intrepid2_config.h" +#include "Kokkos_Random.hpp" +#ifdef HAVE_INTREPID2_DEBUG +#define INTREPID2_TEST_FOR_DEBUG_ABORT_OVERRIDE_TO_CONTINUE +#endif + +#include "Intrepid2_Types.hpp" +#include "Intrepid2_Utils.hpp" + +#include "Intrepid2_HGRAD_PYR_I2_FEM.hpp" +#include "packages/intrepid2/unit-test/Discretization/Basis/Setup.hpp" + +namespace Intrepid2 { + + namespace Test { + + // This test evaluates the basis functions at a set of points on a batch of cells using the team-level getValues, + // and compares the results with those obtained using the classic getValues function. + template + int HGRAD_PYR_I2_FEM_Test02(const bool verbose) { + + //! Setup test output stream. + Teuchos::RCP outStream = setup_output_stream( + verbose, "HGRAD_PYR_I2_FEM, Test 2", {} + ); + + *outStream + << "\n" + << "===============================================================================\n" + << "| Testing Team-level Implemntation of getValues |\n" + << "===============================================================================\n"; + + using DeviceSpaceType = typename DeviceType::execution_space; + Kokkos::print_configuration(std::cout, false); + + int errorFlag = 0; + + try { + using BasisType = Basis_HGRAD_PYR_I2_FEM; + auto basisPtr = Teuchos::rcp(new BasisType()); + + const int ncells = 5, npts = 10, ndim = 3; + Kokkos::DynRankView ConstructWithLabelOutView(outputValuesA, ncells, basisPtr->getCardinality(), npts); + Kokkos::DynRankView ConstructWithLabelOutView(outputValuesB, basisPtr->getCardinality(), npts); + + Kokkos::DynRankView ConstructWithLabelOutView(outputGradsA, ncells, basisPtr->getCardinality(), npts, ndim); + Kokkos::DynRankView ConstructWithLabelOutView(outputGradsB, basisPtr->getCardinality(), npts, ndim); + Kokkos::DynRankView ConstructWithLabelPointView(point, 1); + + using ScalarType = typename ScalarTraits::scalar_type; + + Kokkos::View inputPointsViewToUseRandom("inputPoints", npts*ndim*get_dimension_scalar(point)); + auto vcprop = Kokkos::common_view_alloc_prop(point); + Kokkos::DynRankView inputPoints (Kokkos::view_wrap(inputPointsViewToUseRandom.data(), vcprop), npts, ndim); + + // random values between (0,1) + Kokkos::Random_XorShift64_Pool random(13718); + Kokkos::fill_random(inputPointsViewToUseRandom, random, 1.0); + + + *outStream << "Computing values and gradients for " << ncells << " cells and " << npts << " points using team-level getValues function" <(*basisPtr); + auto basisRawPtr_device = basisPtr_device.get(); + + int scratch_space_level =1; + const int vectorSize = getVectorSizeForHierarchicalParallelism(); + Kokkos::TeamPolicy teamPolicy(ncells, Kokkos::AUTO,vectorSize); + + { //compute values + auto functor = KOKKOS_LAMBDA (typename Kokkos::TeamPolicy::member_type team_member) { + auto valsACell = Kokkos::subview(outputValuesA, team_member.league_rank(), Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL()); + basisRawPtr_device->getValues(valsACell, inputPoints, OPERATOR_VALUE, team_member, team_member.team_scratch(scratch_space_level)); + }; + + //Get the required size of the scratch space per team and per thread. + int perThreadSpaceSize(0), perTeamSpaceSize(0); + basisPtr->getScratchSpaceSize(perTeamSpaceSize,perThreadSpaceSize,inputPoints, OPERATOR_VALUE); + teamPolicy.set_scratch_size(scratch_space_level, Kokkos::PerTeam(perTeamSpaceSize), Kokkos::PerThread(perThreadSpaceSize)); + + Kokkos::parallel_for (teamPolicy,functor); + } + + { //compute gradients + auto functor = KOKKOS_LAMBDA (typename Kokkos::TeamPolicy::member_type team_member) { + auto gradsACell = Kokkos::subview(outputGradsA, team_member.league_rank(), Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL()); + basisRawPtr_device->getValues(gradsACell, inputPoints, OPERATOR_GRAD, team_member, team_member.team_scratch(scratch_space_level)); + }; + + //Get the required size of the scratch space per team and per thread. + int perThreadSpaceSize(0), perTeamSpaceSize(0); + basisPtr->getScratchSpaceSize(perTeamSpaceSize,perThreadSpaceSize,inputPoints, OPERATOR_GRAD); + teamPolicy.set_scratch_size(scratch_space_level, Kokkos::PerTeam(perTeamSpaceSize), Kokkos::PerThread(perThreadSpaceSize)); + + Kokkos::parallel_for (teamPolicy,functor); + } + } + + *outStream << "Computing values and gradients for " << npts << " points using high-level getValues function" <getValues(outputValuesB, inputPoints, OPERATOR_VALUE); + basisPtr->getValues(outputGradsB, inputPoints, OPERATOR_GRAD); + + *outStream << "Comparing values and gradients on host" <(); + for (size_t ic=0;ic tol) { + ++errorFlag; + std::cout << ", ic: " << ic << ", i: " << i << ", j: " << j + << ", val A: " << outputValuesA_Host(ic,i,j) + << ", val B: " << outputValuesB_Host(i,j) + << ", |diff|: " << diff + << ", tol: " << tol + << std::endl; + } + } + } + + { + // compare grads + const auto outputGradsA_Host = Kokkos::create_mirror_view(outputGradsA); Kokkos::deep_copy(outputGradsA_Host, outputGradsA); + const auto outputGradsB_Host = Kokkos::create_mirror_view(outputGradsB); Kokkos::deep_copy(outputGradsB_Host, outputGradsB); + + OutValueType diff = 0; + auto tol = epsilon(); + for (size_t ic=0;ic tol) { + ++errorFlag; + std::cout << ", ic: " << ic << ", i: " << i << ", j: " << j + << ", grads A: [" << outputGradsA_Host(ic,i,j,0) << ", " << outputGradsA_Host(ic,i,j,1) << ", " << outputGradsA_Host(ic,i,j,2) <<"]" + << ", grads B: [" << outputGradsB_Host(i,j,0) << ", " << outputGradsB_Host(i,j,1) << ", " << outputGradsB_Host(i,j,2) <<"]" + << ", |diff|: " << diff + << ", tol: " << tol + << std::endl; + } + } + } + } catch (std::exception &err) { + std::cout << "UNEXPECTED ERROR !!! ----------------------------------------------------------\n"; + std::cout << err.what() << '\n'; + std::cout << "-------------------------------------------------------------------------------" << "\n\n"; + errorFlag = -1000; + }; + + if (errorFlag != 0) + std::cout << "End Result: TEST FAILED\n"; + else + std::cout << "End Result: TEST PASSED\n"; + + return errorFlag; + } + } +} diff --git a/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_QUAD_C1_FEM/CMakeLists.txt b/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_QUAD_C1_FEM/CMakeLists.txt index ef324d6c681f..593042946b82 100644 --- a/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_QUAD_C1_FEM/CMakeLists.txt +++ b/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_QUAD_C1_FEM/CMakeLists.txt @@ -1,8 +1,13 @@ TRIBITS_INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}) + +# test +SET(Intrepid2_TEST_ETI_FILE "test_01") + # value types SET(Intrepid2_TEST_ETI_VALUETYPE_NAME "") SET(Intrepid2_TEST_ETI_VALUETYPE "") +SET(Intrepid2_TEST_ETI_SACADO "") LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE_NAME "DOUBLE") LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE "double") @@ -17,9 +22,80 @@ ENDIF() LIST(LENGTH Intrepid2_TEST_ETI_VALUETYPE_NAME ETI_VALUETYPE_COUNT) MATH(EXPR ETI_VALUETYPE_COUNT "${ETI_VALUETYPE_COUNT}-1") -# Host test -SET(Intrepid2_TEST_ETI_FILE "test_01") +# device +SET(Intrepid2_TEST_ETI_DEVICE_NAME "") +SET(Intrepid2_TEST_ETI_DEVICE "") +IF(Kokkos_ENABLE_SERIAL) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "Serial") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() +IF(Kokkos_ENABLE_OPENMP) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "OpenMP") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() +IF(Kokkos_ENABLE_CUDA) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "CUDA") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() +IF(Kokkos_ENABLE_HIP) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "HIP") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() + +LIST(LENGTH Intrepid2_TEST_ETI_DEVICE_NAME ETI_DEVICE_COUNT) +MATH(EXPR ETI_DEVICE_COUNT "${ETI_DEVICE_COUNT}-1") + +FOREACH(I RANGE ${ETI_DEVICE_COUNT}) + LIST(GET Intrepid2_TEST_ETI_DEVICE_NAME ${I} ETI_DEVICE_NAME) + LIST(GET Intrepid2_TEST_ETI_DEVICE ${I} ETI_DEVICE) + #MESSAGE(STATUS "Generating TEST HGRAD_QUAD_C1_FEM for ${ETI_DEVICE_NAME} with ${ETI_DEVICE}") + FOREACH(J RANGE ${ETI_VALUETYPE_COUNT}) + LIST(GET Intrepid2_TEST_ETI_VALUETYPE_NAME ${J} ETI_VALUETYPE_NAME) + LIST(GET Intrepid2_TEST_ETI_VALUETYPE ${J} ETI_VALUETYPE) + LIST(GET Intrepid2_TEST_ETI_SACADO ${J} ETI_SACADO) + FOREACH(ETI_FILE IN LISTS Intrepid2_TEST_ETI_FILE) + SET(ETI_NAME "${ETI_FILE}_${ETI_DEVICE_NAME}_${ETI_VALUETYPE_NAME}") + MESSAGE(STATUS "Generating TEST: HGRAD_QUAD_C1_FEM ${ETI_NAME}.cpp") + CONFIGURE_FILE(eti/${ETI_FILE}_ETI.in ${ETI_NAME}.cpp) + + TRIBITS_ADD_EXECUTABLE_AND_TEST( + ${ETI_NAME} + SOURCES ${ETI_NAME}.cpp + ARGS PrintItAll + NUM_MPI_PROCS 1 + PASS_REGULAR_EXPRESSION "TEST PASSED" + ADD_DIR_TO_NAME + ) + + ENDFOREACH() + ENDFOREACH() +ENDFOREACH() + + + + +# test +SET(Intrepid2_TEST_ETI_FILE "test_02") + +# value types +SET(Intrepid2_TEST_ETI_VALUETYPE_NAME "") +SET(Intrepid2_TEST_ETI_VALUETYPE "") +SET(Intrepid2_TEST_ETI_SACADO "") + +LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE_NAME "DOUBLE_DOUBLE") +LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE "double,double") +LIST(APPEND Intrepid2_TEST_ETI_SACADO "0") + +IF (HAVE_INTREPID2_SACADO) + LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE_NAME "DFAD_DFAD") + LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE "Sacado::Fad::DFad,Sacado::Fad::DFad ") + LIST(APPEND Intrepid2_TEST_ETI_SACADO "33") +ENDIF() + +LIST(LENGTH Intrepid2_TEST_ETI_VALUETYPE_NAME ETI_VALUETYPE_COUNT) +MATH(EXPR ETI_VALUETYPE_COUNT "${ETI_VALUETYPE_COUNT}-1") +# device SET(Intrepid2_TEST_ETI_DEVICE_NAME "") SET(Intrepid2_TEST_ETI_DEVICE "") IF(Kokkos_ENABLE_SERIAL) diff --git a/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_QUAD_C1_FEM/eti/test_02_ETI.in b/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_QUAD_C1_FEM/eti/test_02_ETI.in new file mode 100644 index 000000000000..7650cb60968c --- /dev/null +++ b/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_QUAD_C1_FEM/eti/test_02_ETI.in @@ -0,0 +1,52 @@ +// @HEADER +// ***************************************************************************** +// Intrepid2 Package +// +// Copyright 2007 NTESS and the Intrepid2 contributors. +// SPDX-License-Identifier: BSD-3-Clause +// ***************************************************************************** +// @HEADER + +/** \file test_01.cpp + \brief Unit test of serial interface Intrepid2::Basis_HGRAD_QUAD_C1_FEM. + \author Kyungjoo Kim +*/ + +#include "Kokkos_Core.hpp" + +#define ETI_SACADO @ETI_SACADO@ +#if (ETI_SACADO != 0) /// SACADO +#include "Kokkos_ViewFactory.hpp" +#include "Sacado.hpp" +#endif + +#if (ETI_SACADO == 0) /// double double +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__) +#elif (ETI_SACADO == 11 /* SFAD SFAD */ || ETI_SACADO == 33 /* DFAD DFAD */) +constexpr int num_deriv = 3; +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#elif (ETI_SACADO == 23) +constexpr int num_deriv = 3; +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#elif (ETI_SACADO == 20) +constexpr int num_deriv = 2; +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__) +#endif + +#include "test_02.hpp" + +int main(int argc, char *argv[]) { + + const bool verbose = (argc-1) > 0; + Kokkos::initialize(); + + Intrepid2::Test::HGRAD_QUAD_C1_FEM_Test02<@ETI_VALUETYPE@,@ETI_DEVICE@>(verbose); + + Kokkos::finalize(); + return 0; +} + diff --git a/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_QUAD_C1_FEM/test_02.hpp b/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_QUAD_C1_FEM/test_02.hpp new file mode 100644 index 000000000000..2dba47d6f022 --- /dev/null +++ b/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_QUAD_C1_FEM/test_02.hpp @@ -0,0 +1,228 @@ +// @HEADER +// ***************************************************************************** +// Intrepid2 Package +// +// Copyright 2007 NTESS and the Intrepid2 contributors. +// SPDX-License-Identifier: BSD-3-Clause +// ***************************************************************************** +// @HEADER + +/** \file test_02.hpp + \brief Unit tests for the Intrepid2::HGRAD_QUAD_C1_FEM class. + \author Created by Kyungjoo Kim, Mauro Perego + */ + + +#include "Intrepid2_config.h" +#include "Kokkos_Random.hpp" +#ifdef HAVE_INTREPID2_DEBUG +#define INTREPID2_TEST_FOR_DEBUG_ABORT_OVERRIDE_TO_CONTINUE +#endif + +#include "Intrepid2_Types.hpp" +#include "Intrepid2_Utils.hpp" + +#include "Intrepid2_HGRAD_QUAD_C1_FEM.hpp" +#include "packages/intrepid2/unit-test/Discretization/Basis/Setup.hpp" + +namespace Intrepid2 { + + namespace Test { + + // This test evaluates the basis functions at a set of points on a batch of cells using the team-level getValues, + // and compares the results with those obtained using the classic getValues function. + template + int HGRAD_QUAD_C1_FEM_Test02(const bool verbose) { + + //! Setup test output stream. + Teuchos::RCP outStream = setup_output_stream( + verbose, "HGRAD_QUAD_C1_FEM, Test 2", {} + ); + + *outStream + << "\n" + << "===============================================================================\n" + << "| Testing Team-level Implemntation of getValues |\n" + << "===============================================================================\n"; + + using DeviceSpaceType = typename DeviceType::execution_space; + Kokkos::print_configuration(std::cout, false); + + int errorFlag = 0; + + try { + using BasisType = Basis_HGRAD_QUAD_C1_FEM; + auto basisPtr = Teuchos::rcp(new BasisType()); + + const int ncells = 5, npts = 10, ndim = 2; + Kokkos::DynRankView ConstructWithLabelOutView(outputValuesA, ncells, basisPtr->getCardinality(), npts); + Kokkos::DynRankView ConstructWithLabelOutView(outputValuesB, basisPtr->getCardinality(), npts); + + Kokkos::DynRankView ConstructWithLabelOutView(outputGradsA, ncells, basisPtr->getCardinality(), npts, ndim); + Kokkos::DynRankView ConstructWithLabelOutView(outputGradsB, basisPtr->getCardinality(), npts, ndim); + + Kokkos::DynRankView ConstructWithLabelOutView(outputCurlsA, ncells, basisPtr->getCardinality(), npts, ndim); + Kokkos::DynRankView ConstructWithLabelOutView(outputCurlsB, basisPtr->getCardinality(), npts, ndim); + + Kokkos::DynRankView ConstructWithLabelPointView(point, 1); + + using ScalarType = typename ScalarTraits::scalar_type; + + Kokkos::View inputPointsViewToUseRandom("inputPoints", npts*ndim*get_dimension_scalar(point)); + auto vcprop = Kokkos::common_view_alloc_prop(point); + Kokkos::DynRankView inputPoints (Kokkos::view_wrap(inputPointsViewToUseRandom.data(), vcprop), npts, ndim); + + // random values between (0,1) + Kokkos::Random_XorShift64_Pool random(13718); + Kokkos::fill_random(inputPointsViewToUseRandom, random, 1.0); + + + *outStream << "Computing values and gradients for " << ncells << " cells and " << npts << " points using team-level getValues function" <(*basisPtr); + auto basisRawPtr_device = basisPtr_device.get(); + + int scratch_space_level =1; + const int vectorSize = getVectorSizeForHierarchicalParallelism(); + Kokkos::TeamPolicy teamPolicy(ncells, Kokkos::AUTO,vectorSize); + + { //compute values + auto functor = KOKKOS_LAMBDA (typename Kokkos::TeamPolicy::member_type team_member) { + auto valsACell = Kokkos::subview(outputValuesA, team_member.league_rank(), Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL()); + basisRawPtr_device->getValues(valsACell, inputPoints, OPERATOR_VALUE, team_member, team_member.team_scratch(scratch_space_level)); + }; + + //Get the required size of the scratch space per team and per thread. + int perThreadSpaceSize(0), perTeamSpaceSize(0); + basisPtr->getScratchSpaceSize(perTeamSpaceSize,perThreadSpaceSize,inputPoints, OPERATOR_VALUE); + teamPolicy.set_scratch_size(scratch_space_level, Kokkos::PerTeam(perTeamSpaceSize), Kokkos::PerThread(perThreadSpaceSize)); + + Kokkos::parallel_for (teamPolicy,functor); + } + + { //compute gradients + auto functor = KOKKOS_LAMBDA (typename Kokkos::TeamPolicy::member_type team_member) { + auto gradsACell = Kokkos::subview(outputGradsA, team_member.league_rank(), Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL()); + basisRawPtr_device->getValues(gradsACell, inputPoints, OPERATOR_GRAD, team_member, team_member.team_scratch(scratch_space_level)); + }; + + //Get the required size of the scratch space per team and per thread. + int perThreadSpaceSize(0), perTeamSpaceSize(0); + basisPtr->getScratchSpaceSize(perTeamSpaceSize,perThreadSpaceSize,inputPoints, OPERATOR_GRAD); + teamPolicy.set_scratch_size(scratch_space_level, Kokkos::PerTeam(perTeamSpaceSize), Kokkos::PerThread(perThreadSpaceSize)); + + Kokkos::parallel_for (teamPolicy,functor); + } + + { //compute curls + auto functor = KOKKOS_LAMBDA (typename Kokkos::TeamPolicy::member_type team_member) { + auto curlsACell = Kokkos::subview(outputCurlsA, team_member.league_rank(), Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL()); + basisRawPtr_device->getValues(curlsACell, inputPoints, OPERATOR_CURL, team_member, team_member.team_scratch(scratch_space_level)); + }; + + //Get the required size of the scratch space per team and per thread. + int perThreadSpaceSize(0), perTeamSpaceSize(0); + basisPtr->getScratchSpaceSize(perTeamSpaceSize,perThreadSpaceSize,inputPoints, OPERATOR_CURL); + teamPolicy.set_scratch_size(scratch_space_level, Kokkos::PerTeam(perTeamSpaceSize), Kokkos::PerThread(perThreadSpaceSize)); + + Kokkos::parallel_for (teamPolicy,functor); + } + } + + *outStream << "Computing values and gradients for " << npts << " points using high-level getValues function" <getValues(outputValuesB, inputPoints, OPERATOR_VALUE); + basisPtr->getValues(outputGradsB, inputPoints, OPERATOR_GRAD); + basisPtr->getValues(outputCurlsB, inputPoints, OPERATOR_CURL); + + *outStream << "Comparing values and gradients on host" <(); + for (size_t ic=0;ic tol) { + ++errorFlag; + std::cout << ", ic: " << ic << ", i: " << i << ", j: " << j + << ", val A: " << outputValuesA_Host(ic,i,j) + << ", val B: " << outputValuesB_Host(i,j) + << ", |diff|: " << diff + << ", tol: " << tol + << std::endl; + } + } + } + + { + // compare grads + const auto outputGradsA_Host = Kokkos::create_mirror_view(outputGradsA); Kokkos::deep_copy(outputGradsA_Host, outputGradsA); + const auto outputGradsB_Host = Kokkos::create_mirror_view(outputGradsB); Kokkos::deep_copy(outputGradsB_Host, outputGradsB); + + OutValueType diff = 0; + auto tol = epsilon(); + for (size_t ic=0;ic tol) { + ++errorFlag; + std::cout << ", ic: " << ic << ", i: " << i << ", j: " << j + << ", grads A: [" << outputGradsA_Host(ic,i,j,0) << ", " << outputGradsA_Host(ic,i,j,1) << "]" + << ", grads B: [" << outputGradsB_Host(i,j,0) << ", " << outputGradsB_Host(i,j,1) << "]" + << ", |diff|: " << diff + << ", tol: " << tol + << std::endl; + } + } + } + + { + // compare curls + const auto outputCurlsA_Host = Kokkos::create_mirror_view(outputCurlsA); Kokkos::deep_copy(outputCurlsA_Host, outputCurlsA); + const auto outputCurlsB_Host = Kokkos::create_mirror_view(outputCurlsB); Kokkos::deep_copy(outputCurlsB_Host, outputCurlsB); + + OutValueType diff = 0; + auto tol = epsilon(); + for (size_t ic=0;ic tol) { + ++errorFlag; + std::cout << ", ic: " << ic << ", i: " << i << ", j: " << j + << ", curls A: [" << outputCurlsA_Host(ic,i,j,0) << ", " << outputCurlsA_Host(ic,i,j,1) <<"]" + << ", curls B: [" << outputCurlsB_Host(i,j,0) << ", " << outputCurlsB_Host(i,j,1) << "]" + << ", |diff|: " << diff + << ", tol: " << tol + << std::endl; + } + } + } + } catch (std::exception &err) { + std::cout << "UNEXPECTED ERROR !!! ----------------------------------------------------------\n"; + std::cout << err.what() << '\n'; + std::cout << "-------------------------------------------------------------------------------" << "\n\n"; + errorFlag = -1000; + }; + + if (errorFlag != 0) + std::cout << "End Result: TEST FAILED\n"; + else + std::cout << "End Result: TEST PASSED\n"; + + return errorFlag; + } + } +} diff --git a/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_QUAD_C2_FEM/CMakeLists.txt b/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_QUAD_C2_FEM/CMakeLists.txt index 6d92bb337ac4..14d863a19fc7 100644 --- a/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_QUAD_C2_FEM/CMakeLists.txt +++ b/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_QUAD_C2_FEM/CMakeLists.txt @@ -1,8 +1,16 @@ TRIBITS_INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}) + +# test +SET(Intrepid2_TEST_ETI_FILE "") +LIST(APPEND Intrepid2_TEST_ETI_FILE + "test_01" + "test_01_Serendipity") + # value types SET(Intrepid2_TEST_ETI_VALUETYPE_NAME "") SET(Intrepid2_TEST_ETI_VALUETYPE "") +SET(Intrepid2_TEST_ETI_SACADO "") LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE_NAME "DOUBLE") LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE "double") @@ -17,12 +25,80 @@ ENDIF() LIST(LENGTH Intrepid2_TEST_ETI_VALUETYPE_NAME ETI_VALUETYPE_COUNT) MATH(EXPR ETI_VALUETYPE_COUNT "${ETI_VALUETYPE_COUNT}-1") -# Host test -SET(Intrepid2_TEST_ETI_FILE "") -LIST(APPEND Intrepid2_TEST_ETI_FILE - "test_01" - "test_01_Serendipity") +# device +SET(Intrepid2_TEST_ETI_DEVICE_NAME "") +SET(Intrepid2_TEST_ETI_DEVICE "") +IF(Kokkos_ENABLE_SERIAL) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "Serial") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() +IF(Kokkos_ENABLE_OPENMP) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "OpenMP") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() +IF(Kokkos_ENABLE_CUDA) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "CUDA") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() +IF(Kokkos_ENABLE_HIP) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "HIP") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() + +LIST(LENGTH Intrepid2_TEST_ETI_DEVICE_NAME ETI_DEVICE_COUNT) +MATH(EXPR ETI_DEVICE_COUNT "${ETI_DEVICE_COUNT}-1") + +FOREACH(I RANGE ${ETI_DEVICE_COUNT}) + LIST(GET Intrepid2_TEST_ETI_DEVICE_NAME ${I} ETI_DEVICE_NAME) + LIST(GET Intrepid2_TEST_ETI_DEVICE ${I} ETI_DEVICE) + #MESSAGE(STATUS "Generating TEST HGRAD_QUAD_C2_FEM for ${ETI_DEVICE_NAME} with ${ETI_DEVICE}") + FOREACH(J RANGE ${ETI_VALUETYPE_COUNT}) + LIST(GET Intrepid2_TEST_ETI_VALUETYPE_NAME ${J} ETI_VALUETYPE_NAME) + LIST(GET Intrepid2_TEST_ETI_VALUETYPE ${J} ETI_VALUETYPE) + LIST(GET Intrepid2_TEST_ETI_SACADO ${J} ETI_SACADO) + FOREACH(ETI_FILE IN LISTS Intrepid2_TEST_ETI_FILE) + SET(ETI_NAME "${ETI_FILE}_${ETI_DEVICE_NAME}_${ETI_VALUETYPE_NAME}") + MESSAGE(STATUS "Generating TEST: HGRAD_QUAD_C2_FEM ${ETI_NAME}.cpp") + CONFIGURE_FILE(eti/${ETI_FILE}_ETI.in ${ETI_NAME}.cpp) + + TRIBITS_ADD_EXECUTABLE_AND_TEST( + ${ETI_NAME} + SOURCES ${ETI_NAME}.cpp + ARGS PrintItAll + NUM_MPI_PROCS 1 + PASS_REGULAR_EXPRESSION "TEST PASSED" + ADD_DIR_TO_NAME + ) + + ENDFOREACH() + ENDFOREACH() +ENDFOREACH() + + + + +# test +SET(Intrepid2_TEST_ETI_FILE "test_02") + +# value types +SET(Intrepid2_TEST_ETI_VALUETYPE_NAME "") +SET(Intrepid2_TEST_ETI_VALUETYPE "") +SET(Intrepid2_TEST_ETI_SACADO "") + +LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE_NAME "DOUBLE_DOUBLE") +LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE "double,double") +LIST(APPEND Intrepid2_TEST_ETI_SACADO "0") + +IF (HAVE_INTREPID2_SACADO) + LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE_NAME "DFAD_DFAD") + LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE "Sacado::Fad::DFad,Sacado::Fad::DFad ") + LIST(APPEND Intrepid2_TEST_ETI_SACADO "33") +ENDIF() + +LIST(LENGTH Intrepid2_TEST_ETI_VALUETYPE_NAME ETI_VALUETYPE_COUNT) +MATH(EXPR ETI_VALUETYPE_COUNT "${ETI_VALUETYPE_COUNT}-1") +# device SET(Intrepid2_TEST_ETI_DEVICE_NAME "") SET(Intrepid2_TEST_ETI_DEVICE "") IF(Kokkos_ENABLE_SERIAL) diff --git a/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_QUAD_C2_FEM/eti/test_02_ETI.in b/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_QUAD_C2_FEM/eti/test_02_ETI.in new file mode 100644 index 000000000000..3dac2095b0b6 --- /dev/null +++ b/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_QUAD_C2_FEM/eti/test_02_ETI.in @@ -0,0 +1,52 @@ +// @HEADER +// ***************************************************************************** +// Intrepid2 Package +// +// Copyright 2007 NTESS and the Intrepid2 contributors. +// SPDX-License-Identifier: BSD-3-Clause +// ***************************************************************************** +// @HEADER + +/** \file test_01.cpp + \brief Unit test of serial interface Intrepid2::Basis_HGRAD_QUAD_C2_FEM. + \author Kyungjoo Kim +*/ + +#include "Kokkos_Core.hpp" + +#define ETI_SACADO @ETI_SACADO@ +#if (ETI_SACADO != 0) /// SACADO +#include "Kokkos_ViewFactory.hpp" +#include "Sacado.hpp" +#endif + +#if (ETI_SACADO == 0) /// double double +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__) +#elif (ETI_SACADO == 11 /* SFAD SFAD */ || ETI_SACADO == 33 /* DFAD DFAD */) +constexpr int num_deriv = 3; +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#elif (ETI_SACADO == 23) +constexpr int num_deriv = 3; +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#elif (ETI_SACADO == 20) +constexpr int num_deriv = 2; +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__) +#endif + +#include "test_02.hpp" + +int main(int argc, char *argv[]) { + + const bool verbose = (argc-1) > 0; + Kokkos::initialize(); + + Intrepid2::Test::HGRAD_QUAD_C2_FEM_Test02<@ETI_VALUETYPE@,@ETI_DEVICE@>(verbose); + + Kokkos::finalize(); + return 0; +} + diff --git a/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_QUAD_C2_FEM/test_02.hpp b/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_QUAD_C2_FEM/test_02.hpp new file mode 100644 index 000000000000..cf2ba0043d7b --- /dev/null +++ b/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_QUAD_C2_FEM/test_02.hpp @@ -0,0 +1,228 @@ +// @HEADER +// ***************************************************************************** +// Intrepid2 Package +// +// Copyright 2007 NTESS and the Intrepid2 contributors. +// SPDX-License-Identifier: BSD-3-Clause +// ***************************************************************************** +// @HEADER + +/** \file test_02.hpp + \brief Unit tests for the Intrepid2::HGRAD_QUAD_C2_FEM class. + \author Created by Kyungjoo Kim, Mauro Perego + */ + + +#include "Intrepid2_config.h" +#include "Kokkos_Random.hpp" +#ifdef HAVE_INTREPID2_DEBUG +#define INTREPID2_TEST_FOR_DEBUG_ABORT_OVERRIDE_TO_CONTINUE +#endif + +#include "Intrepid2_Types.hpp" +#include "Intrepid2_Utils.hpp" + +#include "Intrepid2_HGRAD_QUAD_C2_FEM.hpp" +#include "packages/intrepid2/unit-test/Discretization/Basis/Setup.hpp" + +namespace Intrepid2 { + + // This test evaluates the basis functions at a set of points on a batch of cells using the team-level getValues, + // and compares the results with those obtained using the classic getValues function. + namespace Test { + + template + int HGRAD_QUAD_C2_FEM_Test02(const bool verbose) { + + //! Setup test output stream. + Teuchos::RCP outStream = setup_output_stream( + verbose, "HGRAD_QUAD_C2_FEM, Test 2", {} + ); + + *outStream + << "\n" + << "===============================================================================\n" + << "| Testing Team-level Implemntation of getValues |\n" + << "===============================================================================\n"; + + using DeviceSpaceType = typename DeviceType::execution_space; + Kokkos::print_configuration(std::cout, false); + + int errorFlag = 0; + + try { + using BasisType = Basis_HGRAD_QUAD_C2_FEM; + auto basisPtr = Teuchos::rcp(new BasisType()); + + const int ncells = 5, npts = 10, ndim = 2; + Kokkos::DynRankView ConstructWithLabelOutView(outputValuesA, ncells, basisPtr->getCardinality(), npts); + Kokkos::DynRankView ConstructWithLabelOutView(outputValuesB, basisPtr->getCardinality(), npts); + + Kokkos::DynRankView ConstructWithLabelOutView(outputGradsA, ncells, basisPtr->getCardinality(), npts, ndim); + Kokkos::DynRankView ConstructWithLabelOutView(outputGradsB, basisPtr->getCardinality(), npts, ndim); + + Kokkos::DynRankView ConstructWithLabelOutView(outputCurlsA, ncells, basisPtr->getCardinality(), npts, ndim); + Kokkos::DynRankView ConstructWithLabelOutView(outputCurlsB, basisPtr->getCardinality(), npts, ndim); + + Kokkos::DynRankView ConstructWithLabelPointView(point, 1); + + using ScalarType = typename ScalarTraits::scalar_type; + + Kokkos::View inputPointsViewToUseRandom("inputPoints", npts*ndim*get_dimension_scalar(point)); + auto vcprop = Kokkos::common_view_alloc_prop(point); + Kokkos::DynRankView inputPoints (Kokkos::view_wrap(inputPointsViewToUseRandom.data(), vcprop), npts, ndim); + + // random values between (0,1) + Kokkos::Random_XorShift64_Pool random(13718); + Kokkos::fill_random(inputPointsViewToUseRandom, random, 1.0); + + + *outStream << "Computing values and gradients for " << ncells << " cells and " << npts << " points using team-level getValues function" <(*basisPtr); + auto basisRawPtr_device = basisPtr_device.get(); + + int scratch_space_level =1; + const int vectorSize = getVectorSizeForHierarchicalParallelism(); + Kokkos::TeamPolicy teamPolicy(ncells, Kokkos::AUTO,vectorSize); + + { //compute values + auto functor = KOKKOS_LAMBDA (typename Kokkos::TeamPolicy::member_type team_member) { + auto valsACell = Kokkos::subview(outputValuesA, team_member.league_rank(), Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL()); + basisRawPtr_device->getValues(valsACell, inputPoints, OPERATOR_VALUE, team_member, team_member.team_scratch(scratch_space_level)); + }; + + //Get the required size of the scratch space per team and per thread. + int perThreadSpaceSize(0), perTeamSpaceSize(0); + basisPtr->getScratchSpaceSize(perTeamSpaceSize,perThreadSpaceSize,inputPoints, OPERATOR_VALUE); + teamPolicy.set_scratch_size(scratch_space_level, Kokkos::PerTeam(perTeamSpaceSize), Kokkos::PerThread(perThreadSpaceSize)); + + Kokkos::parallel_for (teamPolicy,functor); + } + + { //compute gradients + auto functor = KOKKOS_LAMBDA (typename Kokkos::TeamPolicy::member_type team_member) { + auto gradsACell = Kokkos::subview(outputGradsA, team_member.league_rank(), Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL()); + basisRawPtr_device->getValues(gradsACell, inputPoints, OPERATOR_GRAD, team_member, team_member.team_scratch(scratch_space_level)); + }; + + //Get the required size of the scratch space per team and per thread. + int perThreadSpaceSize(0), perTeamSpaceSize(0); + basisPtr->getScratchSpaceSize(perTeamSpaceSize,perThreadSpaceSize,inputPoints, OPERATOR_GRAD); + teamPolicy.set_scratch_size(scratch_space_level, Kokkos::PerTeam(perTeamSpaceSize), Kokkos::PerThread(perThreadSpaceSize)); + + Kokkos::parallel_for (teamPolicy,functor); + } + + { //compute curls + auto functor = KOKKOS_LAMBDA (typename Kokkos::TeamPolicy::member_type team_member) { + auto curlsACell = Kokkos::subview(outputCurlsA, team_member.league_rank(), Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL()); + basisRawPtr_device->getValues(curlsACell, inputPoints, OPERATOR_CURL, team_member, team_member.team_scratch(scratch_space_level)); + }; + + //Get the required size of the scratch space per team and per thread. + int perThreadSpaceSize(0), perTeamSpaceSize(0); + basisPtr->getScratchSpaceSize(perTeamSpaceSize,perThreadSpaceSize,inputPoints, OPERATOR_CURL); + teamPolicy.set_scratch_size(scratch_space_level, Kokkos::PerTeam(perTeamSpaceSize), Kokkos::PerThread(perThreadSpaceSize)); + + Kokkos::parallel_for (teamPolicy,functor); + } + } + + *outStream << "Computing values and gradients for " << npts << " points using high-level getValues function" <getValues(outputValuesB, inputPoints, OPERATOR_VALUE); + basisPtr->getValues(outputGradsB, inputPoints, OPERATOR_GRAD); + basisPtr->getValues(outputCurlsB, inputPoints, OPERATOR_CURL); + + *outStream << "Comparing values and gradients on host" <(); + for (size_t ic=0;ic tol) { + ++errorFlag; + std::cout << ", ic: " << ic << ", i: " << i << ", j: " << j + << ", val A: " << outputValuesA_Host(ic,i,j) + << ", val B: " << outputValuesB_Host(i,j) + << ", |diff|: " << diff + << ", tol: " << tol + << std::endl; + } + } + } + + { + // compare grads + const auto outputGradsA_Host = Kokkos::create_mirror_view(outputGradsA); Kokkos::deep_copy(outputGradsA_Host, outputGradsA); + const auto outputGradsB_Host = Kokkos::create_mirror_view(outputGradsB); Kokkos::deep_copy(outputGradsB_Host, outputGradsB); + + OutValueType diff = 0; + auto tol = epsilon(); + for (size_t ic=0;ic tol) { + ++errorFlag; + std::cout << ", ic: " << ic << ", i: " << i << ", j: " << j + << ", grads A: [" << outputGradsA_Host(ic,i,j,0) << ", " << outputGradsA_Host(ic,i,j,1) << "]" + << ", grads B: [" << outputGradsB_Host(i,j,0) << ", " << outputGradsB_Host(i,j,1) << "]" + << ", |diff|: " << diff + << ", tol: " << tol + << std::endl; + } + } + } + + { + // compare curls + const auto outputCurlsA_Host = Kokkos::create_mirror_view(outputCurlsA); Kokkos::deep_copy(outputCurlsA_Host, outputCurlsA); + const auto outputCurlsB_Host = Kokkos::create_mirror_view(outputCurlsB); Kokkos::deep_copy(outputCurlsB_Host, outputCurlsB); + + OutValueType diff = 0; + auto tol = epsilon(); + for (size_t ic=0;ic tol) { + ++errorFlag; + std::cout << ", ic: " << ic << ", i: " << i << ", j: " << j + << ", curls A: [" << outputCurlsA_Host(ic,i,j,0) << ", " << outputCurlsA_Host(ic,i,j,1) <<"]" + << ", curls B: [" << outputCurlsB_Host(i,j,0) << ", " << outputCurlsB_Host(i,j,1) << "]" + << ", |diff|: " << diff + << ", tol: " << tol + << std::endl; + } + } + } + } catch (std::exception &err) { + std::cout << "UNEXPECTED ERROR !!! ----------------------------------------------------------\n"; + std::cout << err.what() << '\n'; + std::cout << "-------------------------------------------------------------------------------" << "\n\n"; + errorFlag = -1000; + }; + + if (errorFlag != 0) + std::cout << "End Result: TEST FAILED\n"; + else + std::cout << "End Result: TEST PASSED\n"; + + return errorFlag; + } + } +} diff --git a/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_QUAD_Cn_FEM/CMakeLists.txt b/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_QUAD_Cn_FEM/CMakeLists.txt index 9a6190ea4405..50f38bf22177 100644 --- a/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_QUAD_Cn_FEM/CMakeLists.txt +++ b/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_QUAD_Cn_FEM/CMakeLists.txt @@ -7,6 +7,7 @@ SET(Intrepid2_TEST_ETI_FILE "test_01") # value types SET(Intrepid2_TEST_ETI_VALUETYPE_NAME "") SET(Intrepid2_TEST_ETI_VALUETYPE "") +SET(Intrepid2_TEST_ETI_SACADO "") LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE_NAME "DOUBLE_DOUBLE") LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE "double,double") @@ -94,11 +95,18 @@ SET(Intrepid2_TEST_ETI_FILE "test_02") # value types SET(Intrepid2_TEST_ETI_VALUETYPE_NAME "") SET(Intrepid2_TEST_ETI_VALUETYPE "") +SET(Intrepid2_TEST_ETI_SACADO "") LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE_NAME "DOUBLE_DOUBLE") LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE "double,double") LIST(APPEND Intrepid2_TEST_ETI_SACADO "0") +IF (HAVE_INTREPID2_SACADO) + LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE_NAME "DFAD_DFAD") + LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE "Sacado::Fad::DFad,Sacado::Fad::DFad ") + LIST(APPEND Intrepid2_TEST_ETI_SACADO "33") +ENDIF() + LIST(LENGTH Intrepid2_TEST_ETI_VALUETYPE_NAME ETI_VALUETYPE_COUNT) MATH(EXPR ETI_VALUETYPE_COUNT "${ETI_VALUETYPE_COUNT}-1") diff --git a/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_QUAD_Cn_FEM/eti/test_01_ETI.in b/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_QUAD_Cn_FEM/eti/test_01_ETI.in index 46bd4b13ccfb..0cae06ee9e31 100644 --- a/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_QUAD_Cn_FEM/eti/test_01_ETI.in +++ b/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_QUAD_Cn_FEM/eti/test_01_ETI.in @@ -28,9 +28,8 @@ constexpr int num_deriv = 10; #define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) #define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) #elif (ETI_SACADO == 23) -constexpr int num_deriv = 9; -constexpr int max_deriv = 10; -#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__, max_deriv+1) +constexpr int num_deriv = 3; +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) #define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) #elif (ETI_SACADO == 20) constexpr int num_deriv = 2; diff --git a/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_QUAD_Cn_FEM/eti/test_02_ETI.in b/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_QUAD_Cn_FEM/eti/test_02_ETI.in index ccb60ba60798..07adf2c5e888 100644 --- a/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_QUAD_Cn_FEM/eti/test_02_ETI.in +++ b/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_QUAD_Cn_FEM/eti/test_02_ETI.in @@ -8,21 +8,44 @@ // @HEADER /** \file test_01.cpp - \brief Unit test of serial interface Intrepid2::Basis_HGRAD_QUAD_Cn_FEM. + \brief Unit test of Intrepid2::Basis_HGRAD_QUAD_Cn_FEM team-level getValues. \author Kyungjoo Kim */ #include "Kokkos_Core.hpp" +#define ETI_SACADO @ETI_SACADO@ +#if (ETI_SACADO != 0) /// SACADO +#include "Kokkos_ViewFactory.hpp" +#include "Sacado.hpp" +#endif + +#if (ETI_SACADO == 0) /// double double +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__) +#elif (ETI_SACADO == 11 /* SFAD SFAD */ || ETI_SACADO == 33 /* DFAD DFAD */) +constexpr int num_deriv = 3; +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#elif (ETI_SACADO == 23) +constexpr int num_deriv = 3; +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#elif (ETI_SACADO == 20) +constexpr int num_deriv = 2; +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__) +#endif + #include "test_02.hpp" int main(int argc, char *argv[]) { + const bool verbose = (argc-1) > 0; Kokkos::initialize(); - { - const bool verbose = (argc-1) > 0; - Intrepid2::Test::HGRAD_QUAD_Cn_FEM_Test02<@ETI_VALUETYPE@,@ETI_DEVICE@>(verbose); - } + + Intrepid2::Test::HGRAD_QUAD_Cn_FEM_Test02<@ETI_VALUETYPE@,@ETI_DEVICE@>(verbose); + Kokkos::finalize(); return 0; } diff --git a/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_QUAD_Cn_FEM/test_02.hpp b/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_QUAD_Cn_FEM/test_02.hpp index 36a858dec901..2e2bdf715470 100644 --- a/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_QUAD_Cn_FEM/test_02.hpp +++ b/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_QUAD_Cn_FEM/test_02.hpp @@ -7,9 +7,9 @@ // ***************************************************************************** // @HEADER -/** \file test_01.hpp +/** \file test_02.hpp \brief Unit tests for the Intrepid2::HGRAD_QUAD_Cn_FEM class. - \author Created by P. Bochev, D. Ridzal, K. Peterson, Kyungjoo Kim + \author Created by Kyungjoo Kim, Mauro Perego */ @@ -23,98 +23,196 @@ #include "Intrepid2_Utils.hpp" #include "Intrepid2_HGRAD_QUAD_Cn_FEM.hpp" +#include "packages/intrepid2/unit-test/Discretization/Basis/Setup.hpp" namespace Intrepid2 { namespace Test { - // This code provides an example to use serial interface of high order elements + // This test evaluates the basis functions at a set of points on a batch of cells using the team-level getValues, + // and compares the results with those obtained using the classic getValues function. template int HGRAD_QUAD_Cn_FEM_Test02(const bool verbose) { + + //! Setup test output stream. + Teuchos::RCP outStream = setup_output_stream( + verbose, "HGRAD_QUAD_Cn_FEM, Test 2", {} + ); + + *outStream + << "\n" + << "===============================================================================\n" + << "| Testing Team-level Implemntation of getValues |\n" + << "===============================================================================\n"; + + using DeviceSpaceType = typename DeviceType::execution_space; Kokkos::print_configuration(std::cout, false); int errorFlag = 0; - + constexpr int maxOrder = 9; try { - for (int order=1;order basis(order); + for (int order=1;order<=maxOrder;++order) { + using BasisType = Basis_HGRAD_QUAD_Cn_FEM; + auto basisPtr = Teuchos::rcp(new BasisType(order)); - // problem setup - // let's say we want to evaluate 1000 points in parallel. output values are stored in outputValuesA and B. - // A is compuated via serial interface and B is computed with top-level interface. - const int npts = 1000, ndim = 2; - Kokkos::DynRankView outputValuesA("outputValuesA", basis.getCardinality(), npts); - Kokkos::DynRankView outputValuesB("outputValuesB", basis.getCardinality(), npts); + const int ncells = 5, npts = 10, ndim = 2; + Kokkos::DynRankView ConstructWithLabelOutView(outputValuesA, ncells, basisPtr->getCardinality(), npts); + Kokkos::DynRankView ConstructWithLabelOutView(outputValuesB, basisPtr->getCardinality(), npts); + + Kokkos::DynRankView ConstructWithLabelOutView(outputGradsA, ncells, basisPtr->getCardinality(), npts, ndim); + Kokkos::DynRankView ConstructWithLabelOutView(outputGradsB, basisPtr->getCardinality(), npts, ndim); + + Kokkos::DynRankView ConstructWithLabelOutView(outputCurlsA, ncells, basisPtr->getCardinality(), npts, ndim); + Kokkos::DynRankView ConstructWithLabelOutView(outputCurlsB, basisPtr->getCardinality(), npts, ndim); + + Kokkos::DynRankView ConstructWithLabelPointView(point, 1); - Kokkos::View inputPointsViewToUseRandom("inputPoints", npts, ndim); - Kokkos::DynRankView inputPoints (inputPointsViewToUseRandom.data(), npts, ndim); + using ScalarType = typename ScalarTraits::scalar_type; - // random values between (-1,1) x (-1,1) + Kokkos::View inputPointsViewToUseRandom("inputPoints", npts*ndim*get_dimension_scalar(point)); + auto vcprop = Kokkos::common_view_alloc_prop(point); + Kokkos::DynRankView inputPoints (Kokkos::view_wrap(inputPointsViewToUseRandom.data(), vcprop), npts, ndim); + + // random values between (0,1) Kokkos::Random_XorShift64_Pool random(13718); Kokkos::fill_random(inputPointsViewToUseRandom, random, 1.0); - // compute setup - // we need vinv and workspace - const auto vinv = basis.getVandermondeInverse(); - - // worksize - // workspace per thread is required for serial interface. - // parallel_for with range policy would be good to use stack workspace - // as team policy only can create shared memory - // this part would be tricky as the max size should be determined at compile time - // let's think about this and find out the best practice. for now I use the following. - constexpr int worksize = (Parameters::MaxOrder+1)*3; - - // if you use team policy, worksize can be gathered from the basis object and use - // kokkos shmem_size APIs to create workspace per team or per thread. - //const auto worksize_for_teampolicy = basis.getWorksizePerPoint(OPERATOR_VALUE); - - // extract point range to be evaluated in each thread - typedef Kokkos::pair range_type; - - // parallel execution with serial interface - Kokkos::RangePolicy policy(0, npts); - Kokkos::parallel_for(policy, KOKKOS_LAMBDA(int i) { - // we evaluate a single point - const range_type pointRange = range_type(i,i+1); + + *outStream << "Order: " << order << ": Computing values and gradients for " << ncells << " cells and " << npts << " points using team-level getValues function" <(*basisPtr); + auto basisRawPtr_device = basisPtr_device.get(); + + int scratch_space_level =1; + const int vectorSize = getVectorSizeForHierarchicalParallelism(); + Kokkos::TeamPolicy teamPolicy(ncells, Kokkos::AUTO,vectorSize); + + { //compute values + auto functor = KOKKOS_LAMBDA (typename Kokkos::TeamPolicy::member_type team_member) { + auto valsACell = Kokkos::subview(outputValuesA, team_member.league_rank(), Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL()); + basisRawPtr_device->getValues(valsACell, inputPoints, OPERATOR_VALUE, team_member, team_member.team_scratch(scratch_space_level)); + }; - // out (# dofs, # pts), input (# pts, # dims) - auto output = Kokkos::subview(outputValuesA, Kokkos::ALL(), pointRange); - auto input = Kokkos::subview(inputPoints, pointRange, Kokkos::ALL()); + //Get the required size of the scratch space per team and per thread. + int perThreadSpaceSize(0), perTeamSpaceSize(0); + basisPtr->getScratchSpaceSize(perTeamSpaceSize,perThreadSpaceSize,inputPoints, OPERATOR_VALUE); + teamPolicy.set_scratch_size(scratch_space_level, Kokkos::PerTeam(perTeamSpaceSize), Kokkos::PerThread(perThreadSpaceSize)); + + Kokkos::parallel_for (teamPolicy,functor); + } + + { //compute gradients + auto functor = KOKKOS_LAMBDA (typename Kokkos::TeamPolicy::member_type team_member) { + auto gradsACell = Kokkos::subview(outputGradsA, team_member.league_rank(), Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL()); + basisRawPtr_device->getValues(gradsACell, inputPoints, OPERATOR_GRAD, team_member, team_member.team_scratch(scratch_space_level)); + }; - // wrap static workspace with a view; serial interface has a template view interface. - // either view or dynrankview with a right size is okay. - OutValueType workbuf[worksize]; - Kokkos::View work(&workbuf[0], worksize); + //Get the required size of the scratch space per team and per thread. + int perThreadSpaceSize(0), perTeamSpaceSize(0); + basisPtr->getScratchSpaceSize(perTeamSpaceSize,perThreadSpaceSize,inputPoints, OPERATOR_GRAD); + teamPolicy.set_scratch_size(scratch_space_level, Kokkos::PerTeam(perTeamSpaceSize), Kokkos::PerThread(perThreadSpaceSize)); + + Kokkos::parallel_for (teamPolicy,functor); + } + + { //compute curls + auto functor = KOKKOS_LAMBDA (typename Kokkos::TeamPolicy::member_type team_member) { + auto curlsACell = Kokkos::subview(outputCurlsA, team_member.league_rank(), Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL()); + basisRawPtr_device->getValues(curlsACell, inputPoints, OPERATOR_CURL, team_member, team_member.team_scratch(scratch_space_level)); + }; - // evaluate basis using serial interface - Impl::Basis_HGRAD_QUAD_Cn_FEM - ::Serial::getValues(output, input, work, vinv); - }); - - // evaluation using high level interface - basis.getValues(outputValuesB, inputPoints, OPERATOR_VALUE); - - // compare - const auto outputValuesA_Host = Kokkos::create_mirror_view(outputValuesA); Kokkos::deep_copy(outputValuesA_Host, outputValuesA); - const auto outputValuesB_Host = Kokkos::create_mirror_view(outputValuesB); Kokkos::deep_copy(outputValuesB_Host, outputValuesB); - - double sum = 0, diff = 0; - for (size_t i=0;igetValues(outputValuesB, inputPoints, OPERATOR_VALUE); + basisPtr->getValues(outputGradsB, inputPoints, OPERATOR_GRAD); + basisPtr->getValues(outputCurlsB, inputPoints, OPERATOR_CURL); + + *outStream << "Order: " << order << ": Comparing values and gradients on host" <(); + for (size_t ic=0;ic tol) { + ++errorFlag; + std::cout << " order: " << order + << ", ic: " << ic << ", i: " << i << ", j: " << j + << ", val A: " << outputValuesA_Host(ic,i,j) + << ", val B: " << outputValuesB_Host(i,j) + << ", |diff|: " << diff + << ", tol: " << tol + << std::endl; + } + } + } + + { + // compare grads + const auto outputGradsA_Host = Kokkos::create_mirror_view(outputGradsA); Kokkos::deep_copy(outputGradsA_Host, outputGradsA); + const auto outputGradsB_Host = Kokkos::create_mirror_view(outputGradsB); Kokkos::deep_copy(outputGradsB_Host, outputGradsB); + + OutValueType diff = 0; + auto tol = epsilon(); + for (size_t ic=0;ic tol) { + ++errorFlag; + std::cout << " order: " << order + << ", ic: " << ic << ", i: " << i << ", j: " << j + << ", grads A: [" << outputGradsA_Host(ic,i,j,0) << ", " << outputGradsA_Host(ic,i,j,1) << "]" + << ", grads B: [" << outputGradsB_Host(i,j,0) << ", " << outputGradsB_Host(i,j,1) << "]" + << ", |diff|: " << diff + << ", tol: " << tol + << std::endl; + } + } + } + + { + // compare curls + const auto outputCurlsA_Host = Kokkos::create_mirror_view(outputCurlsA); Kokkos::deep_copy(outputCurlsA_Host, outputCurlsA); + const auto outputCurlsB_Host = Kokkos::create_mirror_view(outputCurlsB); Kokkos::deep_copy(outputCurlsB_Host, outputCurlsB); + + OutValueType diff = 0; + auto tol = epsilon(); + for (size_t ic=0;ic tol) { + ++errorFlag; + std::cout << " order: " << order + << ", ic: " << ic << ", i: " << i << ", j: " << j + << ", curls A: [" << outputCurlsA_Host(ic,i,j,0) << ", " << outputCurlsA_Host(ic,i,j,1) <<"]" + << ", curls B: [" << outputCurlsB_Host(i,j,0) << ", " << outputCurlsB_Host(i,j,1) << "]" + << ", |diff|: " << diff + << ", tol: " << tol + << std::endl; + } + } } } } catch (std::exception &err) { diff --git a/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_TET_C1_FEM/CMakeLists.txt b/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_TET_C1_FEM/CMakeLists.txt index 37135caa841f..325ab37afd81 100644 --- a/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_TET_C1_FEM/CMakeLists.txt +++ b/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_TET_C1_FEM/CMakeLists.txt @@ -1,8 +1,13 @@ TRIBITS_INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}) + +# test +SET(Intrepid2_TEST_ETI_FILE "test_01") + # value types SET(Intrepid2_TEST_ETI_VALUETYPE_NAME "") SET(Intrepid2_TEST_ETI_VALUETYPE "") +SET(Intrepid2_TEST_ETI_SACADO "") LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE_NAME "DOUBLE") LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE "double") @@ -17,9 +22,80 @@ ENDIF() LIST(LENGTH Intrepid2_TEST_ETI_VALUETYPE_NAME ETI_VALUETYPE_COUNT) MATH(EXPR ETI_VALUETYPE_COUNT "${ETI_VALUETYPE_COUNT}-1") -# Host test -SET(Intrepid2_TEST_ETI_FILE "test_01") +# device +SET(Intrepid2_TEST_ETI_DEVICE_NAME "") +SET(Intrepid2_TEST_ETI_DEVICE "") +IF(Kokkos_ENABLE_SERIAL) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "Serial") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() +IF(Kokkos_ENABLE_OPENMP) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "OpenMP") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() +IF(Kokkos_ENABLE_CUDA) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "CUDA") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() +IF(Kokkos_ENABLE_HIP) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "HIP") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() + +LIST(LENGTH Intrepid2_TEST_ETI_DEVICE_NAME ETI_DEVICE_COUNT) +MATH(EXPR ETI_DEVICE_COUNT "${ETI_DEVICE_COUNT}-1") + +FOREACH(I RANGE ${ETI_DEVICE_COUNT}) + LIST(GET Intrepid2_TEST_ETI_DEVICE_NAME ${I} ETI_DEVICE_NAME) + LIST(GET Intrepid2_TEST_ETI_DEVICE ${I} ETI_DEVICE) + #MESSAGE(STATUS "Generating TEST HGRAD_TET_C1_FEM for ${ETI_DEVICE_NAME} with ${ETI_DEVICE}") + FOREACH(J RANGE ${ETI_VALUETYPE_COUNT}) + LIST(GET Intrepid2_TEST_ETI_VALUETYPE_NAME ${J} ETI_VALUETYPE_NAME) + LIST(GET Intrepid2_TEST_ETI_VALUETYPE ${J} ETI_VALUETYPE) + LIST(GET Intrepid2_TEST_ETI_SACADO ${J} ETI_SACADO) + FOREACH(ETI_FILE IN LISTS Intrepid2_TEST_ETI_FILE) + SET(ETI_NAME "${ETI_FILE}_${ETI_DEVICE_NAME}_${ETI_VALUETYPE_NAME}") + MESSAGE(STATUS "Generating TEST: HGRAD_TET_C1_FEM ${ETI_NAME}.cpp") + CONFIGURE_FILE(eti/${ETI_FILE}_ETI.in ${ETI_NAME}.cpp) + + TRIBITS_ADD_EXECUTABLE_AND_TEST( + ${ETI_NAME} + SOURCES ${ETI_NAME}.cpp + ARGS PrintItAll + NUM_MPI_PROCS 1 + PASS_REGULAR_EXPRESSION "TEST PASSED" + ADD_DIR_TO_NAME + ) + + ENDFOREACH() + ENDFOREACH() +ENDFOREACH() + + + + +# test +SET(Intrepid2_TEST_ETI_FILE "test_02") + +# value types +SET(Intrepid2_TEST_ETI_VALUETYPE_NAME "") +SET(Intrepid2_TEST_ETI_VALUETYPE "") +SET(Intrepid2_TEST_ETI_SACADO "") + +LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE_NAME "DOUBLE_DOUBLE") +LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE "double,double") +LIST(APPEND Intrepid2_TEST_ETI_SACADO "0") + +IF (HAVE_INTREPID2_SACADO) + LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE_NAME "DFAD_DFAD") + LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE "Sacado::Fad::DFad,Sacado::Fad::DFad ") + LIST(APPEND Intrepid2_TEST_ETI_SACADO "33") +ENDIF() + +LIST(LENGTH Intrepid2_TEST_ETI_VALUETYPE_NAME ETI_VALUETYPE_COUNT) +MATH(EXPR ETI_VALUETYPE_COUNT "${ETI_VALUETYPE_COUNT}-1") +# device SET(Intrepid2_TEST_ETI_DEVICE_NAME "") SET(Intrepid2_TEST_ETI_DEVICE "") IF(Kokkos_ENABLE_SERIAL) diff --git a/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_TET_C1_FEM/eti/test_02_ETI.in b/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_TET_C1_FEM/eti/test_02_ETI.in new file mode 100644 index 000000000000..7fab72655932 --- /dev/null +++ b/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_TET_C1_FEM/eti/test_02_ETI.in @@ -0,0 +1,52 @@ +// @HEADER +// ***************************************************************************** +// Intrepid2 Package +// +// Copyright 2007 NTESS and the Intrepid2 contributors. +// SPDX-License-Identifier: BSD-3-Clause +// ***************************************************************************** +// @HEADER + +/** \file test_01.cpp + \brief Unit test of Intrepid2::Basis_HGRAD_TET_C1_FEM team-level getValues. + \author Kyungjoo Kim +*/ + +#include "Kokkos_Core.hpp" + +#define ETI_SACADO @ETI_SACADO@ +#if (ETI_SACADO != 0) /// SACADO +#include "Kokkos_ViewFactory.hpp" +#include "Sacado.hpp" +#endif + +#if (ETI_SACADO == 0) /// double double +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__) +#elif (ETI_SACADO == 11 /* SFAD SFAD */ || ETI_SACADO == 33 /* DFAD DFAD */) +constexpr int num_deriv = 3; +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#elif (ETI_SACADO == 23) +constexpr int num_deriv = 3; +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#elif (ETI_SACADO == 20) +constexpr int num_deriv = 2; +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__) +#endif + +#include "test_02.hpp" + +int main(int argc, char *argv[]) { + + const bool verbose = (argc-1) > 0; + Kokkos::initialize(); + + Intrepid2::Test::HGRAD_TET_C1_FEM_Test02<@ETI_VALUETYPE@,@ETI_DEVICE@>(verbose); + + Kokkos::finalize(); + return 0; +} + diff --git a/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_TET_C1_FEM/test_02.hpp b/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_TET_C1_FEM/test_02.hpp new file mode 100644 index 000000000000..48d5b3eb9e2f --- /dev/null +++ b/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_TET_C1_FEM/test_02.hpp @@ -0,0 +1,184 @@ +// @HEADER +// ***************************************************************************** +// Intrepid2 Package +// +// Copyright 2007 NTESS and the Intrepid2 contributors. +// SPDX-License-Identifier: BSD-3-Clause +// ***************************************************************************** +// @HEADER + +/** \file test_02.hpp + \brief Unit tests for the Intrepid2::HGRAD_TET_C1_FEM class. + \author Created by Kyungjoo Kim, Mauro Perego + */ + + +#include "Intrepid2_config.h" +#include "Kokkos_Random.hpp" +#ifdef HAVE_INTREPID2_DEBUG +#define INTREPID2_TEST_FOR_DEBUG_ABORT_OVERRIDE_TO_CONTINUE +#endif + +#include "Intrepid2_Types.hpp" +#include "Intrepid2_Utils.hpp" + +#include "Intrepid2_HGRAD_TET_C1_FEM.hpp" +#include "packages/intrepid2/unit-test/Discretization/Basis/Setup.hpp" + +namespace Intrepid2 { + + namespace Test { + + // This test evaluates the basis functions at a set of points on a batch of cells using the team-level getValues, + // and compares the results with those obtained using the classic getValues function. + template + int HGRAD_TET_C1_FEM_Test02(const bool verbose) { + + //! Setup test output stream. + Teuchos::RCP outStream = setup_output_stream( + verbose, "HGRAD_TET_C1_FEM, Test 2", {} + ); + + *outStream + << "\n" + << "===============================================================================\n" + << "| Testing Team-level Implemntation of getValues |\n" + << "===============================================================================\n"; + + using DeviceSpaceType = typename DeviceType::execution_space; + Kokkos::print_configuration(std::cout, false); + + int errorFlag = 0; + + try { + using BasisType = Basis_HGRAD_TET_C1_FEM; + auto basisPtr = Teuchos::rcp(new BasisType()); + + const int ncells = 5, npts = 10, ndim = 3; + Kokkos::DynRankView ConstructWithLabelOutView(outputValuesA, ncells, basisPtr->getCardinality(), npts); + Kokkos::DynRankView ConstructWithLabelOutView(outputValuesB, basisPtr->getCardinality(), npts); + + Kokkos::DynRankView ConstructWithLabelOutView(outputGradsA, ncells, basisPtr->getCardinality(), npts, ndim); + Kokkos::DynRankView ConstructWithLabelOutView(outputGradsB, basisPtr->getCardinality(), npts, ndim); + Kokkos::DynRankView ConstructWithLabelPointView(point, 1); + + using ScalarType = typename ScalarTraits::scalar_type; + + Kokkos::View inputPointsViewToUseRandom("inputPoints", npts*ndim*get_dimension_scalar(point)); + auto vcprop = Kokkos::common_view_alloc_prop(point); + Kokkos::DynRankView inputPoints (Kokkos::view_wrap(inputPointsViewToUseRandom.data(), vcprop), npts, ndim); + + // random values between (0,1) + Kokkos::Random_XorShift64_Pool random(13718); + Kokkos::fill_random(inputPointsViewToUseRandom, random, 1.0); + + + *outStream << "Computing values and gradients for " << ncells << " cells and " << npts << " points using team-level getValues function" <(*basisPtr); + auto basisRawPtr_device = basisPtr_device.get(); + + int scratch_space_level =1; + const int vectorSize = getVectorSizeForHierarchicalParallelism(); + Kokkos::TeamPolicy teamPolicy(ncells, Kokkos::AUTO,vectorSize); + + { //compute values + auto functor = KOKKOS_LAMBDA (typename Kokkos::TeamPolicy::member_type team_member) { + auto valsACell = Kokkos::subview(outputValuesA, team_member.league_rank(), Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL()); + basisRawPtr_device->getValues(valsACell, inputPoints, OPERATOR_VALUE, team_member, team_member.team_scratch(scratch_space_level)); + }; + + //Get the required size of the scratch space per team and per thread. + int perThreadSpaceSize(0), perTeamSpaceSize(0); + basisPtr->getScratchSpaceSize(perTeamSpaceSize,perThreadSpaceSize,inputPoints, OPERATOR_VALUE); + teamPolicy.set_scratch_size(scratch_space_level, Kokkos::PerTeam(perTeamSpaceSize), Kokkos::PerThread(perThreadSpaceSize)); + + Kokkos::parallel_for (teamPolicy,functor); + } + + { //compute gradients + auto functor = KOKKOS_LAMBDA (typename Kokkos::TeamPolicy::member_type team_member) { + auto gradsACell = Kokkos::subview(outputGradsA, team_member.league_rank(), Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL()); + basisRawPtr_device->getValues(gradsACell, inputPoints, OPERATOR_GRAD, team_member, team_member.team_scratch(scratch_space_level)); + }; + + //Get the required size of the scratch space per team and per thread. + int perThreadSpaceSize(0), perTeamSpaceSize(0); + basisPtr->getScratchSpaceSize(perTeamSpaceSize,perThreadSpaceSize,inputPoints, OPERATOR_GRAD); + teamPolicy.set_scratch_size(scratch_space_level, Kokkos::PerTeam(perTeamSpaceSize), Kokkos::PerThread(perThreadSpaceSize)); + + Kokkos::parallel_for (teamPolicy,functor); + } + } + + *outStream << "Computing values and gradients for " << npts << " points using high-level getValues function" <getValues(outputValuesB, inputPoints, OPERATOR_VALUE); + basisPtr->getValues(outputGradsB, inputPoints, OPERATOR_GRAD); + + *outStream << "Comparing values and gradients on host" <(); + for (size_t ic=0;ic tol) { + ++errorFlag; + std::cout << ", ic: " << ic << ", i: " << i << ", j: " << j + << ", val A: " << outputValuesA_Host(ic,i,j) + << ", val B: " << outputValuesB_Host(i,j) + << ", |diff|: " << diff + << ", tol: " << tol + << std::endl; + } + } + } + + { + // compare grads + const auto outputGradsA_Host = Kokkos::create_mirror_view(outputGradsA); Kokkos::deep_copy(outputGradsA_Host, outputGradsA); + const auto outputGradsB_Host = Kokkos::create_mirror_view(outputGradsB); Kokkos::deep_copy(outputGradsB_Host, outputGradsB); + + OutValueType diff = 0; + auto tol = epsilon(); + for (size_t ic=0;ic tol) { + ++errorFlag; + std::cout << ", ic: " << ic << ", i: " << i << ", j: " << j + << ", grads A: [" << outputGradsA_Host(ic,i,j,0) << ", " << outputGradsA_Host(ic,i,j,1) << ", " << outputGradsA_Host(ic,i,j,2) <<"]" + << ", grads B: [" << outputGradsB_Host(i,j,0) << ", " << outputGradsB_Host(i,j,1) << ", " << outputGradsB_Host(i,j,2) <<"]" + << ", |diff|: " << diff + << ", tol: " << tol + << std::endl; + } + } + } + } catch (std::exception &err) { + std::cout << "UNEXPECTED ERROR !!! ----------------------------------------------------------\n"; + std::cout << err.what() << '\n'; + std::cout << "-------------------------------------------------------------------------------" << "\n\n"; + errorFlag = -1000; + }; + + if (errorFlag != 0) + std::cout << "End Result: TEST FAILED\n"; + else + std::cout << "End Result: TEST PASSED\n"; + + return errorFlag; + } + } +} diff --git a/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_TET_C2_FEM/CMakeLists.txt b/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_TET_C2_FEM/CMakeLists.txt index 2d0041218982..cac75a8505b4 100644 --- a/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_TET_C2_FEM/CMakeLists.txt +++ b/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_TET_C2_FEM/CMakeLists.txt @@ -1,8 +1,13 @@ TRIBITS_INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}) + +# test +SET(Intrepid2_TEST_ETI_FILE "test_01") + # value types SET(Intrepid2_TEST_ETI_VALUETYPE_NAME "") SET(Intrepid2_TEST_ETI_VALUETYPE "") +SET(Intrepid2_TEST_ETI_SACADO "") LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE_NAME "DOUBLE") LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE "double") @@ -17,9 +22,80 @@ ENDIF() LIST(LENGTH Intrepid2_TEST_ETI_VALUETYPE_NAME ETI_VALUETYPE_COUNT) MATH(EXPR ETI_VALUETYPE_COUNT "${ETI_VALUETYPE_COUNT}-1") -# Host test -SET(Intrepid2_TEST_ETI_FILE "test_01") +# device +SET(Intrepid2_TEST_ETI_DEVICE_NAME "") +SET(Intrepid2_TEST_ETI_DEVICE "") +IF(Kokkos_ENABLE_SERIAL) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "Serial") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() +IF(Kokkos_ENABLE_OPENMP) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "OpenMP") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() +IF(Kokkos_ENABLE_CUDA) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "CUDA") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() +IF(Kokkos_ENABLE_HIP) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "HIP") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() + +LIST(LENGTH Intrepid2_TEST_ETI_DEVICE_NAME ETI_DEVICE_COUNT) +MATH(EXPR ETI_DEVICE_COUNT "${ETI_DEVICE_COUNT}-1") + +FOREACH(I RANGE ${ETI_DEVICE_COUNT}) + LIST(GET Intrepid2_TEST_ETI_DEVICE_NAME ${I} ETI_DEVICE_NAME) + LIST(GET Intrepid2_TEST_ETI_DEVICE ${I} ETI_DEVICE) + #MESSAGE(STATUS "Generating TEST HGRAD_TET_C2_FEM for ${ETI_DEVICE_NAME} with ${ETI_DEVICE}") + FOREACH(J RANGE ${ETI_VALUETYPE_COUNT}) + LIST(GET Intrepid2_TEST_ETI_VALUETYPE_NAME ${J} ETI_VALUETYPE_NAME) + LIST(GET Intrepid2_TEST_ETI_VALUETYPE ${J} ETI_VALUETYPE) + LIST(GET Intrepid2_TEST_ETI_SACADO ${J} ETI_SACADO) + FOREACH(ETI_FILE IN LISTS Intrepid2_TEST_ETI_FILE) + SET(ETI_NAME "${ETI_FILE}_${ETI_DEVICE_NAME}_${ETI_VALUETYPE_NAME}") + MESSAGE(STATUS "Generating TEST: HGRAD_TET_C2_FEM ${ETI_NAME}.cpp") + CONFIGURE_FILE(eti/${ETI_FILE}_ETI.in ${ETI_NAME}.cpp) + + TRIBITS_ADD_EXECUTABLE_AND_TEST( + ${ETI_NAME} + SOURCES ${ETI_NAME}.cpp + ARGS PrintItAll + NUM_MPI_PROCS 1 + PASS_REGULAR_EXPRESSION "TEST PASSED" + ADD_DIR_TO_NAME + ) + + ENDFOREACH() + ENDFOREACH() +ENDFOREACH() + + + + +# test +SET(Intrepid2_TEST_ETI_FILE "test_02") + +# value types +SET(Intrepid2_TEST_ETI_VALUETYPE_NAME "") +SET(Intrepid2_TEST_ETI_VALUETYPE "") +SET(Intrepid2_TEST_ETI_SACADO "") + +LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE_NAME "DOUBLE_DOUBLE") +LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE "double,double") +LIST(APPEND Intrepid2_TEST_ETI_SACADO "0") + +IF (HAVE_INTREPID2_SACADO) + LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE_NAME "DFAD_DFAD") + LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE "Sacado::Fad::DFad,Sacado::Fad::DFad ") + LIST(APPEND Intrepid2_TEST_ETI_SACADO "33") +ENDIF() + +LIST(LENGTH Intrepid2_TEST_ETI_VALUETYPE_NAME ETI_VALUETYPE_COUNT) +MATH(EXPR ETI_VALUETYPE_COUNT "${ETI_VALUETYPE_COUNT}-1") +# device SET(Intrepid2_TEST_ETI_DEVICE_NAME "") SET(Intrepid2_TEST_ETI_DEVICE "") IF(Kokkos_ENABLE_SERIAL) diff --git a/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_TET_C2_FEM/eti/test_02_ETI.in b/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_TET_C2_FEM/eti/test_02_ETI.in new file mode 100644 index 000000000000..b01c59418753 --- /dev/null +++ b/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_TET_C2_FEM/eti/test_02_ETI.in @@ -0,0 +1,52 @@ +// @HEADER +// ***************************************************************************** +// Intrepid2 Package +// +// Copyright 2007 NTESS and the Intrepid2 contributors. +// SPDX-License-Identifier: BSD-3-Clause +// ***************************************************************************** +// @HEADER + +/** \file test_01.cpp + \brief Unit test of Intrepid2::Basis_HGRAD_TET_C2_FEM team-level getValues. + \author Kyungjoo Kim +*/ + +#include "Kokkos_Core.hpp" + +#define ETI_SACADO @ETI_SACADO@ +#if (ETI_SACADO != 0) /// SACADO +#include "Kokkos_ViewFactory.hpp" +#include "Sacado.hpp" +#endif + +#if (ETI_SACADO == 0) /// double double +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__) +#elif (ETI_SACADO == 11 /* SFAD SFAD */ || ETI_SACADO == 33 /* DFAD DFAD */) +constexpr int num_deriv = 3; +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#elif (ETI_SACADO == 23) +constexpr int num_deriv = 3; +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#elif (ETI_SACADO == 20) +constexpr int num_deriv = 2; +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__) +#endif + +#include "test_02.hpp" + +int main(int argc, char *argv[]) { + + const bool verbose = (argc-1) > 0; + Kokkos::initialize(); + + Intrepid2::Test::HGRAD_TET_C2_FEM_Test02<@ETI_VALUETYPE@,@ETI_DEVICE@>(verbose); + + Kokkos::finalize(); + return 0; +} + diff --git a/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_TET_C2_FEM/test_02.hpp b/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_TET_C2_FEM/test_02.hpp new file mode 100644 index 000000000000..5b788cc85328 --- /dev/null +++ b/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_TET_C2_FEM/test_02.hpp @@ -0,0 +1,184 @@ +// @HEADER +// ***************************************************************************** +// Intrepid2 Package +// +// Copyright 2007 NTESS and the Intrepid2 contributors. +// SPDX-License-Identifier: BSD-3-Clause +// ***************************************************************************** +// @HEADER + +/** \file test_02.hpp + \brief Unit tests for the Intrepid2::HGRAD_TET_C2_FEM class. + \author Created by Kyungjoo Kim, Mauro Perego + */ + + +#include "Intrepid2_config.h" +#include "Kokkos_Random.hpp" +#ifdef HAVE_INTREPID2_DEBUG +#define INTREPID2_TEST_FOR_DEBUG_ABORT_OVERRIDE_TO_CONTINUE +#endif + +#include "Intrepid2_Types.hpp" +#include "Intrepid2_Utils.hpp" + +#include "Intrepid2_HGRAD_TET_C2_FEM.hpp" +#include "packages/intrepid2/unit-test/Discretization/Basis/Setup.hpp" + +namespace Intrepid2 { + + // This test evaluates the basis functions at a set of points on a batch of cells using the team-level getValues, + // and compares the results with those obtained using the classic getValues function. + namespace Test { + + template + int HGRAD_TET_C2_FEM_Test02(const bool verbose) { + + //! Setup test output stream. + Teuchos::RCP outStream = setup_output_stream( + verbose, "HGRAD_TET_C2_FEM, Test 2", {} + ); + + *outStream + << "\n" + << "===============================================================================\n" + << "| Testing Team-level Implemntation of getValues |\n" + << "===============================================================================\n"; + + using DeviceSpaceType = typename DeviceType::execution_space; + Kokkos::print_configuration(std::cout, false); + + int errorFlag = 0; + + try { + using BasisType = Basis_HGRAD_TET_C2_FEM; + auto basisPtr = Teuchos::rcp(new BasisType()); + + const int ncells = 5, npts = 10, ndim = 3; + Kokkos::DynRankView ConstructWithLabelOutView(outputValuesA, ncells, basisPtr->getCardinality(), npts); + Kokkos::DynRankView ConstructWithLabelOutView(outputValuesB, basisPtr->getCardinality(), npts); + + Kokkos::DynRankView ConstructWithLabelOutView(outputGradsA, ncells, basisPtr->getCardinality(), npts, ndim); + Kokkos::DynRankView ConstructWithLabelOutView(outputGradsB, basisPtr->getCardinality(), npts, ndim); + Kokkos::DynRankView ConstructWithLabelPointView(point, 1); + + using ScalarType = typename ScalarTraits::scalar_type; + + Kokkos::View inputPointsViewToUseRandom("inputPoints", npts*ndim*get_dimension_scalar(point)); + auto vcprop = Kokkos::common_view_alloc_prop(point); + Kokkos::DynRankView inputPoints (Kokkos::view_wrap(inputPointsViewToUseRandom.data(), vcprop), npts, ndim); + + // random values between (0,1) + Kokkos::Random_XorShift64_Pool random(13718); + Kokkos::fill_random(inputPointsViewToUseRandom, random, 1.0); + + + *outStream << "Computing values and gradients for " << ncells << " cells and " << npts << " points using team-level getValues function" <(*basisPtr); + auto basisRawPtr_device = basisPtr_device.get(); + + int scratch_space_level =1; + const int vectorSize = getVectorSizeForHierarchicalParallelism(); + Kokkos::TeamPolicy teamPolicy(ncells, Kokkos::AUTO,vectorSize); + + { //compute values + auto functor = KOKKOS_LAMBDA (typename Kokkos::TeamPolicy::member_type team_member) { + auto valsACell = Kokkos::subview(outputValuesA, team_member.league_rank(), Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL()); + basisRawPtr_device->getValues(valsACell, inputPoints, OPERATOR_VALUE, team_member, team_member.team_scratch(scratch_space_level)); + }; + + //Get the required size of the scratch space per team and per thread. + int perThreadSpaceSize(0), perTeamSpaceSize(0); + basisPtr->getScratchSpaceSize(perTeamSpaceSize,perThreadSpaceSize,inputPoints, OPERATOR_VALUE); + teamPolicy.set_scratch_size(scratch_space_level, Kokkos::PerTeam(perTeamSpaceSize), Kokkos::PerThread(perThreadSpaceSize)); + + Kokkos::parallel_for (teamPolicy,functor); + } + + { //compute gradients + auto functor = KOKKOS_LAMBDA (typename Kokkos::TeamPolicy::member_type team_member) { + auto gradsACell = Kokkos::subview(outputGradsA, team_member.league_rank(), Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL()); + basisRawPtr_device->getValues(gradsACell, inputPoints, OPERATOR_GRAD, team_member, team_member.team_scratch(scratch_space_level)); + }; + + //Get the required size of the scratch space per team and per thread. + int perThreadSpaceSize(0), perTeamSpaceSize(0); + basisPtr->getScratchSpaceSize(perTeamSpaceSize,perThreadSpaceSize,inputPoints, OPERATOR_GRAD); + teamPolicy.set_scratch_size(scratch_space_level, Kokkos::PerTeam(perTeamSpaceSize), Kokkos::PerThread(perThreadSpaceSize)); + + Kokkos::parallel_for (teamPolicy,functor); + } + } + + *outStream << "Computing values and gradients for " << npts << " points using high-level getValues function" <getValues(outputValuesB, inputPoints, OPERATOR_VALUE); + basisPtr->getValues(outputGradsB, inputPoints, OPERATOR_GRAD); + + *outStream << "Comparing values and gradients on host" <(); + for (size_t ic=0;ic tol) { + ++errorFlag; + std::cout << ", ic: " << ic << ", i: " << i << ", j: " << j + << ", val A: " << outputValuesA_Host(ic,i,j) + << ", val B: " << outputValuesB_Host(i,j) + << ", |diff|: " << diff + << ", tol: " << tol + << std::endl; + } + } + } + + { + // compare grads + const auto outputGradsA_Host = Kokkos::create_mirror_view(outputGradsA); Kokkos::deep_copy(outputGradsA_Host, outputGradsA); + const auto outputGradsB_Host = Kokkos::create_mirror_view(outputGradsB); Kokkos::deep_copy(outputGradsB_Host, outputGradsB); + + OutValueType diff = 0; + auto tol = epsilon(); + for (size_t ic=0;ic tol) { + ++errorFlag; + std::cout << ", ic: " << ic << ", i: " << i << ", j: " << j + << ", grads A: [" << outputGradsA_Host(ic,i,j,0) << ", " << outputGradsA_Host(ic,i,j,1) << ", " << outputGradsA_Host(ic,i,j,2) <<"]" + << ", grads B: [" << outputGradsB_Host(i,j,0) << ", " << outputGradsB_Host(i,j,1) << ", " << outputGradsB_Host(i,j,2) <<"]" + << ", |diff|: " << diff + << ", tol: " << tol + << std::endl; + } + } + } + } catch (std::exception &err) { + std::cout << "UNEXPECTED ERROR !!! ----------------------------------------------------------\n"; + std::cout << err.what() << '\n'; + std::cout << "-------------------------------------------------------------------------------" << "\n\n"; + errorFlag = -1000; + }; + + if (errorFlag != 0) + std::cout << "End Result: TEST FAILED\n"; + else + std::cout << "End Result: TEST PASSED\n"; + + return errorFlag; + } + } +} diff --git a/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_TET_COMP12_FEM/CMakeLists.txt b/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_TET_COMP12_FEM/CMakeLists.txt index 09fddb77ac02..3bc181264b2b 100644 --- a/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_TET_COMP12_FEM/CMakeLists.txt +++ b/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_TET_COMP12_FEM/CMakeLists.txt @@ -1,8 +1,13 @@ TRIBITS_INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}) + +# test +SET(Intrepid2_TEST_ETI_FILE "test_01") + # value types SET(Intrepid2_TEST_ETI_VALUETYPE_NAME "") SET(Intrepid2_TEST_ETI_VALUETYPE "") +SET(Intrepid2_TEST_ETI_SACADO "") LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE_NAME "DOUBLE") LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE "double") @@ -17,9 +22,80 @@ ENDIF() LIST(LENGTH Intrepid2_TEST_ETI_VALUETYPE_NAME ETI_VALUETYPE_COUNT) MATH(EXPR ETI_VALUETYPE_COUNT "${ETI_VALUETYPE_COUNT}-1") -# Host test -SET(Intrepid2_TEST_ETI_FILE "test_01") +# device +SET(Intrepid2_TEST_ETI_DEVICE_NAME "") +SET(Intrepid2_TEST_ETI_DEVICE "") +IF(Kokkos_ENABLE_SERIAL) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "Serial") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() +IF(Kokkos_ENABLE_OPENMP) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "OpenMP") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() +IF(Kokkos_ENABLE_CUDA) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "CUDA") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() +IF(Kokkos_ENABLE_HIP) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "HIP") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() + +LIST(LENGTH Intrepid2_TEST_ETI_DEVICE_NAME ETI_DEVICE_COUNT) +MATH(EXPR ETI_DEVICE_COUNT "${ETI_DEVICE_COUNT}-1") + +FOREACH(I RANGE ${ETI_DEVICE_COUNT}) + LIST(GET Intrepid2_TEST_ETI_DEVICE_NAME ${I} ETI_DEVICE_NAME) + LIST(GET Intrepid2_TEST_ETI_DEVICE ${I} ETI_DEVICE) + #MESSAGE(STATUS "Generating TEST HGRAD_TET_COMP12_FEM for ${ETI_DEVICE_NAME} with ${ETI_DEVICE}") + FOREACH(J RANGE ${ETI_VALUETYPE_COUNT}) + LIST(GET Intrepid2_TEST_ETI_VALUETYPE_NAME ${J} ETI_VALUETYPE_NAME) + LIST(GET Intrepid2_TEST_ETI_VALUETYPE ${J} ETI_VALUETYPE) + LIST(GET Intrepid2_TEST_ETI_SACADO ${J} ETI_SACADO) + FOREACH(ETI_FILE IN LISTS Intrepid2_TEST_ETI_FILE) + SET(ETI_NAME "${ETI_FILE}_${ETI_DEVICE_NAME}_${ETI_VALUETYPE_NAME}") + MESSAGE(STATUS "Generating TEST: HGRAD_TET_COMP12_FEM ${ETI_NAME}.cpp") + CONFIGURE_FILE(eti/${ETI_FILE}_ETI.in ${ETI_NAME}.cpp) + + TRIBITS_ADD_EXECUTABLE_AND_TEST( + ${ETI_NAME} + SOURCES ${ETI_NAME}.cpp + ARGS PrintItAll + NUM_MPI_PROCS 1 + PASS_REGULAR_EXPRESSION "TEST PASSED" + ADD_DIR_TO_NAME + ) + + ENDFOREACH() + ENDFOREACH() +ENDFOREACH() + + + + +# test +SET(Intrepid2_TEST_ETI_FILE "test_02") + +# value types +SET(Intrepid2_TEST_ETI_VALUETYPE_NAME "") +SET(Intrepid2_TEST_ETI_VALUETYPE "") +SET(Intrepid2_TEST_ETI_SACADO "") + +LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE_NAME "DOUBLE_DOUBLE") +LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE "double,double") +LIST(APPEND Intrepid2_TEST_ETI_SACADO "0") + +IF (HAVE_INTREPID2_SACADO) + LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE_NAME "DFAD_DFAD") + LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE "Sacado::Fad::DFad,Sacado::Fad::DFad ") + LIST(APPEND Intrepid2_TEST_ETI_SACADO "33") +ENDIF() + +LIST(LENGTH Intrepid2_TEST_ETI_VALUETYPE_NAME ETI_VALUETYPE_COUNT) +MATH(EXPR ETI_VALUETYPE_COUNT "${ETI_VALUETYPE_COUNT}-1") +# device SET(Intrepid2_TEST_ETI_DEVICE_NAME "") SET(Intrepid2_TEST_ETI_DEVICE "") IF(Kokkos_ENABLE_SERIAL) diff --git a/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_TET_COMP12_FEM/eti/test_02_ETI.in b/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_TET_COMP12_FEM/eti/test_02_ETI.in new file mode 100644 index 000000000000..c7a155d2f8a9 --- /dev/null +++ b/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_TET_COMP12_FEM/eti/test_02_ETI.in @@ -0,0 +1,52 @@ +// @HEADER +// ***************************************************************************** +// Intrepid2 Package +// +// Copyright 2007 NTESS and the Intrepid2 contributors. +// SPDX-License-Identifier: BSD-3-Clause +// ***************************************************************************** +// @HEADER + +/** \file test_01.cpp + \brief Unit test of Intrepid2::Basis_HGRAD_TET_COMP12_FEM team-level getValues. + \author Kyungjoo Kim +*/ + +#include "Kokkos_Core.hpp" + +#define ETI_SACADO @ETI_SACADO@ +#if (ETI_SACADO != 0) /// SACADO +#include "Kokkos_ViewFactory.hpp" +#include "Sacado.hpp" +#endif + +#if (ETI_SACADO == 0) /// double double +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__) +#elif (ETI_SACADO == 11 /* SFAD SFAD */ || ETI_SACADO == 33 /* DFAD DFAD */) +constexpr int num_deriv = 3; +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#elif (ETI_SACADO == 23) +constexpr int num_deriv = 3; +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#elif (ETI_SACADO == 20) +constexpr int num_deriv = 2; +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__) +#endif + +#include "test_02.hpp" + +int main(int argc, char *argv[]) { + + const bool verbose = (argc-1) > 0; + Kokkos::initialize(); + + Intrepid2::Test::HGRAD_TET_COMP12_FEM_Test02<@ETI_VALUETYPE@,@ETI_DEVICE@>(verbose); + + Kokkos::finalize(); + return 0; +} + diff --git a/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_TET_COMP12_FEM/test_02.hpp b/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_TET_COMP12_FEM/test_02.hpp new file mode 100644 index 000000000000..9120a9bf8b53 --- /dev/null +++ b/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_TET_COMP12_FEM/test_02.hpp @@ -0,0 +1,184 @@ +// @HEADER +// ***************************************************************************** +// Intrepid2 Package +// +// Copyright 2007 NTESS and the Intrepid2 contributors. +// SPDX-License-Identifier: BSD-3-Clause +// ***************************************************************************** +// @HEADER + +/** \file test_02.hpp + \brief Unit tests for the Intrepid2::HGRAD_TET_COMP12_FEM class. + \author Created by Kyungjoo Kim, Mauro Perego + */ + + +#include "Intrepid2_config.h" +#include "Kokkos_Random.hpp" +#ifdef HAVE_INTREPID2_DEBUG +#define INTREPID2_TEST_FOR_DEBUG_ABORT_OVERRIDE_TO_CONTINUE +#endif + +#include "Intrepid2_Types.hpp" +#include "Intrepid2_Utils.hpp" + +#include "Intrepid2_HGRAD_TET_COMP12_FEM.hpp" +#include "packages/intrepid2/unit-test/Discretization/Basis/Setup.hpp" + +namespace Intrepid2 { + + namespace Test { + + // This test evaluates the basis functions at a set of points on a batch of cells using the team-level getValues, + // and compares the results with those obtained using the classic getValues function. + template + int HGRAD_TET_COMP12_FEM_Test02(const bool verbose) { + + //! Setup test output stream. + Teuchos::RCP outStream = setup_output_stream( + verbose, "HGRAD_TET_COMP12_FEM, Test 2", {} + ); + + *outStream + << "\n" + << "===============================================================================\n" + << "| Testing Team-level Implemntation of getValues |\n" + << "===============================================================================\n"; + + using DeviceSpaceType = typename DeviceType::execution_space; + Kokkos::print_configuration(std::cout, false); + + int errorFlag = 0; + + try { + using BasisType = Basis_HGRAD_TET_COMP12_FEM; + auto basisPtr = Teuchos::rcp(new BasisType()); + + const int ncells = 5, npts = 10, ndim = 3; + Kokkos::DynRankView ConstructWithLabelOutView(outputValuesA, ncells, basisPtr->getCardinality(), npts); + Kokkos::DynRankView ConstructWithLabelOutView(outputValuesB, basisPtr->getCardinality(), npts); + + Kokkos::DynRankView ConstructWithLabelOutView(outputGradsA, ncells, basisPtr->getCardinality(), npts, ndim); + Kokkos::DynRankView ConstructWithLabelOutView(outputGradsB, basisPtr->getCardinality(), npts, ndim); + Kokkos::DynRankView ConstructWithLabelPointView(point, 1); + + using ScalarType = typename ScalarTraits::scalar_type; + + Kokkos::View inputPointsViewToUseRandom("inputPoints", npts*ndim*get_dimension_scalar(point)); + auto vcprop = Kokkos::common_view_alloc_prop(point); + Kokkos::DynRankView inputPoints (Kokkos::view_wrap(inputPointsViewToUseRandom.data(), vcprop), npts, ndim); + + // random values between (0,1) + Kokkos::Random_XorShift64_Pool random(13718); + Kokkos::fill_random(inputPointsViewToUseRandom, random, 1.0); + + + *outStream << "Computing values and gradients for " << ncells << " cells and " << npts << " points using team-level getValues function" <(*basisPtr); + auto basisRawPtr_device = basisPtr_device.get(); + + int scratch_space_level =1; + const int vectorSize = getVectorSizeForHierarchicalParallelism(); + Kokkos::TeamPolicy teamPolicy(ncells, Kokkos::AUTO,vectorSize); + + { //compute values + auto functor = KOKKOS_LAMBDA (typename Kokkos::TeamPolicy::member_type team_member) { + auto valsACell = Kokkos::subview(outputValuesA, team_member.league_rank(), Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL()); + basisRawPtr_device->getValues(valsACell, inputPoints, OPERATOR_VALUE, team_member, team_member.team_scratch(scratch_space_level)); + }; + + //Get the required size of the scratch space per team and per thread. + int perThreadSpaceSize(0), perTeamSpaceSize(0); + basisPtr->getScratchSpaceSize(perTeamSpaceSize,perThreadSpaceSize,inputPoints, OPERATOR_VALUE); + teamPolicy.set_scratch_size(scratch_space_level, Kokkos::PerTeam(perTeamSpaceSize), Kokkos::PerThread(perThreadSpaceSize)); + + Kokkos::parallel_for (teamPolicy,functor); + } + + { //compute gradients + auto functor = KOKKOS_LAMBDA (typename Kokkos::TeamPolicy::member_type team_member) { + auto gradsACell = Kokkos::subview(outputGradsA, team_member.league_rank(), Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL()); + basisRawPtr_device->getValues(gradsACell, inputPoints, OPERATOR_GRAD, team_member, team_member.team_scratch(scratch_space_level)); + }; + + //Get the required size of the scratch space per team and per thread. + int perThreadSpaceSize(0), perTeamSpaceSize(0); + basisPtr->getScratchSpaceSize(perTeamSpaceSize,perThreadSpaceSize,inputPoints, OPERATOR_GRAD); + teamPolicy.set_scratch_size(scratch_space_level, Kokkos::PerTeam(perTeamSpaceSize), Kokkos::PerThread(perThreadSpaceSize)); + + Kokkos::parallel_for (teamPolicy,functor); + } + } + + *outStream << "Computing values and gradients for " << npts << " points using high-level getValues function" <getValues(outputValuesB, inputPoints, OPERATOR_VALUE); + basisPtr->getValues(outputGradsB, inputPoints, OPERATOR_GRAD); + + *outStream << "Comparing values and gradients on host" <(); + for (size_t ic=0;ic tol) { + ++errorFlag; + std::cout << ", ic: " << ic << ", i: " << i << ", j: " << j + << ", val A: " << outputValuesA_Host(ic,i,j) + << ", val B: " << outputValuesB_Host(i,j) + << ", |diff|: " << diff + << ", tol: " << tol + << std::endl; + } + } + } + + { + // compare grads + const auto outputGradsA_Host = Kokkos::create_mirror_view(outputGradsA); Kokkos::deep_copy(outputGradsA_Host, outputGradsA); + const auto outputGradsB_Host = Kokkos::create_mirror_view(outputGradsB); Kokkos::deep_copy(outputGradsB_Host, outputGradsB); + + OutValueType diff = 0; + auto tol = epsilon(); + for (size_t ic=0;ic tol) { + ++errorFlag; + std::cout << ", ic: " << ic << ", i: " << i << ", j: " << j + << ", grads A: [" << outputGradsA_Host(ic,i,j,0) << ", " << outputGradsA_Host(ic,i,j,1) << ", " << outputGradsA_Host(ic,i,j,2) <<"]" + << ", grads B: [" << outputGradsB_Host(i,j,0) << ", " << outputGradsB_Host(i,j,1) << ", " << outputGradsB_Host(i,j,2) <<"]" + << ", |diff|: " << diff + << ", tol: " << tol + << std::endl; + } + } + } + } catch (std::exception &err) { + std::cout << "UNEXPECTED ERROR !!! ----------------------------------------------------------\n"; + std::cout << err.what() << '\n'; + std::cout << "-------------------------------------------------------------------------------" << "\n\n"; + errorFlag = -1000; + }; + + if (errorFlag != 0) + std::cout << "End Result: TEST FAILED\n"; + else + std::cout << "End Result: TEST PASSED\n"; + + return errorFlag; + } + } +} diff --git a/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_TET_Cn_FEM/CMakeLists.txt b/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_TET_Cn_FEM/CMakeLists.txt index cb2c34d9f2e6..b669b1b2ba1f 100644 --- a/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_TET_Cn_FEM/CMakeLists.txt +++ b/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_TET_Cn_FEM/CMakeLists.txt @@ -7,6 +7,7 @@ SET(Intrepid2_TEST_ETI_FILE "test_01") # value types SET(Intrepid2_TEST_ETI_VALUETYPE_NAME "") SET(Intrepid2_TEST_ETI_VALUETYPE "") +SET(Intrepid2_TEST_ETI_SACADO "") LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE_NAME "DOUBLE_DOUBLE") LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE "double,double") @@ -94,11 +95,18 @@ SET(Intrepid2_TEST_ETI_FILE "test_02") # value types SET(Intrepid2_TEST_ETI_VALUETYPE_NAME "") SET(Intrepid2_TEST_ETI_VALUETYPE "") +SET(Intrepid2_TEST_ETI_SACADO "") LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE_NAME "DOUBLE_DOUBLE") LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE "double,double") LIST(APPEND Intrepid2_TEST_ETI_SACADO "0") +IF (HAVE_INTREPID2_SACADO) + LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE_NAME "DFAD_DFAD") + LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE "Sacado::Fad::DFad,Sacado::Fad::DFad ") + LIST(APPEND Intrepid2_TEST_ETI_SACADO "33") +ENDIF() + LIST(LENGTH Intrepid2_TEST_ETI_VALUETYPE_NAME ETI_VALUETYPE_COUNT) MATH(EXPR ETI_VALUETYPE_COUNT "${ETI_VALUETYPE_COUNT}-1") diff --git a/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_TET_Cn_FEM/eti/test_01_ETI.in b/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_TET_Cn_FEM/eti/test_01_ETI.in index 74f1bccc00db..c997523b3120 100644 --- a/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_TET_Cn_FEM/eti/test_01_ETI.in +++ b/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_TET_Cn_FEM/eti/test_01_ETI.in @@ -28,10 +28,8 @@ constexpr int num_deriv = 10; #define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) #define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) #elif (ETI_SACADO == 23) -/// Mauro, the master branch uses this derivative dimension which sounds dummy -constexpr int num_deriv = 0; //9; -constexpr int max_deriv = 1; //10; -#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__, max_deriv+1) +constexpr int num_deriv = 3; +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) #define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) #elif (ETI_SACADO == 20) constexpr int num_deriv = 2; diff --git a/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_TET_Cn_FEM/eti/test_02_ETI.in b/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_TET_Cn_FEM/eti/test_02_ETI.in index c26586d323cf..a6b3263eb7c0 100644 --- a/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_TET_Cn_FEM/eti/test_02_ETI.in +++ b/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_TET_Cn_FEM/eti/test_02_ETI.in @@ -8,21 +8,44 @@ // @HEADER /** \file test_01.cpp - \brief Unit test of serial interface Intrepid2::Basis_HGRAD_TET_Cn_FEM. + \brief Unit test of Intrepid2::Basis_HGRAD_TET_Cn_FEM team-level getValues. \author Kyungjoo Kim */ #include "Kokkos_Core.hpp" +#define ETI_SACADO @ETI_SACADO@ +#if (ETI_SACADO != 0) /// SACADO +#include "Kokkos_ViewFactory.hpp" +#include "Sacado.hpp" +#endif + +#if (ETI_SACADO == 0) /// double double +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__) +#elif (ETI_SACADO == 11 /* SFAD SFAD */ || ETI_SACADO == 33 /* DFAD DFAD */) +constexpr int num_deriv = 3; +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#elif (ETI_SACADO == 23) +constexpr int num_deriv = 3; +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#elif (ETI_SACADO == 20) +constexpr int num_deriv = 2; +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__) +#endif + #include "test_02.hpp" int main(int argc, char *argv[]) { + const bool verbose = (argc-1) > 0; Kokkos::initialize(); - { - const bool verbose = (argc-1) > 0; - Intrepid2::Test::HGRAD_TET_Cn_FEM_Test02<@ETI_VALUETYPE@,@ETI_DEVICE@>(verbose); - } + + Intrepid2::Test::HGRAD_TET_Cn_FEM_Test02<@ETI_VALUETYPE@,@ETI_DEVICE@>(verbose); + Kokkos::finalize(); return 0; } diff --git a/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_TET_Cn_FEM/test_02.hpp b/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_TET_Cn_FEM/test_02.hpp index 4f6c6c3a33e0..a2cd75fc812e 100644 --- a/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_TET_Cn_FEM/test_02.hpp +++ b/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_TET_Cn_FEM/test_02.hpp @@ -7,9 +7,9 @@ // ***************************************************************************** // @HEADER -/** \file test_01.hpp +/** \file test_02.hpp \brief Unit tests for the Intrepid2::HGRAD_TET_Cn_FEM class. - \author Created by P. Bochev, D. Ridzal, K. Peterson, Kyungjoo Kim + \author Created by Kyungjoo Kim, Mauro Perego */ @@ -23,99 +23,152 @@ #include "Intrepid2_Utils.hpp" #include "Intrepid2_HGRAD_TET_Cn_FEM.hpp" +#include "packages/intrepid2/unit-test/Discretization/Basis/Setup.hpp" namespace Intrepid2 { namespace Test { - // This code provides an example to use serial interface of high order elements + // This test evaluates the basis functions at a set of points on a batch of cells using the team-level getValues, + // and compares the results with those obtained using the classic getValues function. template int HGRAD_TET_Cn_FEM_Test02(const bool verbose) { + + //! Setup test output stream. + Teuchos::RCP outStream = setup_output_stream( + verbose, "HGRAD_TET_Cn_FEM, Test 2", {} + ); + + *outStream + << "\n" + << "===============================================================================\n" + << "| Testing Team-level Implemntation of getValues |\n" + << "===============================================================================\n"; + using DeviceSpaceType = typename DeviceType::execution_space; Kokkos::print_configuration(std::cout, false); int errorFlag = 0; - + constexpr int maxOrder = 7; try { - for (int order=1;order<10;++order) { - Basis_HGRAD_TET_Cn_FEM basis(order); + for (int order=1;order<=maxOrder;++order) { + using BasisType = Basis_HGRAD_TET_Cn_FEM; + auto basisPtr = Teuchos::rcp(new BasisType(order)); - // problem setup - // let's say we want to evaluate 1000 points in parallel. output values are stored in outputValuesA and B. - // A is compuated via serial interface and B is computed with top-level interface. - const int npts = 1000, ndim = 3; - Kokkos::DynRankView outputValuesA("outputValuesA", basis.getCardinality(), npts); - Kokkos::DynRankView outputValuesB("outputValuesB", basis.getCardinality(), npts); + const int ncells = 5, npts = 10, ndim = 3; + Kokkos::DynRankView ConstructWithLabelOutView(outputValuesA, ncells, basisPtr->getCardinality(), npts); + Kokkos::DynRankView ConstructWithLabelOutView(outputValuesB, basisPtr->getCardinality(), npts); + + Kokkos::DynRankView ConstructWithLabelOutView(outputGradsA, ncells, basisPtr->getCardinality(), npts, ndim); + Kokkos::DynRankView ConstructWithLabelOutView(outputGradsB, basisPtr->getCardinality(), npts, ndim); + Kokkos::DynRankView ConstructWithLabelPointView(point, 1); + + using ScalarType = typename ScalarTraits::scalar_type; - Kokkos::View inputPointsViewToUseRandom("inputPoints", npts, ndim); - Kokkos::DynRankView inputPoints (inputPointsViewToUseRandom.data(), npts, ndim); + Kokkos::View inputPointsViewToUseRandom("inputPoints", npts*ndim*get_dimension_scalar(point)); + auto vcprop = Kokkos::common_view_alloc_prop(point); + Kokkos::DynRankView inputPoints (Kokkos::view_wrap(inputPointsViewToUseRandom.data(), vcprop), npts, ndim); - // random values between (-1,1) x (-1,1) + // random values between (0,1) Kokkos::Random_XorShift64_Pool random(13718); Kokkos::fill_random(inputPointsViewToUseRandom, random, 1.0); - // compute setup - // we need vinv and workspace - const auto vinv = basis.getVandermondeInverse(); - - // worksize - // workspace per thread is required for serial interface. - // parallel_for with range policy would be good to use stack workspace - // as team policy only can create shared memory - // this part would be tricky as the max size should be determined at compile time - // let's think about this and find out the best practice. for now I use the following. - constexpr int worksize = (Parameters::MaxOrder+1)*(Parameters::MaxOrder+1)*(Parameters::MaxOrder+1); - - // if you use team policy, worksize can be gathered from the basis object and use - // kokkos shmem_size APIs to create workspace per team or per thread. - //const auto worksize_for_teampolicy = basis.getWorksizePerPoint(OPERATOR_VALUE); - - // extract point range to be evaluated in each thread - typedef Kokkos::pair range_type; - - // parallel execution with serial interface - Kokkos::RangePolicy policy(0, npts); - Kokkos::parallel_for(policy, KOKKOS_LAMBDA(int i) { - // we evaluate a single point - const range_type pointRange = range_type(i,i+1); - - // out (# dofs, # pts), input (# pts, # dims) - auto output = Kokkos::subview(outputValuesA, Kokkos::ALL(), pointRange); - auto input = Kokkos::subview(inputPoints, pointRange, Kokkos::ALL()); + + *outStream << "Order: " << order << ": Computing values and gradients for " << ncells << " cells and " << npts << " points using team-level getValues function" <(*basisPtr); + auto basisRawPtr_device = basisPtr_device.get(); + + int scratch_space_level =1; + const int vectorSize = getVectorSizeForHierarchicalParallelism(); + Kokkos::TeamPolicy teamPolicy(ncells, Kokkos::AUTO,vectorSize); + + { //compute values + auto functor = KOKKOS_LAMBDA (typename Kokkos::TeamPolicy::member_type team_member) { + auto valsACell = Kokkos::subview(outputValuesA, team_member.league_rank(), Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL()); + basisRawPtr_device->getValues(valsACell, inputPoints, OPERATOR_VALUE, team_member, team_member.team_scratch(scratch_space_level)); + }; - // wrap static workspace with a view; serial interface has a template view interface. - // either view or dynrankview with a right size is okay. - OutValueType workbuf[worksize]; - Kokkos::View work(&workbuf[0], worksize); + //Get the required size of the scratch space per team and per thread. + int perThreadSpaceSize(0), perTeamSpaceSize(0); + basisPtr->getScratchSpaceSize(perTeamSpaceSize,perThreadSpaceSize,inputPoints, OPERATOR_VALUE); + teamPolicy.set_scratch_size(scratch_space_level, Kokkos::PerTeam(perTeamSpaceSize), Kokkos::PerThread(perThreadSpaceSize)); + + Kokkos::parallel_for (teamPolicy,functor); + } + + { //compute gradients + auto functor = KOKKOS_LAMBDA (typename Kokkos::TeamPolicy::member_type team_member) { + auto gradsACell = Kokkos::subview(outputGradsA, team_member.league_rank(), Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL()); + basisRawPtr_device->getValues(gradsACell, inputPoints, OPERATOR_GRAD, team_member, team_member.team_scratch(scratch_space_level)); + }; - // evaluate basis using serial interface - Impl::Basis_HGRAD_TET_Cn_FEM - ::Serial::getValues(output, input, work, vinv); - }); - - // evaluation using high level interface - basis.getValues(outputValuesB, inputPoints, OPERATOR_VALUE); - - // compare - const auto outputValuesA_Host = Kokkos::create_mirror_view(outputValuesA); Kokkos::deep_copy(outputValuesA_Host, outputValuesA); - const auto outputValuesB_Host = Kokkos::create_mirror_view(outputValuesB); Kokkos::deep_copy(outputValuesB_Host, outputValuesB); - - double sum = 0, diff = 0; - for (size_t i=0;igetValues(outputValuesB, inputPoints, OPERATOR_VALUE); + basisPtr->getValues(outputGradsB, inputPoints, OPERATOR_GRAD); + + *outStream << "Order: " << order << ": Comparing values and gradients on host" <(); + for (size_t ic=0;ic tol) { + ++errorFlag; + std::cout << " order: " << order + << ", ic: " << ic << ", i: " << i << ", j: " << j + << ", val A: " << outputValuesA_Host(ic,i,j) + << ", val B: " << outputValuesB_Host(i,j) + << ", |diff|: " << diff + << ", tol: " << tol + << std::endl; + } + } + } + + { + // compare grads + const auto outputGradsA_Host = Kokkos::create_mirror_view(outputGradsA); Kokkos::deep_copy(outputGradsA_Host, outputGradsA); + const auto outputGradsB_Host = Kokkos::create_mirror_view(outputGradsB); Kokkos::deep_copy(outputGradsB_Host, outputGradsB); + + OutValueType diff = 0; + //Note, a PR release-debug serial build shows substantially higher errors (possibly due to operation rearrangements). Need to investigate more. + auto tol = epsilon(); + for (size_t ic=0;ic tol) { + ++errorFlag; + std::cout << " order: " << order + << ", ic: " << ic << ", i: " << i << ", j: " << j + << ", grads A: [" << outputGradsA_Host(ic,i,j,0) << ", " << outputGradsA_Host(ic,i,j,1) << ", " << outputGradsA_Host(ic,i,j,2) <<"]" + << ", grads B: [" << outputGradsB_Host(i,j,0) << ", " << outputGradsB_Host(i,j,1) << ", " << outputGradsB_Host(i,j,2) <<"]" + << ", |diff|: " << diff + << ", tol: " << tol + << std::endl; + } + } } } } catch (std::exception &err) { diff --git a/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_TRI_C1_FEM/CMakeLists.txt b/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_TRI_C1_FEM/CMakeLists.txt index eb726da6bb26..c5f307a89f52 100644 --- a/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_TRI_C1_FEM/CMakeLists.txt +++ b/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_TRI_C1_FEM/CMakeLists.txt @@ -1,8 +1,13 @@ TRIBITS_INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}) + +# test +SET(Intrepid2_TEST_ETI_FILE "test_01") + # value types SET(Intrepid2_TEST_ETI_VALUETYPE_NAME "") SET(Intrepid2_TEST_ETI_VALUETYPE "") +SET(Intrepid2_TEST_ETI_SACADO "") LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE_NAME "DOUBLE") LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE "double") @@ -17,9 +22,80 @@ ENDIF() LIST(LENGTH Intrepid2_TEST_ETI_VALUETYPE_NAME ETI_VALUETYPE_COUNT) MATH(EXPR ETI_VALUETYPE_COUNT "${ETI_VALUETYPE_COUNT}-1") -# Host test -SET(Intrepid2_TEST_ETI_FILE "test_01") +# device +SET(Intrepid2_TEST_ETI_DEVICE_NAME "") +SET(Intrepid2_TEST_ETI_DEVICE "") +IF(Kokkos_ENABLE_SERIAL) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "Serial") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() +IF(Kokkos_ENABLE_OPENMP) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "OpenMP") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() +IF(Kokkos_ENABLE_CUDA) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "CUDA") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() +IF(Kokkos_ENABLE_HIP) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "HIP") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() + +LIST(LENGTH Intrepid2_TEST_ETI_DEVICE_NAME ETI_DEVICE_COUNT) +MATH(EXPR ETI_DEVICE_COUNT "${ETI_DEVICE_COUNT}-1") + +FOREACH(I RANGE ${ETI_DEVICE_COUNT}) + LIST(GET Intrepid2_TEST_ETI_DEVICE_NAME ${I} ETI_DEVICE_NAME) + LIST(GET Intrepid2_TEST_ETI_DEVICE ${I} ETI_DEVICE) + #MESSAGE(STATUS "Generating TEST HGRAD_TRI_C1_FEM for ${ETI_DEVICE_NAME} with ${ETI_DEVICE}") + FOREACH(J RANGE ${ETI_VALUETYPE_COUNT}) + LIST(GET Intrepid2_TEST_ETI_VALUETYPE_NAME ${J} ETI_VALUETYPE_NAME) + LIST(GET Intrepid2_TEST_ETI_VALUETYPE ${J} ETI_VALUETYPE) + LIST(GET Intrepid2_TEST_ETI_SACADO ${J} ETI_SACADO) + FOREACH(ETI_FILE IN LISTS Intrepid2_TEST_ETI_FILE) + SET(ETI_NAME "${ETI_FILE}_${ETI_DEVICE_NAME}_${ETI_VALUETYPE_NAME}") + MESSAGE(STATUS "Generating TEST: HGRAD_TRI_C1_FEM ${ETI_NAME}.cpp") + CONFIGURE_FILE(eti/${ETI_FILE}_ETI.in ${ETI_NAME}.cpp) + + TRIBITS_ADD_EXECUTABLE_AND_TEST( + ${ETI_NAME} + SOURCES ${ETI_NAME}.cpp + ARGS PrintItAll + NUM_MPI_PROCS 1 + PASS_REGULAR_EXPRESSION "TEST PASSED" + ADD_DIR_TO_NAME + ) + + ENDFOREACH() + ENDFOREACH() +ENDFOREACH() + + + + +# test +SET(Intrepid2_TEST_ETI_FILE "test_02") + +# value types +SET(Intrepid2_TEST_ETI_VALUETYPE_NAME "") +SET(Intrepid2_TEST_ETI_VALUETYPE "") +SET(Intrepid2_TEST_ETI_SACADO "") + +LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE_NAME "DOUBLE_DOUBLE") +LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE "double,double") +LIST(APPEND Intrepid2_TEST_ETI_SACADO "0") + +IF (HAVE_INTREPID2_SACADO) + LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE_NAME "DFAD_DFAD") + LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE "Sacado::Fad::DFad,Sacado::Fad::DFad ") + LIST(APPEND Intrepid2_TEST_ETI_SACADO "33") +ENDIF() + +LIST(LENGTH Intrepid2_TEST_ETI_VALUETYPE_NAME ETI_VALUETYPE_COUNT) +MATH(EXPR ETI_VALUETYPE_COUNT "${ETI_VALUETYPE_COUNT}-1") +# device SET(Intrepid2_TEST_ETI_DEVICE_NAME "") SET(Intrepid2_TEST_ETI_DEVICE "") IF(Kokkos_ENABLE_SERIAL) diff --git a/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_TRI_C1_FEM/eti/test_02_ETI.in b/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_TRI_C1_FEM/eti/test_02_ETI.in new file mode 100644 index 000000000000..1a918203d7cc --- /dev/null +++ b/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_TRI_C1_FEM/eti/test_02_ETI.in @@ -0,0 +1,52 @@ +// @HEADER +// ***************************************************************************** +// Intrepid2 Package +// +// Copyright 2007 NTESS and the Intrepid2 contributors. +// SPDX-License-Identifier: BSD-3-Clause +// ***************************************************************************** +// @HEADER + +/** \file test_01.cpp + \brief Unit test of Intrepid2::Basis_HGRAD_TRI_C1_FEM team-level getValues. + \author Kyungjoo Kim +*/ + +#include "Kokkos_Core.hpp" + +#define ETI_SACADO @ETI_SACADO@ +#if (ETI_SACADO != 0) /// SACADO +#include "Kokkos_ViewFactory.hpp" +#include "Sacado.hpp" +#endif + +#if (ETI_SACADO == 0) /// double double +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__) +#elif (ETI_SACADO == 11 /* SFAD SFAD */ || ETI_SACADO == 33 /* DFAD DFAD */) +constexpr int num_deriv = 3; +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#elif (ETI_SACADO == 23) +constexpr int num_deriv = 3; +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#elif (ETI_SACADO == 20) +constexpr int num_deriv = 2; +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__) +#endif + +#include "test_02.hpp" + +int main(int argc, char *argv[]) { + + const bool verbose = (argc-1) > 0; + Kokkos::initialize(); + + Intrepid2::Test::HGRAD_TRI_C1_FEM_Test02<@ETI_VALUETYPE@,@ETI_DEVICE@>(verbose); + + Kokkos::finalize(); + return 0; +} + diff --git a/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_TRI_C1_FEM/test_02.hpp b/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_TRI_C1_FEM/test_02.hpp new file mode 100644 index 000000000000..928394ded0a4 --- /dev/null +++ b/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_TRI_C1_FEM/test_02.hpp @@ -0,0 +1,228 @@ +// @HEADER +// ***************************************************************************** +// Intrepid2 Package +// +// Copyright 2007 NTESS and the Intrepid2 contributors. +// SPDX-License-Identifier: BSD-3-Clause +// ***************************************************************************** +// @HEADER + +/** \file test_02.hpp + \brief Unit tests for the Intrepid2::HGRAD_TRI_C1_FEM class. + \author Created by Kyungjoo Kim, Mauro Perego + */ + + +#include "Intrepid2_config.h" +#include "Kokkos_Random.hpp" +#ifdef HAVE_INTREPID2_DEBUG +#define INTREPID2_TEST_FOR_DEBUG_ABORT_OVERRIDE_TO_CONTINUE +#endif + +#include "Intrepid2_Types.hpp" +#include "Intrepid2_Utils.hpp" + +#include "Intrepid2_HGRAD_TRI_C1_FEM.hpp" +#include "packages/intrepid2/unit-test/Discretization/Basis/Setup.hpp" + +namespace Intrepid2 { + + namespace Test { + + // This test evaluates the basis functions at a set of points on a batch of cells using the team-level getValues, + // and compares the results with those obtained using the classic getValues function. + template + int HGRAD_TRI_C1_FEM_Test02(const bool verbose) { + + //! Setup test output stream. + Teuchos::RCP outStream = setup_output_stream( + verbose, "HGRAD_TRI_C1_FEM, Test 2", {} + ); + + *outStream + << "\n" + << "===============================================================================\n" + << "| Testing Team-level Implemntation of getValues |\n" + << "===============================================================================\n"; + + using DeviceSpaceType = typename DeviceType::execution_space; + Kokkos::print_configuration(std::cout, false); + + int errorFlag = 0; + + try { + using BasisType = Basis_HGRAD_TRI_C1_FEM; + auto basisPtr = Teuchos::rcp(new BasisType()); + + const int ncells = 5, npts = 10, ndim = 2; + Kokkos::DynRankView ConstructWithLabelOutView(outputValuesA, ncells, basisPtr->getCardinality(), npts); + Kokkos::DynRankView ConstructWithLabelOutView(outputValuesB, basisPtr->getCardinality(), npts); + + Kokkos::DynRankView ConstructWithLabelOutView(outputGradsA, ncells, basisPtr->getCardinality(), npts, ndim); + Kokkos::DynRankView ConstructWithLabelOutView(outputGradsB, basisPtr->getCardinality(), npts, ndim); + + Kokkos::DynRankView ConstructWithLabelOutView(outputCurlsA, ncells, basisPtr->getCardinality(), npts, ndim); + Kokkos::DynRankView ConstructWithLabelOutView(outputCurlsB, basisPtr->getCardinality(), npts, ndim); + + Kokkos::DynRankView ConstructWithLabelPointView(point, 1); + + using ScalarType = typename ScalarTraits::scalar_type; + + Kokkos::View inputPointsViewToUseRandom("inputPoints", npts*ndim*get_dimension_scalar(point)); + auto vcprop = Kokkos::common_view_alloc_prop(point); + Kokkos::DynRankView inputPoints (Kokkos::view_wrap(inputPointsViewToUseRandom.data(), vcprop), npts, ndim); + + // random values between (0,1) + Kokkos::Random_XorShift64_Pool random(13718); + Kokkos::fill_random(inputPointsViewToUseRandom, random, 1.0); + + + *outStream << "Computing values and gradients for " << ncells << " cells and " << npts << " points using team-level getValues function" <(*basisPtr); + auto basisRawPtr_device = basisPtr_device.get(); + + int scratch_space_level =1; + const int vectorSize = getVectorSizeForHierarchicalParallelism(); + Kokkos::TeamPolicy teamPolicy(ncells, Kokkos::AUTO,vectorSize); + + { //compute values + auto functor = KOKKOS_LAMBDA (typename Kokkos::TeamPolicy::member_type team_member) { + auto valsACell = Kokkos::subview(outputValuesA, team_member.league_rank(), Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL()); + basisRawPtr_device->getValues(valsACell, inputPoints, OPERATOR_VALUE, team_member, team_member.team_scratch(scratch_space_level)); + }; + + //Get the required size of the scratch space per team and per thread. + int perThreadSpaceSize(0), perTeamSpaceSize(0); + basisPtr->getScratchSpaceSize(perTeamSpaceSize,perThreadSpaceSize,inputPoints, OPERATOR_VALUE); + teamPolicy.set_scratch_size(scratch_space_level, Kokkos::PerTeam(perTeamSpaceSize), Kokkos::PerThread(perThreadSpaceSize)); + + Kokkos::parallel_for (teamPolicy,functor); + } + + { //compute gradients + auto functor = KOKKOS_LAMBDA (typename Kokkos::TeamPolicy::member_type team_member) { + auto gradsACell = Kokkos::subview(outputGradsA, team_member.league_rank(), Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL()); + basisRawPtr_device->getValues(gradsACell, inputPoints, OPERATOR_GRAD, team_member, team_member.team_scratch(scratch_space_level)); + }; + + //Get the required size of the scratch space per team and per thread. + int perThreadSpaceSize(0), perTeamSpaceSize(0); + basisPtr->getScratchSpaceSize(perTeamSpaceSize,perThreadSpaceSize,inputPoints, OPERATOR_GRAD); + teamPolicy.set_scratch_size(scratch_space_level, Kokkos::PerTeam(perTeamSpaceSize), Kokkos::PerThread(perThreadSpaceSize)); + + Kokkos::parallel_for (teamPolicy,functor); + } + + { //compute curls + auto functor = KOKKOS_LAMBDA (typename Kokkos::TeamPolicy::member_type team_member) { + auto curlsACell = Kokkos::subview(outputCurlsA, team_member.league_rank(), Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL()); + basisRawPtr_device->getValues(curlsACell, inputPoints, OPERATOR_CURL, team_member, team_member.team_scratch(scratch_space_level)); + }; + + //Get the required size of the scratch space per team and per thread. + int perThreadSpaceSize(0), perTeamSpaceSize(0); + basisPtr->getScratchSpaceSize(perTeamSpaceSize,perThreadSpaceSize,inputPoints, OPERATOR_CURL); + teamPolicy.set_scratch_size(scratch_space_level, Kokkos::PerTeam(perTeamSpaceSize), Kokkos::PerThread(perThreadSpaceSize)); + + Kokkos::parallel_for (teamPolicy,functor); + } + } + + *outStream << "Computing values and gradients for " << npts << " points using high-level getValues function" <getValues(outputValuesB, inputPoints, OPERATOR_VALUE); + basisPtr->getValues(outputGradsB, inputPoints, OPERATOR_GRAD); + basisPtr->getValues(outputCurlsB, inputPoints, OPERATOR_CURL); + + *outStream << "Comparing values and gradients on host" <(); + for (size_t ic=0;ic tol) { + ++errorFlag; + std::cout << ", ic: " << ic << ", i: " << i << ", j: " << j + << ", val A: " << outputValuesA_Host(ic,i,j) + << ", val B: " << outputValuesB_Host(i,j) + << ", |diff|: " << diff + << ", tol: " << tol + << std::endl; + } + } + } + + { + // compare grads + const auto outputGradsA_Host = Kokkos::create_mirror_view(outputGradsA); Kokkos::deep_copy(outputGradsA_Host, outputGradsA); + const auto outputGradsB_Host = Kokkos::create_mirror_view(outputGradsB); Kokkos::deep_copy(outputGradsB_Host, outputGradsB); + + OutValueType diff = 0; + auto tol = epsilon(); + for (size_t ic=0;ic tol) { + ++errorFlag; + std::cout << ", ic: " << ic << ", i: " << i << ", j: " << j + << ", grads A: [" << outputGradsA_Host(ic,i,j,0) << ", " << outputGradsA_Host(ic,i,j,1) << "]" + << ", grads B: [" << outputGradsB_Host(i,j,0) << ", " << outputGradsB_Host(i,j,1) << "]" + << ", |diff|: " << diff + << ", tol: " << tol + << std::endl; + } + } + } + + { + // compare curls + const auto outputCurlsA_Host = Kokkos::create_mirror_view(outputCurlsA); Kokkos::deep_copy(outputCurlsA_Host, outputCurlsA); + const auto outputCurlsB_Host = Kokkos::create_mirror_view(outputCurlsB); Kokkos::deep_copy(outputCurlsB_Host, outputCurlsB); + + OutValueType diff = 0; + auto tol = epsilon(); + for (size_t ic=0;ic tol) { + ++errorFlag; + std::cout << ", ic: " << ic << ", i: " << i << ", j: " << j + << ", curls A: [" << outputCurlsA_Host(ic,i,j,0) << ", " << outputCurlsA_Host(ic,i,j,1) <<"]" + << ", curls B: [" << outputCurlsB_Host(i,j,0) << ", " << outputCurlsB_Host(i,j,1) << "]" + << ", |diff|: " << diff + << ", tol: " << tol + << std::endl; + } + } + } + } catch (std::exception &err) { + std::cout << "UNEXPECTED ERROR !!! ----------------------------------------------------------\n"; + std::cout << err.what() << '\n'; + std::cout << "-------------------------------------------------------------------------------" << "\n\n"; + errorFlag = -1000; + }; + + if (errorFlag != 0) + std::cout << "End Result: TEST FAILED\n"; + else + std::cout << "End Result: TEST PASSED\n"; + + return errorFlag; + } + } +} diff --git a/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_TRI_C2_FEM/CMakeLists.txt b/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_TRI_C2_FEM/CMakeLists.txt index 21c4f220d58a..ae831c937e39 100644 --- a/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_TRI_C2_FEM/CMakeLists.txt +++ b/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_TRI_C2_FEM/CMakeLists.txt @@ -1,8 +1,13 @@ TRIBITS_INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}) + +# test +SET(Intrepid2_TEST_ETI_FILE "test_01") + # value types SET(Intrepid2_TEST_ETI_VALUETYPE_NAME "") SET(Intrepid2_TEST_ETI_VALUETYPE "") +SET(Intrepid2_TEST_ETI_SACADO "") LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE_NAME "DOUBLE") LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE "double") @@ -17,9 +22,80 @@ ENDIF() LIST(LENGTH Intrepid2_TEST_ETI_VALUETYPE_NAME ETI_VALUETYPE_COUNT) MATH(EXPR ETI_VALUETYPE_COUNT "${ETI_VALUETYPE_COUNT}-1") -# Host test -SET(Intrepid2_TEST_ETI_FILE "test_01") +# device +SET(Intrepid2_TEST_ETI_DEVICE_NAME "") +SET(Intrepid2_TEST_ETI_DEVICE "") +IF(Kokkos_ENABLE_SERIAL) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "Serial") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() +IF(Kokkos_ENABLE_OPENMP) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "OpenMP") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() +IF(Kokkos_ENABLE_CUDA) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "CUDA") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() +IF(Kokkos_ENABLE_HIP) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "HIP") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() + +LIST(LENGTH Intrepid2_TEST_ETI_DEVICE_NAME ETI_DEVICE_COUNT) +MATH(EXPR ETI_DEVICE_COUNT "${ETI_DEVICE_COUNT}-1") + +FOREACH(I RANGE ${ETI_DEVICE_COUNT}) + LIST(GET Intrepid2_TEST_ETI_DEVICE_NAME ${I} ETI_DEVICE_NAME) + LIST(GET Intrepid2_TEST_ETI_DEVICE ${I} ETI_DEVICE) + #MESSAGE(STATUS "Generating TEST HGRAD_TRI_C2_FEM for ${ETI_DEVICE_NAME} with ${ETI_DEVICE}") + FOREACH(J RANGE ${ETI_VALUETYPE_COUNT}) + LIST(GET Intrepid2_TEST_ETI_VALUETYPE_NAME ${J} ETI_VALUETYPE_NAME) + LIST(GET Intrepid2_TEST_ETI_VALUETYPE ${J} ETI_VALUETYPE) + LIST(GET Intrepid2_TEST_ETI_SACADO ${J} ETI_SACADO) + FOREACH(ETI_FILE IN LISTS Intrepid2_TEST_ETI_FILE) + SET(ETI_NAME "${ETI_FILE}_${ETI_DEVICE_NAME}_${ETI_VALUETYPE_NAME}") + MESSAGE(STATUS "Generating TEST: HGRAD_TRI_C2_FEM ${ETI_NAME}.cpp") + CONFIGURE_FILE(eti/${ETI_FILE}_ETI.in ${ETI_NAME}.cpp) + + TRIBITS_ADD_EXECUTABLE_AND_TEST( + ${ETI_NAME} + SOURCES ${ETI_NAME}.cpp + ARGS PrintItAll + NUM_MPI_PROCS 1 + PASS_REGULAR_EXPRESSION "TEST PASSED" + ADD_DIR_TO_NAME + ) + + ENDFOREACH() + ENDFOREACH() +ENDFOREACH() + + + + +# test +SET(Intrepid2_TEST_ETI_FILE "test_02") + +# value types +SET(Intrepid2_TEST_ETI_VALUETYPE_NAME "") +SET(Intrepid2_TEST_ETI_VALUETYPE "") +SET(Intrepid2_TEST_ETI_SACADO "") + +LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE_NAME "DOUBLE_DOUBLE") +LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE "double,double") +LIST(APPEND Intrepid2_TEST_ETI_SACADO "0") + +IF (HAVE_INTREPID2_SACADO) + LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE_NAME "DFAD_DFAD") + LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE "Sacado::Fad::DFad,Sacado::Fad::DFad ") + LIST(APPEND Intrepid2_TEST_ETI_SACADO "33") +ENDIF() + +LIST(LENGTH Intrepid2_TEST_ETI_VALUETYPE_NAME ETI_VALUETYPE_COUNT) +MATH(EXPR ETI_VALUETYPE_COUNT "${ETI_VALUETYPE_COUNT}-1") +# device SET(Intrepid2_TEST_ETI_DEVICE_NAME "") SET(Intrepid2_TEST_ETI_DEVICE "") IF(Kokkos_ENABLE_SERIAL) diff --git a/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_TRI_C2_FEM/eti/test_02_ETI.in b/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_TRI_C2_FEM/eti/test_02_ETI.in new file mode 100644 index 000000000000..cd49ca800b02 --- /dev/null +++ b/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_TRI_C2_FEM/eti/test_02_ETI.in @@ -0,0 +1,52 @@ +// @HEADER +// ***************************************************************************** +// Intrepid2 Package +// +// Copyright 2007 NTESS and the Intrepid2 contributors. +// SPDX-License-Identifier: BSD-3-Clause +// ***************************************************************************** +// @HEADER + +/** \file test_01.cpp + \brief Unit test of Intrepid2::Basis_HGRAD_TRI_C2_FEM team-level getValues. + \author Kyungjoo Kim +*/ + +#include "Kokkos_Core.hpp" + +#define ETI_SACADO @ETI_SACADO@ +#if (ETI_SACADO != 0) /// SACADO +#include "Kokkos_ViewFactory.hpp" +#include "Sacado.hpp" +#endif + +#if (ETI_SACADO == 0) /// double double +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__) +#elif (ETI_SACADO == 11 /* SFAD SFAD */ || ETI_SACADO == 33 /* DFAD DFAD */) +constexpr int num_deriv = 3; +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#elif (ETI_SACADO == 23) +constexpr int num_deriv = 3; +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#elif (ETI_SACADO == 20) +constexpr int num_deriv = 2; +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__) +#endif + +#include "test_02.hpp" + +int main(int argc, char *argv[]) { + + const bool verbose = (argc-1) > 0; + Kokkos::initialize(); + + Intrepid2::Test::HGRAD_TRI_C2_FEM_Test02<@ETI_VALUETYPE@,@ETI_DEVICE@>(verbose); + + Kokkos::finalize(); + return 0; +} + diff --git a/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_TRI_C2_FEM/test_02.hpp b/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_TRI_C2_FEM/test_02.hpp new file mode 100644 index 000000000000..60b8c49aa454 --- /dev/null +++ b/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_TRI_C2_FEM/test_02.hpp @@ -0,0 +1,228 @@ +// @HEADER +// ***************************************************************************** +// Intrepid2 Package +// +// Copyright 2007 NTESS and the Intrepid2 contributors. +// SPDX-License-Identifier: BSD-3-Clause +// ***************************************************************************** +// @HEADER + +/** \file test_01.hpp + \brief Unit tests for the Intrepid2::HGRAD_TRI_C2_FEM class. + \author Created by Kyungjoo Kim, Mauro Perego + */ + + +#include "Intrepid2_config.h" +#include "Kokkos_Random.hpp" +#ifdef HAVE_INTREPID2_DEBUG +#define INTREPID2_TEST_FOR_DEBUG_ABORT_OVERRIDE_TO_CONTINUE +#endif + +#include "Intrepid2_Types.hpp" +#include "Intrepid2_Utils.hpp" + +#include "Intrepid2_HGRAD_TRI_C2_FEM.hpp" +#include "packages/intrepid2/unit-test/Discretization/Basis/Setup.hpp" + +namespace Intrepid2 { + + namespace Test { + + // This test evaluates the basis functions at a set of points on a batch of cells using the team-level getValues, + // and compares the results with those obtained using the classic getValues function. + template + int HGRAD_TRI_C2_FEM_Test02(const bool verbose) { + + //! Setup test output stream. + Teuchos::RCP outStream = setup_output_stream( + verbose, "HGRAD_TRI_C2_FEM, Test 2", {} + ); + + *outStream + << "\n" + << "===============================================================================\n" + << "| Testing Team-level Implemntation of getValues |\n" + << "===============================================================================\n"; + + using DeviceSpaceType = typename DeviceType::execution_space; + Kokkos::print_configuration(std::cout, false); + + int errorFlag = 0; + + try { + using BasisType = Basis_HGRAD_TRI_C2_FEM; + auto basisPtr = Teuchos::rcp(new BasisType()); + + const int ncells = 5, npts = 10, ndim = 2; + Kokkos::DynRankView ConstructWithLabelOutView(outputValuesA, ncells, basisPtr->getCardinality(), npts); + Kokkos::DynRankView ConstructWithLabelOutView(outputValuesB, basisPtr->getCardinality(), npts); + + Kokkos::DynRankView ConstructWithLabelOutView(outputGradsA, ncells, basisPtr->getCardinality(), npts, ndim); + Kokkos::DynRankView ConstructWithLabelOutView(outputGradsB, basisPtr->getCardinality(), npts, ndim); + + Kokkos::DynRankView ConstructWithLabelOutView(outputCurlsA, ncells, basisPtr->getCardinality(), npts, ndim); + Kokkos::DynRankView ConstructWithLabelOutView(outputCurlsB, basisPtr->getCardinality(), npts, ndim); + + Kokkos::DynRankView ConstructWithLabelPointView(point, 1); + + using ScalarType = typename ScalarTraits::scalar_type; + + Kokkos::View inputPointsViewToUseRandom("inputPoints", npts*ndim*get_dimension_scalar(point)); + auto vcprop = Kokkos::common_view_alloc_prop(point); + Kokkos::DynRankView inputPoints (Kokkos::view_wrap(inputPointsViewToUseRandom.data(), vcprop), npts, ndim); + + // random values between (0,1) + Kokkos::Random_XorShift64_Pool random(13718); + Kokkos::fill_random(inputPointsViewToUseRandom, random, 1.0); + + + *outStream << "Computing values and gradients for " << ncells << " cells and " << npts << " points using team-level getValues function" <(*basisPtr); + auto basisRawPtr_device = basisPtr_device.get(); + + int scratch_space_level =1; + const int vectorSize = getVectorSizeForHierarchicalParallelism(); + Kokkos::TeamPolicy teamPolicy(ncells, Kokkos::AUTO,vectorSize); + + { //compute values + auto functor = KOKKOS_LAMBDA (typename Kokkos::TeamPolicy::member_type team_member) { + auto valsACell = Kokkos::subview(outputValuesA, team_member.league_rank(), Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL()); + basisRawPtr_device->getValues(valsACell, inputPoints, OPERATOR_VALUE, team_member, team_member.team_scratch(scratch_space_level)); + }; + + //Get the required size of the scratch space per team and per thread. + int perThreadSpaceSize(0), perTeamSpaceSize(0); + basisPtr->getScratchSpaceSize(perTeamSpaceSize,perThreadSpaceSize,inputPoints, OPERATOR_VALUE); + teamPolicy.set_scratch_size(scratch_space_level, Kokkos::PerTeam(perTeamSpaceSize), Kokkos::PerThread(perThreadSpaceSize)); + + Kokkos::parallel_for (teamPolicy,functor); + } + + { //compute gradients + auto functor = KOKKOS_LAMBDA (typename Kokkos::TeamPolicy::member_type team_member) { + auto gradsACell = Kokkos::subview(outputGradsA, team_member.league_rank(), Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL()); + basisRawPtr_device->getValues(gradsACell, inputPoints, OPERATOR_GRAD, team_member, team_member.team_scratch(scratch_space_level)); + }; + + //Get the required size of the scratch space per team and per thread. + int perThreadSpaceSize(0), perTeamSpaceSize(0); + basisPtr->getScratchSpaceSize(perTeamSpaceSize,perThreadSpaceSize,inputPoints, OPERATOR_GRAD); + teamPolicy.set_scratch_size(scratch_space_level, Kokkos::PerTeam(perTeamSpaceSize), Kokkos::PerThread(perThreadSpaceSize)); + + Kokkos::parallel_for (teamPolicy,functor); + } + + { //compute curls + auto functor = KOKKOS_LAMBDA (typename Kokkos::TeamPolicy::member_type team_member) { + auto curlsACell = Kokkos::subview(outputCurlsA, team_member.league_rank(), Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL()); + basisRawPtr_device->getValues(curlsACell, inputPoints, OPERATOR_CURL, team_member, team_member.team_scratch(scratch_space_level)); + }; + + //Get the required size of the scratch space per team and per thread. + int perThreadSpaceSize(0), perTeamSpaceSize(0); + basisPtr->getScratchSpaceSize(perTeamSpaceSize,perThreadSpaceSize,inputPoints, OPERATOR_CURL); + teamPolicy.set_scratch_size(scratch_space_level, Kokkos::PerTeam(perTeamSpaceSize), Kokkos::PerThread(perThreadSpaceSize)); + + Kokkos::parallel_for (teamPolicy,functor); + } + } + + *outStream << "Computing values and gradients for " << npts << " points using high-level getValues function" <getValues(outputValuesB, inputPoints, OPERATOR_VALUE); + basisPtr->getValues(outputGradsB, inputPoints, OPERATOR_GRAD); + basisPtr->getValues(outputCurlsB, inputPoints, OPERATOR_CURL); + + *outStream << "Comparing values and gradients on host" <(); + for (size_t ic=0;ic tol) { + ++errorFlag; + std::cout << ", ic: " << ic << ", i: " << i << ", j: " << j + << ", val A: " << outputValuesA_Host(ic,i,j) + << ", val B: " << outputValuesB_Host(i,j) + << ", |diff|: " << diff + << ", tol: " << tol + << std::endl; + } + } + } + + { + // compare grads + const auto outputGradsA_Host = Kokkos::create_mirror_view(outputGradsA); Kokkos::deep_copy(outputGradsA_Host, outputGradsA); + const auto outputGradsB_Host = Kokkos::create_mirror_view(outputGradsB); Kokkos::deep_copy(outputGradsB_Host, outputGradsB); + + OutValueType diff = 0; + auto tol = epsilon(); + for (size_t ic=0;ic tol) { + ++errorFlag; + std::cout << ", ic: " << ic << ", i: " << i << ", j: " << j + << ", grads A: [" << outputGradsA_Host(ic,i,j,0) << ", " << outputGradsA_Host(ic,i,j,1) << "]" + << ", grads B: [" << outputGradsB_Host(i,j,0) << ", " << outputGradsB_Host(i,j,1) << "]" + << ", |diff|: " << diff + << ", tol: " << tol + << std::endl; + } + } + } + + { + // compare curls + const auto outputCurlsA_Host = Kokkos::create_mirror_view(outputCurlsA); Kokkos::deep_copy(outputCurlsA_Host, outputCurlsA); + const auto outputCurlsB_Host = Kokkos::create_mirror_view(outputCurlsB); Kokkos::deep_copy(outputCurlsB_Host, outputCurlsB); + + OutValueType diff = 0; + auto tol = epsilon(); + for (size_t ic=0;ic tol) { + ++errorFlag; + std::cout << ", ic: " << ic << ", i: " << i << ", j: " << j + << ", curls A: [" << outputCurlsA_Host(ic,i,j,0) << ", " << outputCurlsA_Host(ic,i,j,1) <<"]" + << ", curls B: [" << outputCurlsB_Host(i,j,0) << ", " << outputCurlsB_Host(i,j,1) << "]" + << ", |diff|: " << diff + << ", tol: " << tol + << std::endl; + } + } + } + } catch (std::exception &err) { + std::cout << "UNEXPECTED ERROR !!! ----------------------------------------------------------\n"; + std::cout << err.what() << '\n'; + std::cout << "-------------------------------------------------------------------------------" << "\n\n"; + errorFlag = -1000; + }; + + if (errorFlag != 0) + std::cout << "End Result: TEST FAILED\n"; + else + std::cout << "End Result: TEST PASSED\n"; + + return errorFlag; + } + } +} diff --git a/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_TRI_Cn_FEM/CMakeLists.txt b/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_TRI_Cn_FEM/CMakeLists.txt index 28b96612c334..4855e54c85a1 100644 --- a/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_TRI_Cn_FEM/CMakeLists.txt +++ b/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_TRI_Cn_FEM/CMakeLists.txt @@ -7,6 +7,7 @@ SET(Intrepid2_TEST_ETI_FILE "test_01") # value types SET(Intrepid2_TEST_ETI_VALUETYPE_NAME "") SET(Intrepid2_TEST_ETI_VALUETYPE "") +SET(Intrepid2_TEST_ETI_SACADO "") LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE_NAME "DOUBLE_DOUBLE") LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE "double,double") @@ -94,11 +95,18 @@ SET(Intrepid2_TEST_ETI_FILE "test_02") # value types SET(Intrepid2_TEST_ETI_VALUETYPE_NAME "") SET(Intrepid2_TEST_ETI_VALUETYPE "") +SET(Intrepid2_TEST_ETI_SACADO "") LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE_NAME "DOUBLE_DOUBLE") LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE "double,double") LIST(APPEND Intrepid2_TEST_ETI_SACADO "0") +IF (HAVE_INTREPID2_SACADO) + LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE_NAME "DFAD_DFAD") + LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE "Sacado::Fad::DFad,Sacado::Fad::DFad ") + LIST(APPEND Intrepid2_TEST_ETI_SACADO "33") +ENDIF() + LIST(LENGTH Intrepid2_TEST_ETI_VALUETYPE_NAME ETI_VALUETYPE_COUNT) MATH(EXPR ETI_VALUETYPE_COUNT "${ETI_VALUETYPE_COUNT}-1") diff --git a/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_TRI_Cn_FEM/eti/test_01_ETI.in b/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_TRI_Cn_FEM/eti/test_01_ETI.in index 513cf7cb37bc..eaaead469fb6 100644 --- a/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_TRI_Cn_FEM/eti/test_01_ETI.in +++ b/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_TRI_Cn_FEM/eti/test_01_ETI.in @@ -14,7 +14,6 @@ #include "Kokkos_Core.hpp" - #define ETI_SACADO @ETI_SACADO@ #if (ETI_SACADO != 0) /// SACADO #include "Kokkos_ViewFactory.hpp" @@ -29,16 +28,15 @@ constexpr int num_deriv = 10; #define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) #define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) #elif (ETI_SACADO == 23) -/// Mauro, the master branch uses this derivative dimension which sounds dummy -constexpr int num_deriv = 0; //9; -constexpr int max_deriv = 1; //10; -#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__, max_deriv+1) +constexpr int num_deriv = 3; +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) #define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) #elif (ETI_SACADO == 20) constexpr int num_deriv = 2; #define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) #define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__) #endif + #include "test_01.hpp" int main(int argc, char *argv[]) { diff --git a/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_TRI_Cn_FEM/eti/test_02_ETI.in b/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_TRI_Cn_FEM/eti/test_02_ETI.in index c78997d6ea0c..a5343a485d3a 100644 --- a/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_TRI_Cn_FEM/eti/test_02_ETI.in +++ b/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_TRI_Cn_FEM/eti/test_02_ETI.in @@ -14,15 +14,38 @@ #include "Kokkos_Core.hpp" +#define ETI_SACADO @ETI_SACADO@ +#if (ETI_SACADO != 0) /// SACADO +#include "Kokkos_ViewFactory.hpp" +#include "Sacado.hpp" +#endif + +#if (ETI_SACADO == 0) /// double double +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__) +#elif (ETI_SACADO == 11 /* SFAD SFAD */ || ETI_SACADO == 33 /* DFAD DFAD */) +constexpr int num_deriv = 3; +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#elif (ETI_SACADO == 23) +constexpr int num_deriv = 3; +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#elif (ETI_SACADO == 20) +constexpr int num_deriv = 2; +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__) +#endif + #include "test_02.hpp" int main(int argc, char *argv[]) { + const bool verbose = (argc-1) > 0; Kokkos::initialize(); - { - const bool verbose = (argc-1) > 0; - Intrepid2::Test::HGRAD_TRI_Cn_FEM_Test02<@ETI_VALUETYPE@,@ETI_DEVICE@>(verbose); - } + + Intrepid2::Test::HGRAD_TRI_Cn_FEM_Test02<@ETI_VALUETYPE@,@ETI_DEVICE@>(verbose); + Kokkos::finalize(); return 0; } diff --git a/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_TRI_Cn_FEM/test_02.hpp b/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_TRI_Cn_FEM/test_02.hpp index 80d75c9bf099..a82178b45f9a 100644 --- a/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_TRI_Cn_FEM/test_02.hpp +++ b/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_TRI_Cn_FEM/test_02.hpp @@ -7,9 +7,9 @@ // ***************************************************************************** // @HEADER -/** \file test_01.hpp +/** \file test_02.hpp \brief Unit tests for the Intrepid2::HGRAD_TRI_Cn_FEM class. - \author Created by P. Bochev, D. Ridzal, K. Peterson, Kyungjoo Kim + \author Created by Kyungjoo Kim, Mauro Perego */ @@ -23,99 +23,196 @@ #include "Intrepid2_Utils.hpp" #include "Intrepid2_HGRAD_TRI_Cn_FEM.hpp" +#include "packages/intrepid2/unit-test/Discretization/Basis/Setup.hpp" namespace Intrepid2 { namespace Test { - // This code provides an example to use serial interface of high order elements + // This test evaluates the basis functions at a set of points on a batch of cells using the team-level getValues, + // and compares the results with those obtained using the classic getValues function. template int HGRAD_TRI_Cn_FEM_Test02(const bool verbose) { + + //! Setup test output stream. + Teuchos::RCP outStream = setup_output_stream( + verbose, "HGRAD_TRI_Cn_FEM, Test 2", {} + ); + + *outStream + << "\n" + << "===============================================================================\n" + << "| Testing Team-level Implemntation of getValues |\n" + << "===============================================================================\n"; + using DeviceSpaceType = typename DeviceType::execution_space; Kokkos::print_configuration(std::cout, false); int errorFlag = 0; - + constexpr int maxOrder = 9; try { - for (int order=1;order basis(order); + for (int order=1;order<=maxOrder;++order) { + using BasisType = Basis_HGRAD_TRI_Cn_FEM; + auto basisPtr = Teuchos::rcp(new BasisType(order)); - // problem setup - // let's say we want to evaluate 1000 points in parallel. output values are stored in outputValuesA and B. - // A is compuated via serial interface and B is computed with top-level interface. - const int npts = 1000, ndim = 2; - Kokkos::DynRankView outputValuesA("outputValuesA", basis.getCardinality(), npts); - Kokkos::DynRankView outputValuesB("outputValuesB", basis.getCardinality(), npts); + const int ncells = 5, npts = 10, ndim = 2; + Kokkos::DynRankView ConstructWithLabelOutView(outputValuesA, ncells, basisPtr->getCardinality(), npts); + Kokkos::DynRankView ConstructWithLabelOutView(outputValuesB, basisPtr->getCardinality(), npts); + + Kokkos::DynRankView ConstructWithLabelOutView(outputGradsA, ncells, basisPtr->getCardinality(), npts, ndim); + Kokkos::DynRankView ConstructWithLabelOutView(outputGradsB, basisPtr->getCardinality(), npts, ndim); + + Kokkos::DynRankView ConstructWithLabelOutView(outputCurlsA, ncells, basisPtr->getCardinality(), npts, ndim); + Kokkos::DynRankView ConstructWithLabelOutView(outputCurlsB, basisPtr->getCardinality(), npts, ndim); + + Kokkos::DynRankView ConstructWithLabelPointView(point, 1); - Kokkos::View inputPointsViewToUseRandom("inputPoints", npts, ndim); - Kokkos::DynRankView inputPoints (inputPointsViewToUseRandom.data(), npts, ndim); + using ScalarType = typename ScalarTraits::scalar_type; - // random values between (-1,1) x (-1,1) + Kokkos::View inputPointsViewToUseRandom("inputPoints", npts*ndim*get_dimension_scalar(point)); + auto vcprop = Kokkos::common_view_alloc_prop(point); + Kokkos::DynRankView inputPoints (Kokkos::view_wrap(inputPointsViewToUseRandom.data(), vcprop), npts, ndim); + + // random values between (0,1) Kokkos::Random_XorShift64_Pool random(13718); Kokkos::fill_random(inputPointsViewToUseRandom, random, 1.0); - // compute setup - // we need vinv and workspace - const auto vinv = basis.getVandermondeInverse(); - - // worksize - // workspace per thread is required for serial interface. - // parallel_for with range policy would be good to use stack workspace - // as team policy only can create shared memory - // this part would be tricky as the max size should be determined at compile time - // let's think about this and find out the best practice. for now I use the following. - constexpr int worksize = (Parameters::MaxOrder+1)*(Parameters::MaxOrder+1); - - // if you use team policy, worksize can be gathered from the basis object and use - // kokkos shmem_size APIs to create workspace per team or per thread. - //const auto worksize_for_teampolicy = basis.getWorksizePerPoint(OPERATOR_VALUE); - - // extract point range to be evaluated in each thread - typedef Kokkos::pair range_type; - - // parallel execution with serial interface - Kokkos::RangePolicy policy(0, npts); - Kokkos::parallel_for(policy, KOKKOS_LAMBDA(int i) { - // we evaluate a single point - const range_type pointRange = range_type(i,i+1); + + *outStream << "Order: " << order << ": Computing values and gradients for " << ncells << " cells and " << npts << " points using team-level getValues function" <(*basisPtr); + auto basisRawPtr_device = basisPtr_device.get(); + + int scratch_space_level =1; + const int vectorSize = getVectorSizeForHierarchicalParallelism(); + Kokkos::TeamPolicy teamPolicy(ncells, Kokkos::AUTO,vectorSize); + + { //compute values + auto functor = KOKKOS_LAMBDA (typename Kokkos::TeamPolicy::member_type team_member) { + auto valsACell = Kokkos::subview(outputValuesA, team_member.league_rank(), Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL()); + basisRawPtr_device->getValues(valsACell, inputPoints, OPERATOR_VALUE, team_member, team_member.team_scratch(scratch_space_level)); + }; - // out (# dofs, # pts), input (# pts, # dims) - auto output = Kokkos::subview(outputValuesA, Kokkos::ALL(), pointRange); - auto input = Kokkos::subview(inputPoints, pointRange, Kokkos::ALL()); + //Get the required size of the scratch space per team and per thread. + int perThreadSpaceSize(0), perTeamSpaceSize(0); + basisPtr->getScratchSpaceSize(perTeamSpaceSize,perThreadSpaceSize,inputPoints, OPERATOR_VALUE); + teamPolicy.set_scratch_size(scratch_space_level, Kokkos::PerTeam(perTeamSpaceSize), Kokkos::PerThread(perThreadSpaceSize)); + + Kokkos::parallel_for (teamPolicy,functor); + } + + { //compute gradients + auto functor = KOKKOS_LAMBDA (typename Kokkos::TeamPolicy::member_type team_member) { + auto gradsACell = Kokkos::subview(outputGradsA, team_member.league_rank(), Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL()); + basisRawPtr_device->getValues(gradsACell, inputPoints, OPERATOR_GRAD, team_member, team_member.team_scratch(scratch_space_level)); + }; - // wrap static workspace with a view; serial interface has a template view interface. - // either view or dynrankview with a right size is okay. - OutValueType workbuf[worksize]; - Kokkos::View work(&workbuf[0], worksize); + //Get the required size of the scratch space per team and per thread. + int perThreadSpaceSize(0), perTeamSpaceSize(0); + basisPtr->getScratchSpaceSize(perTeamSpaceSize,perThreadSpaceSize,inputPoints, OPERATOR_GRAD); + teamPolicy.set_scratch_size(scratch_space_level, Kokkos::PerTeam(perTeamSpaceSize), Kokkos::PerThread(perThreadSpaceSize)); + + Kokkos::parallel_for (teamPolicy,functor); + } + + { //compute curls + auto functor = KOKKOS_LAMBDA (typename Kokkos::TeamPolicy::member_type team_member) { + auto curlsACell = Kokkos::subview(outputCurlsA, team_member.league_rank(), Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL()); + basisRawPtr_device->getValues(curlsACell, inputPoints, OPERATOR_CURL, team_member, team_member.team_scratch(scratch_space_level)); + }; - // evaluate basis using serial interface - Impl::Basis_HGRAD_TRI_Cn_FEM - ::Serial::getValues(output, input, work, vinv); - }); - - // evaluation using high level interface - basis.getValues(outputValuesB, inputPoints, OPERATOR_VALUE); - - // compare - const auto outputValuesA_Host = Kokkos::create_mirror_view(outputValuesA); Kokkos::deep_copy(outputValuesA_Host, outputValuesA); - const auto outputValuesB_Host = Kokkos::create_mirror_view(outputValuesB); Kokkos::deep_copy(outputValuesB_Host, outputValuesB); - - double sum = 0, diff = 0; - for (size_t i=0;igetValues(outputValuesB, inputPoints, OPERATOR_VALUE); + basisPtr->getValues(outputGradsB, inputPoints, OPERATOR_GRAD); + basisPtr->getValues(outputCurlsB, inputPoints, OPERATOR_CURL); + + *outStream << "Order: " << order << ": Comparing values and gradients on host" <(); + for (size_t ic=0;ic tol) { + ++errorFlag; + std::cout << " order: " << order + << ", ic: " << ic << ", i: " << i << ", j: " << j + << ", val A: " << outputValuesA_Host(ic,i,j) + << ", val B: " << outputValuesB_Host(i,j) + << ", |diff|: " << diff + << ", tol: " << tol + << std::endl; + } + } + } + + { + // compare grads + const auto outputGradsA_Host = Kokkos::create_mirror_view(outputGradsA); Kokkos::deep_copy(outputGradsA_Host, outputGradsA); + const auto outputGradsB_Host = Kokkos::create_mirror_view(outputGradsB); Kokkos::deep_copy(outputGradsB_Host, outputGradsB); + + OutValueType diff = 0; + auto tol = epsilon(); + for (size_t ic=0;ic tol) { + ++errorFlag; + std::cout << " order: " << order + << ", ic: " << ic << ", i: " << i << ", j: " << j + << ", grads A: [" << outputGradsA_Host(ic,i,j,0) << ", " << outputGradsA_Host(ic,i,j,1) << "]" + << ", grads B: [" << outputGradsB_Host(i,j,0) << ", " << outputGradsB_Host(i,j,1) << "]" + << ", |diff|: " << diff + << ", tol: " << tol + << std::endl; + } + } + } + + { + // compare curls + const auto outputCurlsA_Host = Kokkos::create_mirror_view(outputCurlsA); Kokkos::deep_copy(outputCurlsA_Host, outputCurlsA); + const auto outputCurlsB_Host = Kokkos::create_mirror_view(outputCurlsB); Kokkos::deep_copy(outputCurlsB_Host, outputCurlsB); + + OutValueType diff = 0; + auto tol = epsilon(); + for (size_t ic=0;ic tol) { + ++errorFlag; + std::cout << " order: " << order + << ", ic: " << ic << ", i: " << i << ", j: " << j + << ", curls A: [" << outputCurlsA_Host(ic,i,j,0) << ", " << outputCurlsA_Host(ic,i,j,1) <<"]" + << ", curls B: [" << outputCurlsB_Host(i,j,0) << ", " << outputCurlsB_Host(i,j,1) << "]" + << ", |diff|: " << diff + << ", tol: " << tol + << std::endl; + } + } } } } catch (std::exception &err) { diff --git a/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_WEDGE_C1_FEM/CMakeLists.txt b/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_WEDGE_C1_FEM/CMakeLists.txt index a32463e45988..4b1a7626d4ff 100644 --- a/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_WEDGE_C1_FEM/CMakeLists.txt +++ b/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_WEDGE_C1_FEM/CMakeLists.txt @@ -1,8 +1,13 @@ TRIBITS_INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}) + +# test +SET(Intrepid2_TEST_ETI_FILE "test_01") + # value types SET(Intrepid2_TEST_ETI_VALUETYPE_NAME "") SET(Intrepid2_TEST_ETI_VALUETYPE "") +SET(Intrepid2_TEST_ETI_SACADO "") LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE_NAME "DOUBLE") LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE "double") @@ -17,9 +22,80 @@ ENDIF() LIST(LENGTH Intrepid2_TEST_ETI_VALUETYPE_NAME ETI_VALUETYPE_COUNT) MATH(EXPR ETI_VALUETYPE_COUNT "${ETI_VALUETYPE_COUNT}-1") -# Host test -SET(Intrepid2_TEST_ETI_FILE "test_01") +# device +SET(Intrepid2_TEST_ETI_DEVICE_NAME "") +SET(Intrepid2_TEST_ETI_DEVICE "") +IF(Kokkos_ENABLE_SERIAL) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "Serial") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() +IF(Kokkos_ENABLE_OPENMP) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "OpenMP") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() +IF(Kokkos_ENABLE_CUDA) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "CUDA") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() +IF(Kokkos_ENABLE_HIP) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "HIP") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() + +LIST(LENGTH Intrepid2_TEST_ETI_DEVICE_NAME ETI_DEVICE_COUNT) +MATH(EXPR ETI_DEVICE_COUNT "${ETI_DEVICE_COUNT}-1") + +FOREACH(I RANGE ${ETI_DEVICE_COUNT}) + LIST(GET Intrepid2_TEST_ETI_DEVICE_NAME ${I} ETI_DEVICE_NAME) + LIST(GET Intrepid2_TEST_ETI_DEVICE ${I} ETI_DEVICE) + #MESSAGE(STATUS "Generating TEST HGRAD_WEDGE_C1_FEM for ${ETI_DEVICE_NAME} with ${ETI_DEVICE}") + FOREACH(J RANGE ${ETI_VALUETYPE_COUNT}) + LIST(GET Intrepid2_TEST_ETI_VALUETYPE_NAME ${J} ETI_VALUETYPE_NAME) + LIST(GET Intrepid2_TEST_ETI_VALUETYPE ${J} ETI_VALUETYPE) + LIST(GET Intrepid2_TEST_ETI_SACADO ${J} ETI_SACADO) + FOREACH(ETI_FILE IN LISTS Intrepid2_TEST_ETI_FILE) + SET(ETI_NAME "${ETI_FILE}_${ETI_DEVICE_NAME}_${ETI_VALUETYPE_NAME}") + MESSAGE(STATUS "Generating TEST: HGRAD_WEDGE_C1_FEM ${ETI_NAME}.cpp") + CONFIGURE_FILE(eti/${ETI_FILE}_ETI.in ${ETI_NAME}.cpp) + + TRIBITS_ADD_EXECUTABLE_AND_TEST( + ${ETI_NAME} + SOURCES ${ETI_NAME}.cpp + ARGS PrintItAll + NUM_MPI_PROCS 1 + PASS_REGULAR_EXPRESSION "TEST PASSED" + ADD_DIR_TO_NAME + ) + + ENDFOREACH() + ENDFOREACH() +ENDFOREACH() + + + + +# test +SET(Intrepid2_TEST_ETI_FILE "test_02") + +# value types +SET(Intrepid2_TEST_ETI_VALUETYPE_NAME "") +SET(Intrepid2_TEST_ETI_VALUETYPE "") +SET(Intrepid2_TEST_ETI_SACADO "") + +LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE_NAME "DOUBLE_DOUBLE") +LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE "double,double") +LIST(APPEND Intrepid2_TEST_ETI_SACADO "0") + +IF (HAVE_INTREPID2_SACADO) + LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE_NAME "DFAD_DFAD") + LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE "Sacado::Fad::DFad,Sacado::Fad::DFad ") + LIST(APPEND Intrepid2_TEST_ETI_SACADO "33") +ENDIF() + +LIST(LENGTH Intrepid2_TEST_ETI_VALUETYPE_NAME ETI_VALUETYPE_COUNT) +MATH(EXPR ETI_VALUETYPE_COUNT "${ETI_VALUETYPE_COUNT}-1") +# device SET(Intrepid2_TEST_ETI_DEVICE_NAME "") SET(Intrepid2_TEST_ETI_DEVICE "") IF(Kokkos_ENABLE_SERIAL) diff --git a/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_WEDGE_C1_FEM/eti/test_02_ETI.in b/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_WEDGE_C1_FEM/eti/test_02_ETI.in new file mode 100644 index 000000000000..759d2a05ad2a --- /dev/null +++ b/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_WEDGE_C1_FEM/eti/test_02_ETI.in @@ -0,0 +1,52 @@ +// @HEADER +// ***************************************************************************** +// Intrepid2 Package +// +// Copyright 2007 NTESS and the Intrepid2 contributors. +// SPDX-License-Identifier: BSD-3-Clause +// ***************************************************************************** +// @HEADER + +/** \file test_01.cpp + \brief Unit test of Intrepid2::Basis_HGRAD_WEDGE_C1_FEM team-level getValues. + \author Kyungjoo Kim +*/ + +#include "Kokkos_Core.hpp" + +#define ETI_SACADO @ETI_SACADO@ +#if (ETI_SACADO != 0) /// SACADO +#include "Kokkos_ViewFactory.hpp" +#include "Sacado.hpp" +#endif + +#if (ETI_SACADO == 0) /// double double +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__) +#elif (ETI_SACADO == 11 /* SFAD SFAD */ || ETI_SACADO == 33 /* DFAD DFAD */) +constexpr int num_deriv = 3; +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#elif (ETI_SACADO == 23) +constexpr int num_deriv = 3; +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#elif (ETI_SACADO == 20) +constexpr int num_deriv = 2; +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__) +#endif + +#include "test_02.hpp" + +int main(int argc, char *argv[]) { + + const bool verbose = (argc-1) > 0; + Kokkos::initialize(); + + Intrepid2::Test::HGRAD_WEDGE_C1_FEM_Test02<@ETI_VALUETYPE@,@ETI_DEVICE@>(verbose); + + Kokkos::finalize(); + return 0; +} + diff --git a/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_WEDGE_C1_FEM/test_02.hpp b/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_WEDGE_C1_FEM/test_02.hpp new file mode 100644 index 000000000000..33f9bb85137d --- /dev/null +++ b/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_WEDGE_C1_FEM/test_02.hpp @@ -0,0 +1,184 @@ +// @HEADER +// ***************************************************************************** +// Intrepid2 Package +// +// Copyright 2007 NTESS and the Intrepid2 contributors. +// SPDX-License-Identifier: BSD-3-Clause +// ***************************************************************************** +// @HEADER + +/** \file test_02.hpp + \brief Unit tests for the Intrepid2::HGRAD_WEDGE_C1_FEM class. + \author Created by Kyungjoo Kim, Mauro Perego + */ + + +#include "Intrepid2_config.h" +#include "Kokkos_Random.hpp" +#ifdef HAVE_INTREPID2_DEBUG +#define INTREPID2_TEST_FOR_DEBUG_ABORT_OVERRIDE_TO_CONTINUE +#endif + +#include "Intrepid2_Types.hpp" +#include "Intrepid2_Utils.hpp" + +#include "Intrepid2_HGRAD_WEDGE_C1_FEM.hpp" +#include "packages/intrepid2/unit-test/Discretization/Basis/Setup.hpp" + +namespace Intrepid2 { + + namespace Test { + + // This test evaluates the basis functions at a set of points on a batch of cells using the team-level getValues, + // and compares the results with those obtained using the classic getValues function. + template + int HGRAD_WEDGE_C1_FEM_Test02(const bool verbose) { + + //! Setup test output stream. + Teuchos::RCP outStream = setup_output_stream( + verbose, "HGRAD_WEDGE_C1_FEM, Test 2", {} + ); + + *outStream + << "\n" + << "===============================================================================\n" + << "| Testing Team-level Implemntation of getValues |\n" + << "===============================================================================\n"; + + using DeviceSpaceType = typename DeviceType::execution_space; + Kokkos::print_configuration(std::cout, false); + + int errorFlag = 0; + + try { + using BasisType = Basis_HGRAD_WEDGE_C1_FEM; + auto basisPtr = Teuchos::rcp(new BasisType()); + + const int ncells = 5, npts = 10, ndim = 3; + Kokkos::DynRankView ConstructWithLabelOutView(outputValuesA, ncells, basisPtr->getCardinality(), npts); + Kokkos::DynRankView ConstructWithLabelOutView(outputValuesB, basisPtr->getCardinality(), npts); + + Kokkos::DynRankView ConstructWithLabelOutView(outputGradsA, ncells, basisPtr->getCardinality(), npts, ndim); + Kokkos::DynRankView ConstructWithLabelOutView(outputGradsB, basisPtr->getCardinality(), npts, ndim); + Kokkos::DynRankView ConstructWithLabelPointView(point, 1); + + using ScalarType = typename ScalarTraits::scalar_type; + + Kokkos::View inputPointsViewToUseRandom("inputPoints", npts*ndim*get_dimension_scalar(point)); + auto vcprop = Kokkos::common_view_alloc_prop(point); + Kokkos::DynRankView inputPoints (Kokkos::view_wrap(inputPointsViewToUseRandom.data(), vcprop), npts, ndim); + + // random values between (0,1) + Kokkos::Random_XorShift64_Pool random(13718); + Kokkos::fill_random(inputPointsViewToUseRandom, random, 1.0); + + + *outStream << "Computing values and gradients for " << ncells << " cells and " << npts << " points using team-level getValues function" <(*basisPtr); + auto basisRawPtr_device = basisPtr_device.get(); + + int scratch_space_level =1; + const int vectorSize = getVectorSizeForHierarchicalParallelism(); + Kokkos::TeamPolicy teamPolicy(ncells, Kokkos::AUTO,vectorSize); + + { //compute values + auto functor = KOKKOS_LAMBDA (typename Kokkos::TeamPolicy::member_type team_member) { + auto valsACell = Kokkos::subview(outputValuesA, team_member.league_rank(), Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL()); + basisRawPtr_device->getValues(valsACell, inputPoints, OPERATOR_VALUE, team_member, team_member.team_scratch(scratch_space_level)); + }; + + //Get the required size of the scratch space per team and per thread. + int perThreadSpaceSize(0), perTeamSpaceSize(0); + basisPtr->getScratchSpaceSize(perTeamSpaceSize,perThreadSpaceSize,inputPoints, OPERATOR_VALUE); + teamPolicy.set_scratch_size(scratch_space_level, Kokkos::PerTeam(perTeamSpaceSize), Kokkos::PerThread(perThreadSpaceSize)); + + Kokkos::parallel_for (teamPolicy,functor); + } + + { //compute gradients + auto functor = KOKKOS_LAMBDA (typename Kokkos::TeamPolicy::member_type team_member) { + auto gradsACell = Kokkos::subview(outputGradsA, team_member.league_rank(), Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL()); + basisRawPtr_device->getValues(gradsACell, inputPoints, OPERATOR_GRAD, team_member, team_member.team_scratch(scratch_space_level)); + }; + + //Get the required size of the scratch space per team and per thread. + int perThreadSpaceSize(0), perTeamSpaceSize(0); + basisPtr->getScratchSpaceSize(perTeamSpaceSize,perThreadSpaceSize,inputPoints, OPERATOR_GRAD); + teamPolicy.set_scratch_size(scratch_space_level, Kokkos::PerTeam(perTeamSpaceSize), Kokkos::PerThread(perThreadSpaceSize)); + + Kokkos::parallel_for (teamPolicy,functor); + } + } + + *outStream << "Computing values and gradients for " << npts << " points using high-level getValues function" <getValues(outputValuesB, inputPoints, OPERATOR_VALUE); + basisPtr->getValues(outputGradsB, inputPoints, OPERATOR_GRAD); + + *outStream << "Comparing values and gradients on host" <(); + for (size_t ic=0;ic tol) { + ++errorFlag; + std::cout << ", ic: " << ic << ", i: " << i << ", j: " << j + << ", val A: " << outputValuesA_Host(ic,i,j) + << ", val B: " << outputValuesB_Host(i,j) + << ", |diff|: " << diff + << ", tol: " << tol + << std::endl; + } + } + } + + { + // compare grads + const auto outputGradsA_Host = Kokkos::create_mirror_view(outputGradsA); Kokkos::deep_copy(outputGradsA_Host, outputGradsA); + const auto outputGradsB_Host = Kokkos::create_mirror_view(outputGradsB); Kokkos::deep_copy(outputGradsB_Host, outputGradsB); + + OutValueType diff = 0; + auto tol = epsilon(); + for (size_t ic=0;ic tol) { + ++errorFlag; + std::cout << ", ic: " << ic << ", i: " << i << ", j: " << j + << ", grads A: [" << outputGradsA_Host(ic,i,j,0) << ", " << outputGradsA_Host(ic,i,j,1) << ", " << outputGradsA_Host(ic,i,j,2) <<"]" + << ", grads B: [" << outputGradsB_Host(i,j,0) << ", " << outputGradsB_Host(i,j,1) << ", " << outputGradsB_Host(i,j,2) <<"]" + << ", |diff|: " << diff + << ", tol: " << tol + << std::endl; + } + } + } + } catch (std::exception &err) { + std::cout << "UNEXPECTED ERROR !!! ----------------------------------------------------------\n"; + std::cout << err.what() << '\n'; + std::cout << "-------------------------------------------------------------------------------" << "\n\n"; + errorFlag = -1000; + }; + + if (errorFlag != 0) + std::cout << "End Result: TEST FAILED\n"; + else + std::cout << "End Result: TEST PASSED\n"; + + return errorFlag; + } + } +} diff --git a/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_WEDGE_C2_FEM/CMakeLists.txt b/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_WEDGE_C2_FEM/CMakeLists.txt index 759b1bc6bc22..f82d6a4f7fc4 100644 --- a/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_WEDGE_C2_FEM/CMakeLists.txt +++ b/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_WEDGE_C2_FEM/CMakeLists.txt @@ -1,8 +1,16 @@ TRIBITS_INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}) + +# test +SET(Intrepid2_TEST_ETI_FILE "") +LIST(APPEND Intrepid2_TEST_ETI_FILE + "test_01" + "test_01_Serendipity") + # value types SET(Intrepid2_TEST_ETI_VALUETYPE_NAME "") SET(Intrepid2_TEST_ETI_VALUETYPE "") +SET(Intrepid2_TEST_ETI_SACADO "") LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE_NAME "DOUBLE") LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE "double") @@ -17,12 +25,80 @@ ENDIF() LIST(LENGTH Intrepid2_TEST_ETI_VALUETYPE_NAME ETI_VALUETYPE_COUNT) MATH(EXPR ETI_VALUETYPE_COUNT "${ETI_VALUETYPE_COUNT}-1") -# Host test -SET(Intrepid2_TEST_ETI_FILE "") -LIST(APPEND Intrepid2_TEST_ETI_FILE - "test_01" - "test_01_Serendipity") +# device +SET(Intrepid2_TEST_ETI_DEVICE_NAME "") +SET(Intrepid2_TEST_ETI_DEVICE "") +IF(Kokkos_ENABLE_SERIAL) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "Serial") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() +IF(Kokkos_ENABLE_OPENMP) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "OpenMP") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() +IF(Kokkos_ENABLE_CUDA) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "CUDA") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() +IF(Kokkos_ENABLE_HIP) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "HIP") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() + +LIST(LENGTH Intrepid2_TEST_ETI_DEVICE_NAME ETI_DEVICE_COUNT) +MATH(EXPR ETI_DEVICE_COUNT "${ETI_DEVICE_COUNT}-1") + +FOREACH(I RANGE ${ETI_DEVICE_COUNT}) + LIST(GET Intrepid2_TEST_ETI_DEVICE_NAME ${I} ETI_DEVICE_NAME) + LIST(GET Intrepid2_TEST_ETI_DEVICE ${I} ETI_DEVICE) + #MESSAGE(STATUS "Generating TEST HGRAD_WEDGE_C2_FEM for ${ETI_DEVICE_NAME} with ${ETI_DEVICE}") + FOREACH(J RANGE ${ETI_VALUETYPE_COUNT}) + LIST(GET Intrepid2_TEST_ETI_VALUETYPE_NAME ${J} ETI_VALUETYPE_NAME) + LIST(GET Intrepid2_TEST_ETI_VALUETYPE ${J} ETI_VALUETYPE) + LIST(GET Intrepid2_TEST_ETI_SACADO ${J} ETI_SACADO) + FOREACH(ETI_FILE IN LISTS Intrepid2_TEST_ETI_FILE) + SET(ETI_NAME "${ETI_FILE}_${ETI_DEVICE_NAME}_${ETI_VALUETYPE_NAME}") + MESSAGE(STATUS "Generating TEST: HGRAD_WEDGE_C2_FEM ${ETI_NAME}.cpp") + CONFIGURE_FILE(eti/${ETI_FILE}_ETI.in ${ETI_NAME}.cpp) + TRIBITS_ADD_EXECUTABLE_AND_TEST( + ${ETI_NAME} + SOURCES ${ETI_NAME}.cpp + ARGS PrintItAll + NUM_MPI_PROCS 1 + PASS_REGULAR_EXPRESSION "TEST PASSED" + ADD_DIR_TO_NAME + ) + + ENDFOREACH() + ENDFOREACH() +ENDFOREACH() + + + + +# test +SET(Intrepid2_TEST_ETI_FILE "test_02") + +# value types +SET(Intrepid2_TEST_ETI_VALUETYPE_NAME "") +SET(Intrepid2_TEST_ETI_VALUETYPE "") +SET(Intrepid2_TEST_ETI_SACADO "") + +LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE_NAME "DOUBLE_DOUBLE") +LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE "double,double") +LIST(APPEND Intrepid2_TEST_ETI_SACADO "0") + +IF (HAVE_INTREPID2_SACADO) + LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE_NAME "DFAD_DFAD") + LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE "Sacado::Fad::DFad,Sacado::Fad::DFad ") + LIST(APPEND Intrepid2_TEST_ETI_SACADO "33") +ENDIF() + +LIST(LENGTH Intrepid2_TEST_ETI_VALUETYPE_NAME ETI_VALUETYPE_COUNT) +MATH(EXPR ETI_VALUETYPE_COUNT "${ETI_VALUETYPE_COUNT}-1") + +# device SET(Intrepid2_TEST_ETI_DEVICE_NAME "") SET(Intrepid2_TEST_ETI_DEVICE "") IF(Kokkos_ENABLE_SERIAL) @@ -83,4 +159,3 @@ TRIBITS_COPY_FILES_TO_BINARY_DIR(HGRAD_WEDGE_C2TestDataCopy SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/testdata" DEST_DIR "${CMAKE_CURRENT_BINARY_DIR}/testdata" ) - diff --git a/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_WEDGE_C2_FEM/eti/test_02_ETI.in b/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_WEDGE_C2_FEM/eti/test_02_ETI.in new file mode 100644 index 000000000000..86de2ff60329 --- /dev/null +++ b/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_WEDGE_C2_FEM/eti/test_02_ETI.in @@ -0,0 +1,52 @@ +// @HEADER +// ***************************************************************************** +// Intrepid2 Package +// +// Copyright 2007 NTESS and the Intrepid2 contributors. +// SPDX-License-Identifier: BSD-3-Clause +// ***************************************************************************** +// @HEADER + +/** \file test_01.cpp + \brief Unit test of Intrepid2::Basis_HGRAD_WEDGE_C2_FEM team-level getValues. + \author Kyungjoo Kim +*/ + +#include "Kokkos_Core.hpp" + +#define ETI_SACADO @ETI_SACADO@ +#if (ETI_SACADO != 0) /// SACADO +#include "Kokkos_ViewFactory.hpp" +#include "Sacado.hpp" +#endif + +#if (ETI_SACADO == 0) /// double double +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__) +#elif (ETI_SACADO == 11 /* SFAD SFAD */ || ETI_SACADO == 33 /* DFAD DFAD */) +constexpr int num_deriv = 3; +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#elif (ETI_SACADO == 23) +constexpr int num_deriv = 3; +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#elif (ETI_SACADO == 20) +constexpr int num_deriv = 2; +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__) +#endif + +#include "test_02.hpp" + +int main(int argc, char *argv[]) { + + const bool verbose = (argc-1) > 0; + Kokkos::initialize(); + + Intrepid2::Test::HGRAD_WEDGE_C2_FEM_Test02<@ETI_VALUETYPE@,@ETI_DEVICE@>(verbose); + + Kokkos::finalize(); + return 0; +} + diff --git a/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_WEDGE_C2_FEM/test_02.hpp b/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_WEDGE_C2_FEM/test_02.hpp new file mode 100644 index 000000000000..35f0e18c3dbe --- /dev/null +++ b/packages/intrepid2/unit-test/Discretization/Basis/HGRAD_WEDGE_C2_FEM/test_02.hpp @@ -0,0 +1,182 @@ +// @HEADER +// ***************************************************************************** +// Intrepid2 Package +// +// Copyright 2007 NTESS and the Intrepid2 contributors. +// SPDX-License-Identifier: BSD-3-Clause +// ***************************************************************************** +// @HEADER + +/** \file test_02.hpp + \brief Unit tests for the Intrepid2::HGRAD_WEDGE_C2_FEM class. + \author Created by Kyungjoo Kim, Mauro Perego + */ + + +#include "Intrepid2_config.h" +#include "Kokkos_Random.hpp" +#ifdef HAVE_INTREPID2_DEBUG +#define INTREPID2_TEST_FOR_DEBUG_ABORT_OVERRIDE_TO_CONTINUE +#endif + +#include "Intrepid2_Types.hpp" +#include "Intrepid2_Utils.hpp" + +#include "Intrepid2_HGRAD_WEDGE_C2_FEM.hpp" +#include "packages/intrepid2/unit-test/Discretization/Basis/Setup.hpp" + +namespace Intrepid2 { + + namespace Test { + + template + int HGRAD_WEDGE_C2_FEM_Test02(const bool verbose) { + + //! Setup test output stream. + Teuchos::RCP outStream = setup_output_stream( + verbose, "HGRAD_WEDGE_C2_FEM, Test 2", {} + ); + + *outStream + << "\n" + << "===============================================================================\n" + << "| Testing Team-level Implemntation of getValues |\n" + << "===============================================================================\n"; + + using DeviceSpaceType = typename DeviceType::execution_space; + Kokkos::print_configuration(std::cout, false); + + int errorFlag = 0; + + try { + using BasisType = Basis_HGRAD_WEDGE_C2_FEM; + auto basisPtr = Teuchos::rcp(new BasisType()); + + const int ncells = 5, npts = 10, ndim = 3; + Kokkos::DynRankView ConstructWithLabelOutView(outputValuesA, ncells, basisPtr->getCardinality(), npts); + Kokkos::DynRankView ConstructWithLabelOutView(outputValuesB, basisPtr->getCardinality(), npts); + + Kokkos::DynRankView ConstructWithLabelOutView(outputGradsA, ncells, basisPtr->getCardinality(), npts, ndim); + Kokkos::DynRankView ConstructWithLabelOutView(outputGradsB, basisPtr->getCardinality(), npts, ndim); + Kokkos::DynRankView ConstructWithLabelPointView(point, 1); + + using ScalarType = typename ScalarTraits::scalar_type; + + Kokkos::View inputPointsViewToUseRandom("inputPoints", npts*ndim*get_dimension_scalar(point)); + auto vcprop = Kokkos::common_view_alloc_prop(point); + Kokkos::DynRankView inputPoints (Kokkos::view_wrap(inputPointsViewToUseRandom.data(), vcprop), npts, ndim); + + // random values between (0,1) + Kokkos::Random_XorShift64_Pool random(13718); + Kokkos::fill_random(inputPointsViewToUseRandom, random, 1.0); + + + *outStream << "Computing values and gradients for " << ncells << " cells and " << npts << " points using team-level getValues function" <(*basisPtr); + auto basisRawPtr_device = basisPtr_device.get(); + + int scratch_space_level =1; + const int vectorSize = getVectorSizeForHierarchicalParallelism(); + Kokkos::TeamPolicy teamPolicy(ncells, Kokkos::AUTO,vectorSize); + + { //compute values + auto functor = KOKKOS_LAMBDA (typename Kokkos::TeamPolicy::member_type team_member) { + auto valsACell = Kokkos::subview(outputValuesA, team_member.league_rank(), Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL()); + basisRawPtr_device->getValues(valsACell, inputPoints, OPERATOR_VALUE, team_member, team_member.team_scratch(scratch_space_level)); + }; + + //Get the required size of the scratch space per team and per thread. + int perThreadSpaceSize(0), perTeamSpaceSize(0); + basisPtr->getScratchSpaceSize(perTeamSpaceSize,perThreadSpaceSize,inputPoints, OPERATOR_VALUE); + teamPolicy.set_scratch_size(scratch_space_level, Kokkos::PerTeam(perTeamSpaceSize), Kokkos::PerThread(perThreadSpaceSize)); + + Kokkos::parallel_for (teamPolicy,functor); + } + + { //compute gradients + auto functor = KOKKOS_LAMBDA (typename Kokkos::TeamPolicy::member_type team_member) { + auto gradsACell = Kokkos::subview(outputGradsA, team_member.league_rank(), Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL()); + basisRawPtr_device->getValues(gradsACell, inputPoints, OPERATOR_GRAD, team_member, team_member.team_scratch(scratch_space_level)); + }; + + //Get the required size of the scratch space per team and per thread. + int perThreadSpaceSize(0), perTeamSpaceSize(0); + basisPtr->getScratchSpaceSize(perTeamSpaceSize,perThreadSpaceSize,inputPoints, OPERATOR_GRAD); + teamPolicy.set_scratch_size(scratch_space_level, Kokkos::PerTeam(perTeamSpaceSize), Kokkos::PerThread(perThreadSpaceSize)); + + Kokkos::parallel_for (teamPolicy,functor); + } + } + + *outStream << "Computing values and gradients for " << npts << " points using high-level getValues function" <getValues(outputValuesB, inputPoints, OPERATOR_VALUE); + basisPtr->getValues(outputGradsB, inputPoints, OPERATOR_GRAD); + + *outStream << "Comparing values and gradients on host" <(); + for (size_t ic=0;ic tol) { + ++errorFlag; + std::cout << ", ic: " << ic << ", i: " << i << ", j: " << j + << ", val A: " << outputValuesA_Host(ic,i,j) + << ", val B: " << outputValuesB_Host(i,j) + << ", |diff|: " << diff + << ", tol: " << tol + << std::endl; + } + } + } + + { + // compare grads + const auto outputGradsA_Host = Kokkos::create_mirror_view(outputGradsA); Kokkos::deep_copy(outputGradsA_Host, outputGradsA); + const auto outputGradsB_Host = Kokkos::create_mirror_view(outputGradsB); Kokkos::deep_copy(outputGradsB_Host, outputGradsB); + + OutValueType diff = 0; + auto tol = epsilon(); + for (size_t ic=0;ic tol) { + ++errorFlag; + std::cout << ", ic: " << ic << ", i: " << i << ", j: " << j + << ", grads A: [" << outputGradsA_Host(ic,i,j,0) << ", " << outputGradsA_Host(ic,i,j,1) << ", " << outputGradsA_Host(ic,i,j,2) <<"]" + << ", grads B: [" << outputGradsB_Host(i,j,0) << ", " << outputGradsB_Host(i,j,1) << ", " << outputGradsB_Host(i,j,2) <<"]" + << ", |diff|: " << diff + << ", tol: " << tol + << std::endl; + } + } + } + } catch (std::exception &err) { + std::cout << "UNEXPECTED ERROR !!! ----------------------------------------------------------\n"; + std::cout << err.what() << '\n'; + std::cout << "-------------------------------------------------------------------------------" << "\n\n"; + errorFlag = -1000; + }; + + if (errorFlag != 0) + std::cout << "End Result: TEST FAILED\n"; + else + std::cout << "End Result: TEST PASSED\n"; + + return errorFlag; + } + } +} diff --git a/packages/intrepid2/unit-test/Discretization/Basis/HVOL_HEX_Cn_FEM/CMakeLists.txt b/packages/intrepid2/unit-test/Discretization/Basis/HVOL_HEX_Cn_FEM/CMakeLists.txt index ebf2144cc03f..fa03caf7d02b 100644 --- a/packages/intrepid2/unit-test/Discretization/Basis/HVOL_HEX_Cn_FEM/CMakeLists.txt +++ b/packages/intrepid2/unit-test/Discretization/Basis/HVOL_HEX_Cn_FEM/CMakeLists.txt @@ -1,8 +1,13 @@ TRIBITS_INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}) + +# test +SET(Intrepid2_TEST_ETI_FILE "test_01") + # value types SET(Intrepid2_TEST_ETI_VALUETYPE_NAME "") SET(Intrepid2_TEST_ETI_VALUETYPE "") +SET(Intrepid2_TEST_ETI_SACADO "") LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE_NAME "DOUBLE_DOUBLE") LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE "double,double") @@ -32,9 +37,80 @@ ENDIF() LIST(LENGTH Intrepid2_TEST_ETI_VALUETYPE_NAME ETI_VALUETYPE_COUNT) MATH(EXPR ETI_VALUETYPE_COUNT "${ETI_VALUETYPE_COUNT}-1") +# device +SET(Intrepid2_TEST_ETI_DEVICE_NAME "") +SET(Intrepid2_TEST_ETI_DEVICE "") +IF(Kokkos_ENABLE_SERIAL) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "Serial") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() +IF(Kokkos_ENABLE_OPENMP) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "OpenMP") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() +IF(Kokkos_ENABLE_CUDA) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "CUDA") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() +IF(Kokkos_ENABLE_HIP) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "HIP") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() + +LIST(LENGTH Intrepid2_TEST_ETI_DEVICE_NAME ETI_DEVICE_COUNT) +MATH(EXPR ETI_DEVICE_COUNT "${ETI_DEVICE_COUNT}-1") + +FOREACH(I RANGE ${ETI_DEVICE_COUNT}) + LIST(GET Intrepid2_TEST_ETI_DEVICE_NAME ${I} ETI_DEVICE_NAME) + LIST(GET Intrepid2_TEST_ETI_DEVICE ${I} ETI_DEVICE) + #MESSAGE(STATUS "Generating TEST HVOL_HEX_Cn_FEM for ${ETI_DEVICE_NAME} with ${ETI_DEVICE}") + FOREACH(J RANGE ${ETI_VALUETYPE_COUNT}) + LIST(GET Intrepid2_TEST_ETI_VALUETYPE_NAME ${J} ETI_VALUETYPE_NAME) + LIST(GET Intrepid2_TEST_ETI_VALUETYPE ${J} ETI_VALUETYPE) + LIST(GET Intrepid2_TEST_ETI_SACADO ${J} ETI_SACADO) + FOREACH(ETI_FILE IN LISTS Intrepid2_TEST_ETI_FILE) + SET(ETI_NAME "${ETI_FILE}_${ETI_DEVICE_NAME}_${ETI_VALUETYPE_NAME}") + MESSAGE(STATUS "Generating TEST: HVOL_HEX_Cn_FEM ${ETI_NAME}.cpp") + CONFIGURE_FILE(eti/${ETI_FILE}_ETI.in ${ETI_NAME}.cpp) + + TRIBITS_ADD_EXECUTABLE_AND_TEST( + ${ETI_NAME} + SOURCES ${ETI_NAME}.cpp + ARGS PrintItAll + NUM_MPI_PROCS 1 + PASS_REGULAR_EXPRESSION "TEST PASSED" + ADD_DIR_TO_NAME + ) + + ENDFOREACH() + ENDFOREACH() +ENDFOREACH() + + + + # test -SET(Intrepid2_TEST_ETI_FILE "test_01") +SET(Intrepid2_TEST_ETI_FILE "test_02") +# value types +SET(Intrepid2_TEST_ETI_VALUETYPE_NAME "") +SET(Intrepid2_TEST_ETI_VALUETYPE "") +SET(Intrepid2_TEST_ETI_SACADO "") + +LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE_NAME "DOUBLE_DOUBLE") +LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE "double,double") +LIST(APPEND Intrepid2_TEST_ETI_SACADO "0") + +IF (HAVE_INTREPID2_SACADO) + LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE_NAME "DFAD_DFAD") + LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE "Sacado::Fad::DFad,Sacado::Fad::DFad ") + LIST(APPEND Intrepid2_TEST_ETI_SACADO "33") +ENDIF() + +LIST(LENGTH Intrepid2_TEST_ETI_VALUETYPE_NAME ETI_VALUETYPE_COUNT) +MATH(EXPR ETI_VALUETYPE_COUNT "${ETI_VALUETYPE_COUNT}-1") + +# device SET(Intrepid2_TEST_ETI_DEVICE_NAME "") SET(Intrepid2_TEST_ETI_DEVICE "") IF(Kokkos_ENABLE_SERIAL) @@ -60,7 +136,6 @@ MATH(EXPR ETI_DEVICE_COUNT "${ETI_DEVICE_COUNT}-1") FOREACH(I RANGE ${ETI_DEVICE_COUNT}) LIST(GET Intrepid2_TEST_ETI_DEVICE_NAME ${I} ETI_DEVICE_NAME) LIST(GET Intrepid2_TEST_ETI_DEVICE ${I} ETI_DEVICE) - #MESSAGE(STATUS "Generating TEST HVOL_HEX_Cn_FEM for ${ETI_DEVICE_NAME} with ${ETI_DEVICE}") FOREACH(J RANGE ${ETI_VALUETYPE_COUNT}) LIST(GET Intrepid2_TEST_ETI_VALUETYPE_NAME ${J} ETI_VALUETYPE_NAME) LIST(GET Intrepid2_TEST_ETI_VALUETYPE ${J} ETI_VALUETYPE) diff --git a/packages/intrepid2/unit-test/Discretization/Basis/HVOL_HEX_Cn_FEM/eti/test_02_ETI.in b/packages/intrepid2/unit-test/Discretization/Basis/HVOL_HEX_Cn_FEM/eti/test_02_ETI.in new file mode 100644 index 000000000000..766fea986506 --- /dev/null +++ b/packages/intrepid2/unit-test/Discretization/Basis/HVOL_HEX_Cn_FEM/eti/test_02_ETI.in @@ -0,0 +1,52 @@ +// @HEADER +// ***************************************************************************** +// Intrepid2 Package +// +// Copyright 2007 NTESS and the Intrepid2 contributors. +// SPDX-License-Identifier: BSD-3-Clause +// ***************************************************************************** +// @HEADER + +/** \file test_02.cpp + \brief Unit test of Intrepid2::Basis_HVOL_HEX_Cn_FEM team-level getValues. + \author Kyungjoo Kim +*/ + +#include "Kokkos_Core.hpp" + +#define ETI_SACADO @ETI_SACADO@ +#if (ETI_SACADO != 0) /// SACADO +#include "Kokkos_ViewFactory.hpp" +#include "Sacado.hpp" +#endif + +#if (ETI_SACADO == 0) /// double double +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__) +#elif (ETI_SACADO == 11 /* SFAD SFAD */ || ETI_SACADO == 33 /* DFAD DFAD */) +constexpr int num_deriv = 3; +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#elif (ETI_SACADO == 23) +constexpr int num_deriv = 3; +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#elif (ETI_SACADO == 20) +constexpr int num_deriv = 2; +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__) +#endif + +#include "test_02.hpp" + +int main(int argc, char *argv[]) { + + const bool verbose = (argc-1) > 0; + Kokkos::initialize(); + + Intrepid2::Test::HVOL_HEX_Cn_FEM_Test02<@ETI_VALUETYPE@,@ETI_DEVICE@>(verbose); + + Kokkos::finalize(); + return 0; +} + diff --git a/packages/intrepid2/unit-test/Discretization/Basis/HVOL_HEX_Cn_FEM/test_02.hpp b/packages/intrepid2/unit-test/Discretization/Basis/HVOL_HEX_Cn_FEM/test_02.hpp new file mode 100644 index 000000000000..115a371bc82a --- /dev/null +++ b/packages/intrepid2/unit-test/Discretization/Basis/HVOL_HEX_Cn_FEM/test_02.hpp @@ -0,0 +1,144 @@ +// @HEADER +// ***************************************************************************** +// Intrepid2 Package +// +// Copyright 2007 NTESS and the Intrepid2 contributors. +// SPDX-License-Identifier: BSD-3-Clause +// ***************************************************************************** +// @HEADER + +/** \file test_02.hpp + \brief Unit tests for the Intrepid2::HVOL_HEX_Cn_FEM class. + \author Created by Kyungjoo Kim, Mauro Perego + */ + + +#include "Intrepid2_config.h" +#include "Kokkos_Random.hpp" +#ifdef HAVE_INTREPID2_DEBUG +#define INTREPID2_TEST_FOR_DEBUG_ABORT_OVERRIDE_TO_CONTINUE +#endif + +#include "Intrepid2_Types.hpp" +#include "Intrepid2_Utils.hpp" + +#include "Intrepid2_HVOL_HEX_Cn_FEM.hpp" +#include "packages/intrepid2/unit-test/Discretization/Basis/Setup.hpp" + +namespace Intrepid2 { + + namespace Test { + + // This test evaluates the basis functions at a set of points on a batch of cells using the team-level getValues, + // and compares the results with those obtained using the classic getValues function. + template + int HVOL_HEX_Cn_FEM_Test02(const bool verbose) { + + //! Setup test output stream. + Teuchos::RCP outStream = setup_output_stream( + verbose, "HVOL_HEX_Cn_FEM, Test 2", {} + ); + + *outStream + << "\n" + << "===============================================================================\n" + << "| Testing Team-level Implemntation of getValues |\n" + << "===============================================================================\n"; + + using DeviceSpaceType = typename DeviceType::execution_space; + Kokkos::print_configuration(std::cout, false); + + int errorFlag = 0; + constexpr int maxOrder = 9; + try { + for (int order=1;order<=maxOrder;++order) { + using BasisType = Basis_HVOL_HEX_Cn_FEM; + auto basisPtr = Teuchos::rcp(new BasisType(order)); + + const int ncells = 5, npts = 10, ndim = 3; + Kokkos::DynRankView ConstructWithLabelOutView(outputValuesA, ncells, basisPtr->getCardinality(), npts); + Kokkos::DynRankView ConstructWithLabelOutView(outputValuesB, basisPtr->getCardinality(), npts); + Kokkos::DynRankView ConstructWithLabelPointView(point, 1); + + using ScalarType = typename ScalarTraits::scalar_type; + + Kokkos::View inputPointsViewToUseRandom("inputPoints", npts*ndim*get_dimension_scalar(point)); + auto vcprop = Kokkos::common_view_alloc_prop(point); + Kokkos::DynRankView inputPoints (Kokkos::view_wrap(inputPointsViewToUseRandom.data(), vcprop), npts, ndim); + + // random values between (0,1) + Kokkos::Random_XorShift64_Pool random(13718); + Kokkos::fill_random(inputPointsViewToUseRandom, random, 1.0); + + + *outStream << "Order: " << order << ": Computing values for " << ncells << " cells and " << npts << " points using team-level getValues function" <(*basisPtr); + auto basisRawPtr_device = basisPtr_device.get(); + + int scratch_space_level =1; + const int vectorSize = getVectorSizeForHierarchicalParallelism(); + Kokkos::TeamPolicy teamPolicy(ncells, Kokkos::AUTO,vectorSize); + + { //compute values + auto functor = KOKKOS_LAMBDA (typename Kokkos::TeamPolicy::member_type team_member) { + auto valsACell = Kokkos::subview(outputValuesA, team_member.league_rank(), Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL()); + basisRawPtr_device->getValues(valsACell, inputPoints, OPERATOR_VALUE, team_member, team_member.team_scratch(scratch_space_level)); + }; + + //Get the required size of the scratch space per team and per thread. + int perThreadSpaceSize(0), perTeamSpaceSize(0); + basisPtr->getScratchSpaceSize(perTeamSpaceSize,perThreadSpaceSize,inputPoints, OPERATOR_VALUE); + teamPolicy.set_scratch_size(scratch_space_level, Kokkos::PerTeam(perTeamSpaceSize), Kokkos::PerThread(perThreadSpaceSize)); + + Kokkos::parallel_for (teamPolicy,functor); + } + } + + *outStream << "Order: " << order << ": Computing values for " << npts << " points using high-level getValues function" <getValues(outputValuesB, inputPoints, OPERATOR_VALUE); + + *outStream << "Order: " << order << ": Comparing values on host" <(); + for (size_t ic=0;ic tol) { + ++errorFlag; + std::cout << " order: " << order + << ", ic: " << ic << ", i: " << i << ", j: " << j + << ", val A: " << outputValuesA_Host(ic,i,j) + << ", val B: " << outputValuesB_Host(i,j) + << ", |diff|: " << diff + << ", tol: " << tol + << std::endl; + } + } + } + } + } catch (std::exception &err) { + std::cout << "UNEXPECTED ERROR !!! ----------------------------------------------------------\n"; + std::cout << err.what() << '\n'; + std::cout << "-------------------------------------------------------------------------------" << "\n\n"; + errorFlag = -1000; + }; + + if (errorFlag != 0) + std::cout << "End Result: TEST FAILED\n"; + else + std::cout << "End Result: TEST PASSED\n"; + + return errorFlag; + } + } +} diff --git a/packages/intrepid2/unit-test/Discretization/Basis/HVOL_LINE_Cn_FEM/CMakeLists.txt b/packages/intrepid2/unit-test/Discretization/Basis/HVOL_LINE_Cn_FEM/CMakeLists.txt index f5caa97dcaf1..24d663415a74 100644 --- a/packages/intrepid2/unit-test/Discretization/Basis/HVOL_LINE_Cn_FEM/CMakeLists.txt +++ b/packages/intrepid2/unit-test/Discretization/Basis/HVOL_LINE_Cn_FEM/CMakeLists.txt @@ -1,8 +1,13 @@ TRIBITS_INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}) + +# test +SET(Intrepid2_TEST_ETI_FILE "test_01") + # value types SET(Intrepid2_TEST_ETI_VALUETYPE_NAME "") SET(Intrepid2_TEST_ETI_VALUETYPE "") +SET(Intrepid2_TEST_ETI_SACADO "") LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE_NAME "DOUBLE_DOUBLE") LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE "double,double") @@ -32,9 +37,80 @@ ENDIF() LIST(LENGTH Intrepid2_TEST_ETI_VALUETYPE_NAME ETI_VALUETYPE_COUNT) MATH(EXPR ETI_VALUETYPE_COUNT "${ETI_VALUETYPE_COUNT}-1") +# device +SET(Intrepid2_TEST_ETI_DEVICE_NAME "") +SET(Intrepid2_TEST_ETI_DEVICE "") +IF(Kokkos_ENABLE_SERIAL) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "Serial") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() +IF(Kokkos_ENABLE_OPENMP) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "OpenMP") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() +IF(Kokkos_ENABLE_CUDA) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "CUDA") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() +IF(Kokkos_ENABLE_HIP) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "HIP") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() + +LIST(LENGTH Intrepid2_TEST_ETI_DEVICE_NAME ETI_DEVICE_COUNT) +MATH(EXPR ETI_DEVICE_COUNT "${ETI_DEVICE_COUNT}-1") + +FOREACH(I RANGE ${ETI_DEVICE_COUNT}) + LIST(GET Intrepid2_TEST_ETI_DEVICE_NAME ${I} ETI_DEVICE_NAME) + LIST(GET Intrepid2_TEST_ETI_DEVICE ${I} ETI_DEVICE) + #MESSAGE(STATUS "Generating TEST HVOL_LINE_Cn_FEM for ${ETI_DEVICE_NAME} with ${ETI_DEVICE}") + FOREACH(J RANGE ${ETI_VALUETYPE_COUNT}) + LIST(GET Intrepid2_TEST_ETI_VALUETYPE_NAME ${J} ETI_VALUETYPE_NAME) + LIST(GET Intrepid2_TEST_ETI_VALUETYPE ${J} ETI_VALUETYPE) + LIST(GET Intrepid2_TEST_ETI_SACADO ${J} ETI_SACADO) + FOREACH(ETI_FILE IN LISTS Intrepid2_TEST_ETI_FILE) + SET(ETI_NAME "${ETI_FILE}_${ETI_DEVICE_NAME}_${ETI_VALUETYPE_NAME}") + MESSAGE(STATUS "Generating TEST: HVOL_LINE_Cn_FEM ${ETI_NAME}.cpp") + CONFIGURE_FILE(eti/${ETI_FILE}_ETI.in ${ETI_NAME}.cpp) + + TRIBITS_ADD_EXECUTABLE_AND_TEST( + ${ETI_NAME} + SOURCES ${ETI_NAME}.cpp + ARGS PrintItAll + NUM_MPI_PROCS 1 + PASS_REGULAR_EXPRESSION "TEST PASSED" + ADD_DIR_TO_NAME + ) + + ENDFOREACH() + ENDFOREACH() +ENDFOREACH() + + + + # test -SET(Intrepid2_TEST_ETI_FILE "test_01") +SET(Intrepid2_TEST_ETI_FILE "test_02") +# value types +SET(Intrepid2_TEST_ETI_VALUETYPE_NAME "") +SET(Intrepid2_TEST_ETI_VALUETYPE "") +SET(Intrepid2_TEST_ETI_SACADO "") + +LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE_NAME "DOUBLE_DOUBLE") +LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE "double,double") +LIST(APPEND Intrepid2_TEST_ETI_SACADO "0") + +IF (HAVE_INTREPID2_SACADO) + LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE_NAME "DFAD_DFAD") + LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE "Sacado::Fad::DFad,Sacado::Fad::DFad ") + LIST(APPEND Intrepid2_TEST_ETI_SACADO "33") +ENDIF() + +LIST(LENGTH Intrepid2_TEST_ETI_VALUETYPE_NAME ETI_VALUETYPE_COUNT) +MATH(EXPR ETI_VALUETYPE_COUNT "${ETI_VALUETYPE_COUNT}-1") + +# device SET(Intrepid2_TEST_ETI_DEVICE_NAME "") SET(Intrepid2_TEST_ETI_DEVICE "") IF(Kokkos_ENABLE_SERIAL) @@ -60,7 +136,6 @@ MATH(EXPR ETI_DEVICE_COUNT "${ETI_DEVICE_COUNT}-1") FOREACH(I RANGE ${ETI_DEVICE_COUNT}) LIST(GET Intrepid2_TEST_ETI_DEVICE_NAME ${I} ETI_DEVICE_NAME) LIST(GET Intrepid2_TEST_ETI_DEVICE ${I} ETI_DEVICE) - #MESSAGE(STATUS "Generating TEST HVOL_LINE_Cn_FEM for ${ETI_DEVICE_NAME} with ${ETI_DEVICE}") FOREACH(J RANGE ${ETI_VALUETYPE_COUNT}) LIST(GET Intrepid2_TEST_ETI_VALUETYPE_NAME ${J} ETI_VALUETYPE_NAME) LIST(GET Intrepid2_TEST_ETI_VALUETYPE ${J} ETI_VALUETYPE) diff --git a/packages/intrepid2/unit-test/Discretization/Basis/HVOL_LINE_Cn_FEM/eti/test_02_ETI.in b/packages/intrepid2/unit-test/Discretization/Basis/HVOL_LINE_Cn_FEM/eti/test_02_ETI.in new file mode 100644 index 000000000000..a6f42f8ba7b8 --- /dev/null +++ b/packages/intrepid2/unit-test/Discretization/Basis/HVOL_LINE_Cn_FEM/eti/test_02_ETI.in @@ -0,0 +1,52 @@ +// @HEADER +// ***************************************************************************** +// Intrepid2 Package +// +// Copyright 2007 NTESS and the Intrepid2 contributors. +// SPDX-License-Identifier: BSD-3-Clause +// ***************************************************************************** +// @HEADER + +/** \file test_02.cpp + \brief Unit test of Intrepid2::Basis_HVOL_LINE_Cn_FEM team-level getValues. + \author Kyungjoo Kim +*/ + +#include "Kokkos_Core.hpp" + +#define ETI_SACADO @ETI_SACADO@ +#if (ETI_SACADO != 0) /// SACADO +#include "Kokkos_ViewFactory.hpp" +#include "Sacado.hpp" +#endif + +#if (ETI_SACADO == 0) /// double double +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__) +#elif (ETI_SACADO == 11 /* SFAD SFAD */ || ETI_SACADO == 33 /* DFAD DFAD */) +constexpr int num_deriv = 3; +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#elif (ETI_SACADO == 23) +constexpr int num_deriv = 3; +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#elif (ETI_SACADO == 20) +constexpr int num_deriv = 2; +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__) +#endif + +#include "test_02.hpp" + +int main(int argc, char *argv[]) { + + const bool verbose = (argc-1) > 0; + Kokkos::initialize(); + + Intrepid2::Test::HVOL_LINE_Cn_FEM_Test02<@ETI_VALUETYPE@,@ETI_DEVICE@>(verbose); + + Kokkos::finalize(); + return 0; +} + diff --git a/packages/intrepid2/unit-test/Discretization/Basis/HVOL_LINE_Cn_FEM/test_02.hpp b/packages/intrepid2/unit-test/Discretization/Basis/HVOL_LINE_Cn_FEM/test_02.hpp new file mode 100644 index 000000000000..c71f401eda49 --- /dev/null +++ b/packages/intrepid2/unit-test/Discretization/Basis/HVOL_LINE_Cn_FEM/test_02.hpp @@ -0,0 +1,144 @@ +// @HEADER +// ***************************************************************************** +// Intrepid2 Package +// +// Copyright 2007 NTESS and the Intrepid2 contributors. +// SPDX-License-Identifier: BSD-3-Clause +// ***************************************************************************** +// @HEADER + +/** \file test_02.hpp + \brief Unit tests for the Intrepid2::HVOL_LINE_Cn_FEM class. + \author Created by Kyungjoo Kim, Mauro Perego + */ + + +#include "Intrepid2_config.h" +#include "Kokkos_Random.hpp" +#ifdef HAVE_INTREPID2_DEBUG +#define INTREPID2_TEST_FOR_DEBUG_ABORT_OVERRIDE_TO_CONTINUE +#endif + +#include "Intrepid2_Types.hpp" +#include "Intrepid2_Utils.hpp" + +#include "Intrepid2_HVOL_LINE_Cn_FEM.hpp" +#include "packages/intrepid2/unit-test/Discretization/Basis/Setup.hpp" + +namespace Intrepid2 { + + namespace Test { + + // This test evaluates the basis functions at a set of points on a batch of cells using the team-level getValues, + // and compares the results with those obtained using the classic getValues function. + template + int HVOL_LINE_Cn_FEM_Test02(const bool verbose) { + + //! Setup test output stream. + Teuchos::RCP outStream = setup_output_stream( + verbose, "HVOL_LINE_Cn_FEM, Test 2", {} + ); + + *outStream + << "\n" + << "===============================================================================\n" + << "| Testing Team-level Implemntation of getValues |\n" + << "===============================================================================\n"; + + using DeviceSpaceType = typename DeviceType::execution_space; + Kokkos::print_configuration(std::cout, false); + + int errorFlag = 0; + constexpr int maxOrder = 9; + try { + for (int order=1;order<=maxOrder;++order) { + using BasisType = Basis_HVOL_LINE_Cn_FEM; + auto basisPtr = Teuchos::rcp(new BasisType(order)); + + const int ncells = 5, npts = 10, ndim = 1; + Kokkos::DynRankView ConstructWithLabelOutView(outputValuesA, ncells, basisPtr->getCardinality(), npts); + Kokkos::DynRankView ConstructWithLabelOutView(outputValuesB, basisPtr->getCardinality(), npts); + Kokkos::DynRankView ConstructWithLabelPointView(point, 1); + + using ScalarType = typename ScalarTraits::scalar_type; + + Kokkos::View inputPointsViewToUseRandom("inputPoints", npts*ndim*get_dimension_scalar(point)); + auto vcprop = Kokkos::common_view_alloc_prop(point); + Kokkos::DynRankView inputPoints (Kokkos::view_wrap(inputPointsViewToUseRandom.data(), vcprop), npts, ndim); + + // random values between (0,1) + Kokkos::Random_XorShift64_Pool random(13718); + Kokkos::fill_random(inputPointsViewToUseRandom, random, 1.0); + + + *outStream << "Order: " << order << ": Computing values for " << ncells << " cells and " << npts << " points using team-level getValues function" <(*basisPtr); + auto basisRawPtr_device = basisPtr_device.get(); + + int scratch_space_level =1; + const int vectorSize = getVectorSizeForHierarchicalParallelism(); + Kokkos::TeamPolicy teamPolicy(ncells, Kokkos::AUTO,vectorSize); + + { //compute values + auto functor = KOKKOS_LAMBDA (typename Kokkos::TeamPolicy::member_type team_member) { + auto valsACell = Kokkos::subview(outputValuesA, team_member.league_rank(), Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL()); + basisRawPtr_device->getValues(valsACell, inputPoints, OPERATOR_VALUE, team_member, team_member.team_scratch(scratch_space_level)); + }; + + //Get the required size of the scratch space per team and per thread. + int perThreadSpaceSize(0), perTeamSpaceSize(0); + basisPtr->getScratchSpaceSize(perTeamSpaceSize,perThreadSpaceSize,inputPoints, OPERATOR_VALUE); + teamPolicy.set_scratch_size(scratch_space_level, Kokkos::PerTeam(perTeamSpaceSize), Kokkos::PerThread(perThreadSpaceSize)); + + Kokkos::parallel_for (teamPolicy,functor); + } + } + + *outStream << "Order: " << order << ": Computing values for " << npts << " points using high-level getValues function" <getValues(outputValuesB, inputPoints, OPERATOR_VALUE); + + *outStream << "Order: " << order << ": Comparing values on host" <(); + for (size_t ic=0;ic tol) { + ++errorFlag; + std::cout << " order: " << order + << ", ic: " << ic << ", i: " << i << ", j: " << j + << ", val A: " << outputValuesA_Host(ic,i,j) + << ", val B: " << outputValuesB_Host(i,j) + << ", |diff|: " << diff + << ", tol: " << tol + << std::endl; + } + } + } + } + } catch (std::exception &err) { + std::cout << "UNEXPECTED ERROR !!! ----------------------------------------------------------\n"; + std::cout << err.what() << '\n'; + std::cout << "-------------------------------------------------------------------------------" << "\n\n"; + errorFlag = -1000; + }; + + if (errorFlag != 0) + std::cout << "End Result: TEST FAILED\n"; + else + std::cout << "End Result: TEST PASSED\n"; + + return errorFlag; + } + } +} diff --git a/packages/intrepid2/unit-test/Discretization/Basis/HVOL_QUAD_Cn_FEM/CMakeLists.txt b/packages/intrepid2/unit-test/Discretization/Basis/HVOL_QUAD_Cn_FEM/CMakeLists.txt index 769157316641..aedb132dcc82 100644 --- a/packages/intrepid2/unit-test/Discretization/Basis/HVOL_QUAD_Cn_FEM/CMakeLists.txt +++ b/packages/intrepid2/unit-test/Discretization/Basis/HVOL_QUAD_Cn_FEM/CMakeLists.txt @@ -1,8 +1,13 @@ TRIBITS_INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}) + +# test +SET(Intrepid2_TEST_ETI_FILE "test_01") + # value types SET(Intrepid2_TEST_ETI_VALUETYPE_NAME "") SET(Intrepid2_TEST_ETI_VALUETYPE "") +SET(Intrepid2_TEST_ETI_SACADO "") LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE_NAME "DOUBLE_DOUBLE") LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE "double,double") @@ -32,9 +37,80 @@ ENDIF() LIST(LENGTH Intrepid2_TEST_ETI_VALUETYPE_NAME ETI_VALUETYPE_COUNT) MATH(EXPR ETI_VALUETYPE_COUNT "${ETI_VALUETYPE_COUNT}-1") +# device +SET(Intrepid2_TEST_ETI_DEVICE_NAME "") +SET(Intrepid2_TEST_ETI_DEVICE "") +IF(Kokkos_ENABLE_SERIAL) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "Serial") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() +IF(Kokkos_ENABLE_OPENMP) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "OpenMP") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() +IF(Kokkos_ENABLE_CUDA) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "CUDA") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() +IF(Kokkos_ENABLE_HIP) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "HIP") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() + +LIST(LENGTH Intrepid2_TEST_ETI_DEVICE_NAME ETI_DEVICE_COUNT) +MATH(EXPR ETI_DEVICE_COUNT "${ETI_DEVICE_COUNT}-1") + +FOREACH(I RANGE ${ETI_DEVICE_COUNT}) + LIST(GET Intrepid2_TEST_ETI_DEVICE_NAME ${I} ETI_DEVICE_NAME) + LIST(GET Intrepid2_TEST_ETI_DEVICE ${I} ETI_DEVICE) + #MESSAGE(STATUS "Generating TEST HVOL_QUAD_Cn_FEM for ${ETI_DEVICE_NAME} with ${ETI_DEVICE}") + FOREACH(J RANGE ${ETI_VALUETYPE_COUNT}) + LIST(GET Intrepid2_TEST_ETI_VALUETYPE_NAME ${J} ETI_VALUETYPE_NAME) + LIST(GET Intrepid2_TEST_ETI_VALUETYPE ${J} ETI_VALUETYPE) + LIST(GET Intrepid2_TEST_ETI_SACADO ${J} ETI_SACADO) + FOREACH(ETI_FILE IN LISTS Intrepid2_TEST_ETI_FILE) + SET(ETI_NAME "${ETI_FILE}_${ETI_DEVICE_NAME}_${ETI_VALUETYPE_NAME}") + MESSAGE(STATUS "Generating TEST: HVOL_QUAD_Cn_FEM ${ETI_NAME}.cpp") + CONFIGURE_FILE(eti/${ETI_FILE}_ETI.in ${ETI_NAME}.cpp) + + TRIBITS_ADD_EXECUTABLE_AND_TEST( + ${ETI_NAME} + SOURCES ${ETI_NAME}.cpp + ARGS PrintItAll + NUM_MPI_PROCS 1 + PASS_REGULAR_EXPRESSION "TEST PASSED" + ADD_DIR_TO_NAME + ) + + ENDFOREACH() + ENDFOREACH() +ENDFOREACH() + + + + # test -SET(Intrepid2_TEST_ETI_FILE "test_01") +SET(Intrepid2_TEST_ETI_FILE "test_02") +# value types +SET(Intrepid2_TEST_ETI_VALUETYPE_NAME "") +SET(Intrepid2_TEST_ETI_VALUETYPE "") +SET(Intrepid2_TEST_ETI_SACADO "") + +LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE_NAME "DOUBLE_DOUBLE") +LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE "double,double") +LIST(APPEND Intrepid2_TEST_ETI_SACADO "0") + +IF (HAVE_INTREPID2_SACADO) + LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE_NAME "DFAD_DFAD") + LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE "Sacado::Fad::DFad,Sacado::Fad::DFad ") + LIST(APPEND Intrepid2_TEST_ETI_SACADO "33") +ENDIF() + +LIST(LENGTH Intrepid2_TEST_ETI_VALUETYPE_NAME ETI_VALUETYPE_COUNT) +MATH(EXPR ETI_VALUETYPE_COUNT "${ETI_VALUETYPE_COUNT}-1") + +# device SET(Intrepid2_TEST_ETI_DEVICE_NAME "") SET(Intrepid2_TEST_ETI_DEVICE "") IF(Kokkos_ENABLE_SERIAL) @@ -60,7 +136,6 @@ MATH(EXPR ETI_DEVICE_COUNT "${ETI_DEVICE_COUNT}-1") FOREACH(I RANGE ${ETI_DEVICE_COUNT}) LIST(GET Intrepid2_TEST_ETI_DEVICE_NAME ${I} ETI_DEVICE_NAME) LIST(GET Intrepid2_TEST_ETI_DEVICE ${I} ETI_DEVICE) - #MESSAGE(STATUS "Generating TEST HVOL_QUAD_Cn_FEM for ${ETI_DEVICE_NAME} with ${ETI_DEVICE}") FOREACH(J RANGE ${ETI_VALUETYPE_COUNT}) LIST(GET Intrepid2_TEST_ETI_VALUETYPE_NAME ${J} ETI_VALUETYPE_NAME) LIST(GET Intrepid2_TEST_ETI_VALUETYPE ${J} ETI_VALUETYPE) diff --git a/packages/intrepid2/unit-test/Discretization/Basis/HVOL_QUAD_Cn_FEM/eti/test_02_ETI.in b/packages/intrepid2/unit-test/Discretization/Basis/HVOL_QUAD_Cn_FEM/eti/test_02_ETI.in new file mode 100644 index 000000000000..1c01cd896135 --- /dev/null +++ b/packages/intrepid2/unit-test/Discretization/Basis/HVOL_QUAD_Cn_FEM/eti/test_02_ETI.in @@ -0,0 +1,52 @@ +// @HEADER +// ***************************************************************************** +// Intrepid2 Package +// +// Copyright 2007 NTESS and the Intrepid2 contributors. +// SPDX-License-Identifier: BSD-3-Clause +// ***************************************************************************** +// @HEADER + +/** \file test_02.cpp + \brief Unit test of Intrepid2::Basis_HVOL_QUAD_Cn_FEM team-level getValues. + \author Kyungjoo Kim +*/ + +#include "Kokkos_Core.hpp" + +#define ETI_SACADO @ETI_SACADO@ +#if (ETI_SACADO != 0) /// SACADO +#include "Kokkos_ViewFactory.hpp" +#include "Sacado.hpp" +#endif + +#if (ETI_SACADO == 0) /// double double +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__) +#elif (ETI_SACADO == 11 /* SFAD SFAD */ || ETI_SACADO == 33 /* DFAD DFAD */) +constexpr int num_deriv = 3; +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#elif (ETI_SACADO == 23) +constexpr int num_deriv = 3; +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#elif (ETI_SACADO == 20) +constexpr int num_deriv = 2; +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__) +#endif + +#include "test_02.hpp" + +int main(int argc, char *argv[]) { + + const bool verbose = (argc-1) > 0; + Kokkos::initialize(); + + Intrepid2::Test::HVOL_QUAD_Cn_FEM_Test02<@ETI_VALUETYPE@,@ETI_DEVICE@>(verbose); + + Kokkos::finalize(); + return 0; +} + diff --git a/packages/intrepid2/unit-test/Discretization/Basis/HVOL_QUAD_Cn_FEM/test_02.hpp b/packages/intrepid2/unit-test/Discretization/Basis/HVOL_QUAD_Cn_FEM/test_02.hpp new file mode 100644 index 000000000000..044f8fad53a0 --- /dev/null +++ b/packages/intrepid2/unit-test/Discretization/Basis/HVOL_QUAD_Cn_FEM/test_02.hpp @@ -0,0 +1,144 @@ +// @HEADER +// ***************************************************************************** +// Intrepid2 Package +// +// Copyright 2007 NTESS and the Intrepid2 contributors. +// SPDX-License-Identifier: BSD-3-Clause +// ***************************************************************************** +// @HEADER + +/** \file test_02.hpp + \brief Unit tests for the Intrepid2::HVOL_QUAD_Cn_FEM class. + \author Created by Kyungjoo Kim, Mauro Perego + */ + + +#include "Intrepid2_config.h" +#include "Kokkos_Random.hpp" +#ifdef HAVE_INTREPID2_DEBUG +#define INTREPID2_TEST_FOR_DEBUG_ABORT_OVERRIDE_TO_CONTINUE +#endif + +#include "Intrepid2_Types.hpp" +#include "Intrepid2_Utils.hpp" + +#include "Intrepid2_HVOL_QUAD_Cn_FEM.hpp" +#include "packages/intrepid2/unit-test/Discretization/Basis/Setup.hpp" + +namespace Intrepid2 { + + namespace Test { + + // This test evaluates the basis functions at a set of points on a batch of cells using the team-level getValues, + // and compares the results with those obtained using the classic getValues function. + template + int HVOL_QUAD_Cn_FEM_Test02(const bool verbose) { + + //! Setup test output stream. + Teuchos::RCP outStream = setup_output_stream( + verbose, "HVOL_QUAD_Cn_FEM, Test 2", {} + ); + + *outStream + << "\n" + << "===============================================================================\n" + << "| Testing Team-level Implemntation of getValues |\n" + << "===============================================================================\n"; + + using DeviceSpaceType = typename DeviceType::execution_space; + Kokkos::print_configuration(std::cout, false); + + int errorFlag = 0; + constexpr int maxOrder = 9; + try { + for (int order=1;order<=maxOrder;++order) { + using BasisType = Basis_HVOL_QUAD_Cn_FEM; + auto basisPtr = Teuchos::rcp(new BasisType(order)); + + const int ncells = 5, npts = 10, ndim = 2; + Kokkos::DynRankView ConstructWithLabelOutView(outputValuesA, ncells, basisPtr->getCardinality(), npts); + Kokkos::DynRankView ConstructWithLabelOutView(outputValuesB, basisPtr->getCardinality(), npts); + Kokkos::DynRankView ConstructWithLabelPointView(point, 1); + + using ScalarType = typename ScalarTraits::scalar_type; + + Kokkos::View inputPointsViewToUseRandom("inputPoints", npts*ndim*get_dimension_scalar(point)); + auto vcprop = Kokkos::common_view_alloc_prop(point); + Kokkos::DynRankView inputPoints (Kokkos::view_wrap(inputPointsViewToUseRandom.data(), vcprop), npts, ndim); + + // random values between (0,1) + Kokkos::Random_XorShift64_Pool random(13718); + Kokkos::fill_random(inputPointsViewToUseRandom, random, 1.0); + + + *outStream << "Order: " << order << ": Computing values for " << ncells << " cells and " << npts << " points using team-level getValues function" <(*basisPtr); + auto basisRawPtr_device = basisPtr_device.get(); + + int scratch_space_level =1; + const int vectorSize = getVectorSizeForHierarchicalParallelism(); + Kokkos::TeamPolicy teamPolicy(ncells, Kokkos::AUTO,vectorSize); + + { //compute values + auto functor = KOKKOS_LAMBDA (typename Kokkos::TeamPolicy::member_type team_member) { + auto valsACell = Kokkos::subview(outputValuesA, team_member.league_rank(), Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL()); + basisRawPtr_device->getValues(valsACell, inputPoints, OPERATOR_VALUE, team_member, team_member.team_scratch(scratch_space_level)); + }; + + //Get the required size of the scratch space per team and per thread. + int perThreadSpaceSize(0), perTeamSpaceSize(0); + basisPtr->getScratchSpaceSize(perTeamSpaceSize,perThreadSpaceSize,inputPoints, OPERATOR_VALUE); + teamPolicy.set_scratch_size(scratch_space_level, Kokkos::PerTeam(perTeamSpaceSize), Kokkos::PerThread(perThreadSpaceSize)); + + Kokkos::parallel_for (teamPolicy,functor); + } + } + + *outStream << "Order: " << order << ": Computing values for " << npts << " points using high-level getValues function" <getValues(outputValuesB, inputPoints, OPERATOR_VALUE); + + *outStream << "Order: " << order << ": Comparing values on host" <(); + for (size_t ic=0;ic tol) { + ++errorFlag; + std::cout << " order: " << order + << ", ic: " << ic << ", i: " << i << ", j: " << j + << ", val A: " << outputValuesA_Host(ic,i,j) + << ", val B: " << outputValuesB_Host(i,j) + << ", |diff|: " << diff + << ", tol: " << tol + << std::endl; + } + } + } + } + } catch (std::exception &err) { + std::cout << "UNEXPECTED ERROR !!! ----------------------------------------------------------\n"; + std::cout << err.what() << '\n'; + std::cout << "-------------------------------------------------------------------------------" << "\n\n"; + errorFlag = -1000; + }; + + if (errorFlag != 0) + std::cout << "End Result: TEST FAILED\n"; + else + std::cout << "End Result: TEST PASSED\n"; + + return errorFlag; + } + } +} diff --git a/packages/intrepid2/unit-test/Discretization/Basis/HVOL_TET_Cn_FEM/CMakeLists.txt b/packages/intrepid2/unit-test/Discretization/Basis/HVOL_TET_Cn_FEM/CMakeLists.txt index 0f61f9a7cfff..7dfea7c9986c 100644 --- a/packages/intrepid2/unit-test/Discretization/Basis/HVOL_TET_Cn_FEM/CMakeLists.txt +++ b/packages/intrepid2/unit-test/Discretization/Basis/HVOL_TET_Cn_FEM/CMakeLists.txt @@ -1,8 +1,13 @@ TRIBITS_INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}) + +# test +SET(Intrepid2_TEST_ETI_FILE "test_01") + # value types SET(Intrepid2_TEST_ETI_VALUETYPE_NAME "") SET(Intrepid2_TEST_ETI_VALUETYPE "") +SET(Intrepid2_TEST_ETI_SACADO "") LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE_NAME "DOUBLE_DOUBLE") LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE "double,double") @@ -32,9 +37,80 @@ ENDIF() LIST(LENGTH Intrepid2_TEST_ETI_VALUETYPE_NAME ETI_VALUETYPE_COUNT) MATH(EXPR ETI_VALUETYPE_COUNT "${ETI_VALUETYPE_COUNT}-1") +# device +SET(Intrepid2_TEST_ETI_DEVICE_NAME "") +SET(Intrepid2_TEST_ETI_DEVICE "") +IF(Kokkos_ENABLE_SERIAL) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "Serial") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() +IF(Kokkos_ENABLE_OPENMP) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "OpenMP") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() +IF(Kokkos_ENABLE_CUDA) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "CUDA") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() +IF(Kokkos_ENABLE_HIP) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "HIP") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() + +LIST(LENGTH Intrepid2_TEST_ETI_DEVICE_NAME ETI_DEVICE_COUNT) +MATH(EXPR ETI_DEVICE_COUNT "${ETI_DEVICE_COUNT}-1") + +FOREACH(I RANGE ${ETI_DEVICE_COUNT}) + LIST(GET Intrepid2_TEST_ETI_DEVICE_NAME ${I} ETI_DEVICE_NAME) + LIST(GET Intrepid2_TEST_ETI_DEVICE ${I} ETI_DEVICE) + #MESSAGE(STATUS "Generating TEST HVOL_TET_Cn_FEM for ${ETI_DEVICE_NAME} with ${ETI_DEVICE}") + FOREACH(J RANGE ${ETI_VALUETYPE_COUNT}) + LIST(GET Intrepid2_TEST_ETI_VALUETYPE_NAME ${J} ETI_VALUETYPE_NAME) + LIST(GET Intrepid2_TEST_ETI_VALUETYPE ${J} ETI_VALUETYPE) + LIST(GET Intrepid2_TEST_ETI_SACADO ${J} ETI_SACADO) + FOREACH(ETI_FILE IN LISTS Intrepid2_TEST_ETI_FILE) + SET(ETI_NAME "${ETI_FILE}_${ETI_DEVICE_NAME}_${ETI_VALUETYPE_NAME}") + MESSAGE(STATUS "Generating TEST: HVOL_TET_Cn_FEM ${ETI_NAME}.cpp") + CONFIGURE_FILE(eti/${ETI_FILE}_ETI.in ${ETI_NAME}.cpp) + + TRIBITS_ADD_EXECUTABLE_AND_TEST( + ${ETI_NAME} + SOURCES ${ETI_NAME}.cpp + ARGS PrintItAll + NUM_MPI_PROCS 1 + PASS_REGULAR_EXPRESSION "TEST PASSED" + ADD_DIR_TO_NAME + ) + + ENDFOREACH() + ENDFOREACH() +ENDFOREACH() + + + + # test -SET(Intrepid2_TEST_ETI_FILE "test_01") +SET(Intrepid2_TEST_ETI_FILE "test_02") +# value types +SET(Intrepid2_TEST_ETI_VALUETYPE_NAME "") +SET(Intrepid2_TEST_ETI_VALUETYPE "") +SET(Intrepid2_TEST_ETI_SACADO "") + +LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE_NAME "DOUBLE_DOUBLE") +LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE "double,double") +LIST(APPEND Intrepid2_TEST_ETI_SACADO "0") + +IF (HAVE_INTREPID2_SACADO) + LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE_NAME "DFAD_DFAD") + LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE "Sacado::Fad::DFad,Sacado::Fad::DFad ") + LIST(APPEND Intrepid2_TEST_ETI_SACADO "33") +ENDIF() + +LIST(LENGTH Intrepid2_TEST_ETI_VALUETYPE_NAME ETI_VALUETYPE_COUNT) +MATH(EXPR ETI_VALUETYPE_COUNT "${ETI_VALUETYPE_COUNT}-1") + +# device SET(Intrepid2_TEST_ETI_DEVICE_NAME "") SET(Intrepid2_TEST_ETI_DEVICE "") IF(Kokkos_ENABLE_SERIAL) @@ -60,7 +136,6 @@ MATH(EXPR ETI_DEVICE_COUNT "${ETI_DEVICE_COUNT}-1") FOREACH(I RANGE ${ETI_DEVICE_COUNT}) LIST(GET Intrepid2_TEST_ETI_DEVICE_NAME ${I} ETI_DEVICE_NAME) LIST(GET Intrepid2_TEST_ETI_DEVICE ${I} ETI_DEVICE) - #MESSAGE(STATUS "Generating TEST HVOL_TET_Cn_FEM for ${ETI_DEVICE_NAME} with ${ETI_DEVICE}") FOREACH(J RANGE ${ETI_VALUETYPE_COUNT}) LIST(GET Intrepid2_TEST_ETI_VALUETYPE_NAME ${J} ETI_VALUETYPE_NAME) LIST(GET Intrepid2_TEST_ETI_VALUETYPE ${J} ETI_VALUETYPE) diff --git a/packages/intrepid2/unit-test/Discretization/Basis/HVOL_TET_Cn_FEM/eti/test_02_ETI.in b/packages/intrepid2/unit-test/Discretization/Basis/HVOL_TET_Cn_FEM/eti/test_02_ETI.in new file mode 100644 index 000000000000..d15050227457 --- /dev/null +++ b/packages/intrepid2/unit-test/Discretization/Basis/HVOL_TET_Cn_FEM/eti/test_02_ETI.in @@ -0,0 +1,52 @@ +// @HEADER +// ***************************************************************************** +// Intrepid2 Package +// +// Copyright 2007 NTESS and the Intrepid2 contributors. +// SPDX-License-Identifier: BSD-3-Clause +// ***************************************************************************** +// @HEADER + +/** \file test_02.cpp + \brief Unit test of Intrepid2::Basis_HVOL_TET_Cn_FEM team-level getValues. + \author Kyungjoo Kim +*/ + +#include "Kokkos_Core.hpp" + +#define ETI_SACADO @ETI_SACADO@ +#if (ETI_SACADO != 0) /// SACADO +#include "Kokkos_ViewFactory.hpp" +#include "Sacado.hpp" +#endif + +#if (ETI_SACADO == 0) /// double double +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__) +#elif (ETI_SACADO == 11 /* SFAD SFAD */ || ETI_SACADO == 33 /* DFAD DFAD */) +constexpr int num_deriv = 3; +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#elif (ETI_SACADO == 23) +constexpr int num_deriv = 3; +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#elif (ETI_SACADO == 20) +constexpr int num_deriv = 2; +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__) +#endif + +#include "test_02.hpp" + +int main(int argc, char *argv[]) { + + const bool verbose = (argc-1) > 0; + Kokkos::initialize(); + + Intrepid2::Test::HVOL_TET_Cn_FEM_Test02<@ETI_VALUETYPE@,@ETI_DEVICE@>(verbose); + + Kokkos::finalize(); + return 0; +} + diff --git a/packages/intrepid2/unit-test/Discretization/Basis/HVOL_TET_Cn_FEM/test_02.hpp b/packages/intrepid2/unit-test/Discretization/Basis/HVOL_TET_Cn_FEM/test_02.hpp new file mode 100644 index 000000000000..d27c666355c1 --- /dev/null +++ b/packages/intrepid2/unit-test/Discretization/Basis/HVOL_TET_Cn_FEM/test_02.hpp @@ -0,0 +1,144 @@ +// @HEADER +// ***************************************************************************** +// Intrepid2 Package +// +// Copyright 2007 NTESS and the Intrepid2 contributors. +// SPDX-License-Identifier: BSD-3-Clause +// ***************************************************************************** +// @HEADER + +/** \file test_02.hpp + \brief Unit tests for the Intrepid2::HVOL_TET_Cn_FEM class. + \author Created by Kyungjoo Kim, Mauro Perego + */ + + +#include "Intrepid2_config.h" +#include "Kokkos_Random.hpp" +#ifdef HAVE_INTREPID2_DEBUG +#define INTREPID2_TEST_FOR_DEBUG_ABORT_OVERRIDE_TO_CONTINUE +#endif + +#include "Intrepid2_Types.hpp" +#include "Intrepid2_Utils.hpp" + +#include "Intrepid2_HVOL_TET_Cn_FEM.hpp" +#include "packages/intrepid2/unit-test/Discretization/Basis/Setup.hpp" + +namespace Intrepid2 { + + namespace Test { + + // This test evaluates the basis functions at a set of points on a batch of cells using the team-level getValues, + // and compares the results with those obtained using the classic getValues function. + template + int HVOL_TET_Cn_FEM_Test02(const bool verbose) { + + //! Setup test output stream. + Teuchos::RCP outStream = setup_output_stream( + verbose, "HVOL_TET_Cn_FEM, Test 2", {} + ); + + *outStream + << "\n" + << "===============================================================================\n" + << "| Testing Team-level Implemntation of getValues |\n" + << "===============================================================================\n"; + + using DeviceSpaceType = typename DeviceType::execution_space; + Kokkos::print_configuration(std::cout, false); + + int errorFlag = 0; + constexpr int maxOrder = 9; + try { + for (int order=1;order<=maxOrder;++order) { + using BasisType = Basis_HVOL_TET_Cn_FEM; + auto basisPtr = Teuchos::rcp(new BasisType(order)); + + const int ncells = 5, npts = 10, ndim = 3; + Kokkos::DynRankView ConstructWithLabelOutView(outputValuesA, ncells, basisPtr->getCardinality(), npts); + Kokkos::DynRankView ConstructWithLabelOutView(outputValuesB, basisPtr->getCardinality(), npts); + Kokkos::DynRankView ConstructWithLabelPointView(point, 1); + + using ScalarType = typename ScalarTraits::scalar_type; + + Kokkos::View inputPointsViewToUseRandom("inputPoints", npts*ndim*get_dimension_scalar(point)); + auto vcprop = Kokkos::common_view_alloc_prop(point); + Kokkos::DynRankView inputPoints (Kokkos::view_wrap(inputPointsViewToUseRandom.data(), vcprop), npts, ndim); + + // random values between (0,1) + Kokkos::Random_XorShift64_Pool random(13718); + Kokkos::fill_random(inputPointsViewToUseRandom, random, 1.0); + + + *outStream << "Order: " << order << ": Computing values for " << ncells << " cells and " << npts << " points using team-level getValues function" <(*basisPtr); + auto basisRawPtr_device = basisPtr_device.get(); + + int scratch_space_level =1; + const int vectorSize = getVectorSizeForHierarchicalParallelism(); + Kokkos::TeamPolicy teamPolicy(ncells, Kokkos::AUTO,vectorSize); + + { //compute values + auto functor = KOKKOS_LAMBDA (typename Kokkos::TeamPolicy::member_type team_member) { + auto valsACell = Kokkos::subview(outputValuesA, team_member.league_rank(), Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL()); + basisRawPtr_device->getValues(valsACell, inputPoints, OPERATOR_VALUE, team_member, team_member.team_scratch(scratch_space_level)); + }; + + //Get the required size of the scratch space per team and per thread. + int perThreadSpaceSize(0), perTeamSpaceSize(0); + basisPtr->getScratchSpaceSize(perTeamSpaceSize,perThreadSpaceSize,inputPoints, OPERATOR_VALUE); + teamPolicy.set_scratch_size(scratch_space_level, Kokkos::PerTeam(perTeamSpaceSize), Kokkos::PerThread(perThreadSpaceSize)); + + Kokkos::parallel_for (teamPolicy,functor); + } + } + + *outStream << "Order: " << order << ": Computing values for " << npts << " points using high-level getValues function" <getValues(outputValuesB, inputPoints, OPERATOR_VALUE); + + *outStream << "Order: " << order << ": Comparing values on host" <(); + for (size_t ic=0;ic tol) { + ++errorFlag; + std::cout << " order: " << order + << ", ic: " << ic << ", i: " << i << ", j: " << j + << ", val A: " << outputValuesA_Host(ic,i,j) + << ", val B: " << outputValuesB_Host(i,j) + << ", |diff|: " << diff + << ", tol: " << tol + << std::endl; + } + } + } + } + } catch (std::exception &err) { + std::cout << "UNEXPECTED ERROR !!! ----------------------------------------------------------\n"; + std::cout << err.what() << '\n'; + std::cout << "-------------------------------------------------------------------------------" << "\n\n"; + errorFlag = -1000; + }; + + if (errorFlag != 0) + std::cout << "End Result: TEST FAILED\n"; + else + std::cout << "End Result: TEST PASSED\n"; + + return errorFlag; + } + } +} diff --git a/packages/intrepid2/unit-test/Discretization/Basis/HVOL_TRI_Cn_FEM/CMakeLists.txt b/packages/intrepid2/unit-test/Discretization/Basis/HVOL_TRI_Cn_FEM/CMakeLists.txt index 700140bb8337..49398919d584 100644 --- a/packages/intrepid2/unit-test/Discretization/Basis/HVOL_TRI_Cn_FEM/CMakeLists.txt +++ b/packages/intrepid2/unit-test/Discretization/Basis/HVOL_TRI_Cn_FEM/CMakeLists.txt @@ -1,8 +1,13 @@ TRIBITS_INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}) + +# test +SET(Intrepid2_TEST_ETI_FILE "test_01") + # value types SET(Intrepid2_TEST_ETI_VALUETYPE_NAME "") SET(Intrepid2_TEST_ETI_VALUETYPE "") +SET(Intrepid2_TEST_ETI_SACADO "") LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE_NAME "DOUBLE_DOUBLE") LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE "double,double") @@ -32,9 +37,80 @@ ENDIF() LIST(LENGTH Intrepid2_TEST_ETI_VALUETYPE_NAME ETI_VALUETYPE_COUNT) MATH(EXPR ETI_VALUETYPE_COUNT "${ETI_VALUETYPE_COUNT}-1") +# device +SET(Intrepid2_TEST_ETI_DEVICE_NAME "") +SET(Intrepid2_TEST_ETI_DEVICE "") +IF(Kokkos_ENABLE_SERIAL) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "Serial") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() +IF(Kokkos_ENABLE_OPENMP) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "OpenMP") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() +IF(Kokkos_ENABLE_CUDA) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "CUDA") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() +IF(Kokkos_ENABLE_HIP) + LIST(APPEND Intrepid2_TEST_ETI_DEVICE_NAME "HIP") + LIST(APPEND Intrepid2_TEST_ETI_DEVICE "Kokkos::Device") +ENDIF() + +LIST(LENGTH Intrepid2_TEST_ETI_DEVICE_NAME ETI_DEVICE_COUNT) +MATH(EXPR ETI_DEVICE_COUNT "${ETI_DEVICE_COUNT}-1") + +FOREACH(I RANGE ${ETI_DEVICE_COUNT}) + LIST(GET Intrepid2_TEST_ETI_DEVICE_NAME ${I} ETI_DEVICE_NAME) + LIST(GET Intrepid2_TEST_ETI_DEVICE ${I} ETI_DEVICE) + #MESSAGE(STATUS "Generating TEST HVOL_TRI_Cn_FEM for ${ETI_DEVICE_NAME} with ${ETI_DEVICE}") + FOREACH(J RANGE ${ETI_VALUETYPE_COUNT}) + LIST(GET Intrepid2_TEST_ETI_VALUETYPE_NAME ${J} ETI_VALUETYPE_NAME) + LIST(GET Intrepid2_TEST_ETI_VALUETYPE ${J} ETI_VALUETYPE) + LIST(GET Intrepid2_TEST_ETI_SACADO ${J} ETI_SACADO) + FOREACH(ETI_FILE IN LISTS Intrepid2_TEST_ETI_FILE) + SET(ETI_NAME "${ETI_FILE}_${ETI_DEVICE_NAME}_${ETI_VALUETYPE_NAME}") + MESSAGE(STATUS "Generating TEST: HVOL_TRI_Cn_FEM ${ETI_NAME}.cpp") + CONFIGURE_FILE(eti/${ETI_FILE}_ETI.in ${ETI_NAME}.cpp) + + TRIBITS_ADD_EXECUTABLE_AND_TEST( + ${ETI_NAME} + SOURCES ${ETI_NAME}.cpp + ARGS PrintItAll + NUM_MPI_PROCS 1 + PASS_REGULAR_EXPRESSION "TEST PASSED" + ADD_DIR_TO_NAME + ) + + ENDFOREACH() + ENDFOREACH() +ENDFOREACH() + + + + # test -SET(Intrepid2_TEST_ETI_FILE "test_01") +SET(Intrepid2_TEST_ETI_FILE "test_02") +# value types +SET(Intrepid2_TEST_ETI_VALUETYPE_NAME "") +SET(Intrepid2_TEST_ETI_VALUETYPE "") +SET(Intrepid2_TEST_ETI_SACADO "") + +LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE_NAME "DOUBLE_DOUBLE") +LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE "double,double") +LIST(APPEND Intrepid2_TEST_ETI_SACADO "0") + +IF (HAVE_INTREPID2_SACADO) + LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE_NAME "DFAD_DFAD") + LIST(APPEND Intrepid2_TEST_ETI_VALUETYPE "Sacado::Fad::DFad,Sacado::Fad::DFad ") + LIST(APPEND Intrepid2_TEST_ETI_SACADO "33") +ENDIF() + +LIST(LENGTH Intrepid2_TEST_ETI_VALUETYPE_NAME ETI_VALUETYPE_COUNT) +MATH(EXPR ETI_VALUETYPE_COUNT "${ETI_VALUETYPE_COUNT}-1") + +# device SET(Intrepid2_TEST_ETI_DEVICE_NAME "") SET(Intrepid2_TEST_ETI_DEVICE "") IF(Kokkos_ENABLE_SERIAL) @@ -60,7 +136,6 @@ MATH(EXPR ETI_DEVICE_COUNT "${ETI_DEVICE_COUNT}-1") FOREACH(I RANGE ${ETI_DEVICE_COUNT}) LIST(GET Intrepid2_TEST_ETI_DEVICE_NAME ${I} ETI_DEVICE_NAME) LIST(GET Intrepid2_TEST_ETI_DEVICE ${I} ETI_DEVICE) - #MESSAGE(STATUS "Generating TEST HVOL_TRI_Cn_FEM for ${ETI_DEVICE_NAME} with ${ETI_DEVICE}") FOREACH(J RANGE ${ETI_VALUETYPE_COUNT}) LIST(GET Intrepid2_TEST_ETI_VALUETYPE_NAME ${J} ETI_VALUETYPE_NAME) LIST(GET Intrepid2_TEST_ETI_VALUETYPE ${J} ETI_VALUETYPE) diff --git a/packages/intrepid2/unit-test/Discretization/Basis/HVOL_TRI_Cn_FEM/eti/test_02_ETI.in b/packages/intrepid2/unit-test/Discretization/Basis/HVOL_TRI_Cn_FEM/eti/test_02_ETI.in new file mode 100644 index 000000000000..4b98bc03263a --- /dev/null +++ b/packages/intrepid2/unit-test/Discretization/Basis/HVOL_TRI_Cn_FEM/eti/test_02_ETI.in @@ -0,0 +1,52 @@ +// @HEADER +// ***************************************************************************** +// Intrepid2 Package +// +// Copyright 2007 NTESS and the Intrepid2 contributors. +// SPDX-License-Identifier: BSD-3-Clause +// ***************************************************************************** +// @HEADER + +/** \file test_02.cpp + \brief Unit test of Intrepid2::Basis_HVOL_TRI_Cn_FEM team-level getValues. + \author Kyungjoo Kim +*/ + +#include "Kokkos_Core.hpp" + +#define ETI_SACADO @ETI_SACADO@ +#if (ETI_SACADO != 0) /// SACADO +#include "Kokkos_ViewFactory.hpp" +#include "Sacado.hpp" +#endif + +#if (ETI_SACADO == 0) /// double double +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__) +#elif (ETI_SACADO == 11 /* SFAD SFAD */ || ETI_SACADO == 33 /* DFAD DFAD */) +constexpr int num_deriv = 3; +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#elif (ETI_SACADO == 23) +constexpr int num_deriv = 3; +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#elif (ETI_SACADO == 20) +constexpr int num_deriv = 2; +#define ConstructWithLabelOutView(obj, ...) obj(#obj, __VA_ARGS__, num_deriv+1) +#define ConstructWithLabelPointView(obj, ...) obj(#obj, __VA_ARGS__) +#endif + +#include "test_02.hpp" + +int main(int argc, char *argv[]) { + + const bool verbose = (argc-1) > 0; + Kokkos::initialize(); + + Intrepid2::Test::HVOL_TRI_Cn_FEM_Test02<@ETI_VALUETYPE@,@ETI_DEVICE@>(verbose); + + Kokkos::finalize(); + return 0; +} + diff --git a/packages/intrepid2/unit-test/Discretization/Basis/HVOL_TRI_Cn_FEM/test_02.hpp b/packages/intrepid2/unit-test/Discretization/Basis/HVOL_TRI_Cn_FEM/test_02.hpp new file mode 100644 index 000000000000..aaefaa951c33 --- /dev/null +++ b/packages/intrepid2/unit-test/Discretization/Basis/HVOL_TRI_Cn_FEM/test_02.hpp @@ -0,0 +1,145 @@ +// @HEADER +// ***************************************************************************** +// Intrepid2 Package +// +// Copyright 2007 NTESS and the Intrepid2 contributors. +// SPDX-License-Identifier: BSD-3-Clause +// ***************************************************************************** +// @HEADER + +/** \file test_02.hpp + \brief Unit tests for the Intrepid2::HVOL_TRI_Cn_FEM class. + \author Created by Kyungjoo Kim, Mauro Perego + */ + + +#include "Intrepid2_config.h" +#include "Kokkos_Random.hpp" +#ifdef HAVE_INTREPID2_DEBUG +#define INTREPID2_TEST_FOR_DEBUG_ABORT_OVERRIDE_TO_CONTINUE +#endif + +#include "Intrepid2_Types.hpp" +#include "Intrepid2_Utils.hpp" + +#include "Intrepid2_HVOL_TRI_Cn_FEM.hpp" +#include "packages/intrepid2/unit-test/Discretization/Basis/Setup.hpp" + +namespace Intrepid2 { + + namespace Test { + + // This test evaluates the basis functions at a set of points on a batch of cells using the team-level getValues, + // and compares the results with those obtained using the classic getValues function. + template + int HVOL_TRI_Cn_FEM_Test02(const bool verbose) { + + //! Setup test output stream. + Teuchos::RCP outStream = setup_output_stream( + verbose, "HVOL_TRI_Cn_FEM, Test 2", {} + ); + + *outStream + << "\n" + << "===============================================================================\n" + << "| Testing Team-level Implemntation of getValues |\n" + << "===============================================================================\n"; + + using DeviceSpaceType = typename DeviceType::execution_space; + Kokkos::print_configuration(std::cout, false); + + int errorFlag = 0; + + constexpr int maxOrder = 9; + try { + for (int order=1;order<=maxOrder;++order) { + using BasisType = Basis_HVOL_TRI_Cn_FEM; + auto basisPtr = Teuchos::rcp(new BasisType(order)); + + const int ncells = 5, npts = 10, ndim = 2; + Kokkos::DynRankView ConstructWithLabelOutView(outputValuesA, ncells, basisPtr->getCardinality(), npts); + Kokkos::DynRankView ConstructWithLabelOutView(outputValuesB, basisPtr->getCardinality(), npts); + Kokkos::DynRankView ConstructWithLabelPointView(point, 1); + + using ScalarType = typename ScalarTraits::scalar_type; + + Kokkos::View inputPointsViewToUseRandom("inputPoints", npts*ndim*get_dimension_scalar(point)); + auto vcprop = Kokkos::common_view_alloc_prop(point); + Kokkos::DynRankView inputPoints (Kokkos::view_wrap(inputPointsViewToUseRandom.data(), vcprop), npts, ndim); + + // random values between (0,1) + Kokkos::Random_XorShift64_Pool random(13718); + Kokkos::fill_random(inputPointsViewToUseRandom, random, 1.0); + + + *outStream << "Order: " << order << ": Computing values for " << ncells << " cells and " << npts << " points using team-level getValues function" <(*basisPtr); + auto basisRawPtr_device = basisPtr_device.get(); + + int scratch_space_level =1; + const int vectorSize = getVectorSizeForHierarchicalParallelism(); + Kokkos::TeamPolicy teamPolicy(ncells, Kokkos::AUTO,vectorSize); + + { //compute values + auto functor = KOKKOS_LAMBDA (typename Kokkos::TeamPolicy::member_type team_member) { + auto valsACell = Kokkos::subview(outputValuesA, team_member.league_rank(), Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL()); + basisRawPtr_device->getValues(valsACell, inputPoints, OPERATOR_VALUE, team_member, team_member.team_scratch(scratch_space_level)); + }; + + //Get the required size of the scratch space per team and per thread. + int perThreadSpaceSize(0), perTeamSpaceSize(0); + basisPtr->getScratchSpaceSize(perTeamSpaceSize,perThreadSpaceSize,inputPoints, OPERATOR_VALUE); + teamPolicy.set_scratch_size(scratch_space_level, Kokkos::PerTeam(perTeamSpaceSize), Kokkos::PerThread(perThreadSpaceSize)); + + Kokkos::parallel_for (teamPolicy,functor); + } + } + + *outStream << "Order: " << order << ": Computing values for " << npts << " points using high-level getValues function" <getValues(outputValuesB, inputPoints, OPERATOR_VALUE); + + *outStream << "Order: " << order << ": Comparing values on host" <(); + for (size_t ic=0;ic tol) { + ++errorFlag; + std::cout << " order: " << order + << ", ic: " << ic << ", i: " << i << ", j: " << j + << ", val A: " << outputValuesA_Host(ic,i,j) + << ", val B: " << outputValuesB_Host(i,j) + << ", |diff|: " << diff + << ", tol: " << tol + << std::endl; + } + } + } + } + } catch (std::exception &err) { + std::cout << "UNEXPECTED ERROR !!! ----------------------------------------------------------\n"; + std::cout << err.what() << '\n'; + std::cout << "-------------------------------------------------------------------------------" << "\n\n"; + errorFlag = -1000; + }; + + if (errorFlag != 0) + std::cout << "End Result: TEST FAILED\n"; + else + std::cout << "End Result: TEST PASSED\n"; + + return errorFlag; + } + } +}