int HGRAD_TRI_C1_FEM_Test01(const bool verbose) { Teuchos::RCP<std::ostream> outStream; Teuchos::oblackholestream bhs; // outputs nothing if (verbose) outStream = Teuchos::rcp(&std::cout, false); else outStream = Teuchos::rcp(&bhs, false); Teuchos::oblackholestream oldFormatState; oldFormatState.copyfmt(std::cout); typedef typename Kokkos::Impl::is_space<DeviceSpaceType>::host_mirror_space::execution_space HostSpaceType ; *outStream << "DeviceSpace:: "; DeviceSpaceType::print_configuration(*outStream, false); *outStream << "HostSpace:: "; HostSpaceType::print_configuration(*outStream, false); *outStream << "===============================================================================\n" << "| |\n" << "| Unit Test (Basis_HGRAD_TRI_C1_FEM) |\n" << "| |\n" << "| 1) Conversion of Dof tags into Dof ordinals and back |\n" << "| 2) Basis values for VALUE, GRAD, CURL, and Dk operators |\n" << "| |\n" << "| Questions? Contact Pavel Bochev ([email protected]), |\n" << "| Denis Ridzal ([email protected]), |\n" << "| Kara Peterson ([email protected]), |\n" << "| Kyungjoo Kim ([email protected]). |\n" << "| |\n" << "| Intrepid's website: http://trilinos.sandia.gov/packages/intrepid |\n" << "| Trilinos website: http://trilinos.sandia.gov |\n" << "| |\n" << "===============================================================================\n"; typedef Kokkos::DynRankView<ValueType,DeviceSpaceType> DynRankView; #define ConstructWithLabel(obj, ...) obj(#obj, __VA_ARGS__) const ValueType tol = Parameters::Tolerence; int errorFlag = 0; // for virtual function, value and point types are declared in the class typedef ValueType outputValueType; typedef ValueType pointValueType; Basis_HGRAD_TRI_C1_FEM<DeviceSpaceType,outputValueType,pointValueType> triBasis; //typedef typename decltype(triBasis)::outputViewType outputViewType; //typedef typename decltype(triBasis)::pointViewType pointViewType; *outStream << "\n" << "===============================================================================\n" << "| TEST 1: Basis creation, exceptions tests |\n" << "===============================================================================\n"; try { ordinal_type nthrow = 0, ncatch = 0; #ifdef HAVE_INTREPID2_DEBUG // Define array containing the 3 vertices of the reference Triangle, its center and another point DynRankView ConstructWithLabel(triNodes, 5, 2); // Generic array for the output values; needs to be properly resized depending on the operator type const auto numFields = triBasis.getCardinality(); const auto numPoints = triNodes.dimension(0); const auto spaceDim = triBasis.getBaseCellTopology().getDimension(); DynRankView vals; vals = DynRankView("vals", numFields, numPoints); { // exception #1: DIV cannot be applied to scalar functions INTREPID2_TEST_ERROR_EXPECTED( triBasis.getValues(vals, triNodes, OPERATOR_DIV) ); } // Exceptions 2-6: all bf tags/bf Ids below are wrong and should cause getDofOrdinal() and // getDofTag() to access invalid array elements thereby causing bounds check exception { // exception #2 INTREPID2_TEST_ERROR_EXPECTED( triBasis.getDofOrdinal(2,0,0) ); // exception #3 INTREPID2_TEST_ERROR_EXPECTED( triBasis.getDofOrdinal(1,1,1) ); // exception #4 INTREPID2_TEST_ERROR_EXPECTED( triBasis.getDofOrdinal(0,4,0) ); // exception #5 INTREPID2_TEST_ERROR_EXPECTED( triBasis.getDofTag(5) ); // exception #6 INTREPID2_TEST_ERROR_EXPECTED( triBasis.getDofTag(-1) ); } // Exceptions 7-17 test exception handling with incorrectly dimensioned input/output arrays // exception #7: input points array must be of rank-2 { DynRankView ConstructWithLabel( badPoints1, 4, 5, 3); INTREPID2_TEST_ERROR_EXPECTED( triBasis.getValues(vals, badPoints1, OPERATOR_VALUE) ); } { // exception #8 dimension 1 in the input point array must equal space dimension of the cell DynRankView ConstructWithLabel( badPoints2, 4, 3); INTREPID2_TEST_ERROR_EXPECTED( triBasis.getValues(vals, badPoints2, OPERATOR_VALUE) ); } { // exception #9 output values must be of rank-2 for OPERATOR_VALUE DynRankView ConstructWithLabel( badVals1, 4, 3, 1); INTREPID2_TEST_ERROR_EXPECTED( triBasis.getValues(badVals1, triNodes, OPERATOR_VALUE) ); } { // exception #10 output values must be of rank-3 for OPERATOR_GRAD DynRankView ConstructWithLabel( badVals2, 4, 3); INTREPID2_TEST_ERROR_EXPECTED( triBasis.getValues(badVals2, triNodes, OPERATOR_GRAD) ); // exception #11 output values must be of rank-3 for OPERATOR_CURL INTREPID2_TEST_ERROR_EXPECTED( triBasis.getValues(badVals2, triNodes, OPERATOR_CURL) ); // exception #12 output values must be of rank-3 for OPERATOR_D2 INTREPID2_TEST_ERROR_EXPECTED( triBasis.getValues(badVals2, triNodes, OPERATOR_D2) ); } { // exception #13 incorrect 1st dimension of output array (must equal number of basis functions) DynRankView ConstructWithLabel( badVals3, numFields + 1, numPoints); INTREPID2_TEST_ERROR_EXPECTED( triBasis.getValues(badVals3, triNodes, OPERATOR_VALUE) ); } { // exception #14 incorrect 0th dimension of output array (must equal number of points) DynRankView ConstructWithLabel( badVals4, numFields, numPoints + 1); INTREPID2_TEST_ERROR_EXPECTED( triBasis.getValues(badVals4, triNodes, OPERATOR_VALUE) ); } { // exception #15: incorrect 2nd dimension of output array (must equal the space dimension) DynRankView ConstructWithLabel( badVals5, numFields, numPoints, spaceDim + 1); INTREPID2_TEST_ERROR_EXPECTED( triBasis.getValues(badVals5, triNodes, OPERATOR_GRAD) ); } { // exception #16: incorrect 2nd dimension of output array (must equal D2 cardinality in 2D) DynRankView ConstructWithLabel( badVals6, numFields, numPoints, 40); INTREPID2_TEST_ERROR_EXPECTED( triBasis.getValues(badVals6, triNodes, OPERATOR_D2) ); } #endif if (nthrow != ncatch) { errorFlag++; *outStream << std::setw(70) << "^^^^----FAILURE!" << "\n"; *outStream << "# of catch ("<< ncatch << ") is different from # of throw (" << ncatch << ")\n"; } } catch (std::logic_error err) { *outStream << "UNEXPECTED ERROR !!! ----------------------------------------------------------\n"; *outStream << err.what() << '\n'; *outStream << "-------------------------------------------------------------------------------" << "\n\n"; errorFlag = -1000; } *outStream << "\n" << "===============================================================================\n" << "| TEST 2: correctness of tag to enum and enum to tag lookups |\n" << "===============================================================================\n"; // all tags are on host space try { const auto numFields = triBasis.getCardinality(); const auto allTags = triBasis.getAllDofTags(); // Loop over all tags, lookup the associated dof enumeration and then lookup the tag again const auto dofTagSize = allTags.dimension(0); for (auto i=0;i<dofTagSize;++i) { const auto bfOrd = triBasis.getDofOrdinal(allTags(i,0), allTags(i,1), allTags(i,2)); const auto myTag = triBasis.getDofTag(bfOrd); if( !( (myTag(0) == allTags(i,0)) && (myTag(1) == allTags(i,1)) && (myTag(2) == allTags(i,2)) && (myTag(3) == allTags(i,3)) ) ) { errorFlag++; *outStream << std::setw(70) << "^^^^----FAILURE!" << "\n"; *outStream << " getDofOrdinal( {" << allTags(i,0) << ", " << allTags(i,1) << ", " << allTags(i,2) << ", " << allTags(i,3) << "}) = " << bfOrd <<" but \n"; *outStream << " getDofTag(" << bfOrd << ") = { " << myTag(0) << ", " << myTag(1) << ", " << myTag(2) << ", " << myTag(3) << "}\n"; } } // Now do the same but loop over basis functions for (auto bfOrd=0;bfOrd<numFields;++bfOrd) { const auto myTag = triBasis.getDofTag(bfOrd); const auto myBfOrd = triBasis.getDofOrdinal(myTag(0), myTag(1), myTag(2)); if ( bfOrd != myBfOrd) { errorFlag++; *outStream << std::setw(70) << "^^^^----FAILURE!" << "\n"; *outStream << " getDofTag(" << bfOrd << ") = { " << myTag(0) << ", " << myTag(1) << ", " << myTag(2) << ", " << myTag(3) << "} but getDofOrdinal({" << myTag(0) << ", " << myTag(1) << ", " << myTag(2) << ", " << myTag(3) << "} ) = " << myBfOrd << "\n"; } } } catch (std::logic_error err) { *outStream << err.what() << "\n\n"; errorFlag = -1000; } *outStream \ << "\n" << "===============================================================================\n"\ << "| TEST 3: correctness of basis function values |\n"\ << "===============================================================================\n"; outStream -> precision(20); // VALUE: Each row gives the 3 correct basis set values at an evaluation point const ValueType basisValues[] = { 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.5, 0.5, 0.25,0.0, 0.75 }; // GRAD and D1: each row gives the 6 correct values of the gradients of the 3 basis functions const ValueType basisGrads[] = { -1.0, -1.0, 1.0, 0.0, 0.0, 1.0, -1.0, -1.0, 1.0, 0.0, 0.0, 1.0, -1.0, -1.0, 1.0, 0.0, 0.0, 1.0, -1.0, -1.0, 1.0, 0.0, 0.0, 1.0, -1.0, -1.0, 1.0, 0.0, 0.0, 1.0, }; // CURL: each row gives the 6 correct values of the curls of the 3 basis functions const ValueType basisCurls[] = { -1.0, 1.0, 0.0, -1.0, 1.0, 0.0, -1.0, 1.0, 0.0, -1.0, 1.0, 0.0, -1.0, 1.0, 0.0, -1.0, 1.0, 0.0, -1.0, 1.0, 0.0, -1.0, 1.0, 0.0, -1.0, 1.0, 0.0, -1.0, 1.0, 0.0 }; try{ DynRankView ConstructWithLabel(triNodesHost, 5, 2); triNodesHost(0,0) = 0.0; triNodesHost(0,1) = 0.0; triNodesHost(1,0) = 1.0; triNodesHost(1,1) = 0.0; triNodesHost(2,0) = 0.0; triNodesHost(2,1) = 1.0; triNodesHost(3,0) = 0.5; triNodesHost(3,1) = 0.5; triNodesHost(4,0) = 0.0; triNodesHost(4,1) = 0.75; auto triNodes = Kokkos::create_mirror_view(typename DeviceSpaceType::memory_space(), triNodesHost); Kokkos::deep_copy(triNodes, triNodesHost); // Dimensions for the output arrays: const auto numFields = triBasis.getCardinality(); const auto numPoints = triNodes.dimension(0); const auto spaceDim = triBasis.getBaseCellTopology().getDimension(); // Check VALUE of basis functions: resize vals to rank-2 container: { DynRankView vals = DynRankView("vals", numFields, numPoints); triBasis.getValues(vals, triNodes, OPERATOR_VALUE); auto vals_host = Kokkos::create_mirror_view(typename HostSpaceType::memory_space(), vals); Kokkos::deep_copy(vals_host, vals); for (auto i=0;i<numFields;++i) { for (auto j=0;j<numPoints;++j) { const auto l = i + j * numFields; if (std::abs(vals_host(i,j) - basisValues[l]) > tol) { errorFlag++; *outStream << std::setw(70) << "^^^^----FAILURE!" << "\n"; // Output the multi-index of the value where the error is: *outStream << " At multi-index { "; *outStream << i << " ";*outStream << j << " "; *outStream << "} computed value: " << vals_host(i,j) << " but reference value: " << basisValues[l] << "\n"; } } } } // Check GRAD of basis { DynRankView vals = DynRankView("vals", numFields, numPoints, spaceDim); triBasis.getValues(vals, triNodes, OPERATOR_GRAD); auto vals_host = Kokkos::create_mirror_view(typename HostSpaceType::memory_space(), vals); Kokkos::deep_copy(vals_host, vals); for (auto i=0;i<numFields;++i) { for (auto j=0;j<numPoints;++j) { for (auto k=0;k<spaceDim;++k) { auto l = k + i * spaceDim + j * spaceDim * numFields; if (std::abs(vals_host(i,j,k) - basisGrads[l]) > tol) { errorFlag++; *outStream << std::setw(70) << "^^^^----FAILURE!" << "\n"; // Output the multi-index of the value where the error is: *outStream << " At multi-index { "; *outStream << i << " ";*outStream << j << " ";*outStream << k << " "; *outStream << "} computed grad component: " << vals_host(i,j,k) << " but reference grad component: " << basisGrads[l] << "\n"; } } } } } // Check D1 of basis { DynRankView vals = DynRankView("vals", numFields, numPoints, spaceDim); triBasis.getValues(vals, triNodes, OPERATOR_D1); auto vals_host = Kokkos::create_mirror_view(typename HostSpaceType::memory_space(), vals); Kokkos::deep_copy(vals_host, vals); for (auto i=0;i<numFields;++i) { for (auto j=0;j<numPoints;++j) { for (auto k=0;k<spaceDim;++k) { auto l = k + i * spaceDim + j * spaceDim * numFields; if (std::abs(vals_host(i,j,k) - basisGrads[l]) > tol) { errorFlag++; *outStream << std::setw(70) << "^^^^----FAILURE!" << "\n"; // Output the multi-index of the value where the error is: *outStream << " At multi-index { "; *outStream << i << " ";*outStream << j << " ";*outStream << k << " "; *outStream << "} computed D1 component: " << vals_host(i,j,k) << " but reference D1 component: " << basisGrads[l] << "\n"; } } } } } // Check CURL of basis function { DynRankView vals = DynRankView("vals", numFields, numPoints, spaceDim); triBasis.getValues(vals, triNodes, OPERATOR_CURL); auto vals_host = Kokkos::create_mirror_view(typename HostSpaceType::memory_space(), vals); Kokkos::deep_copy(vals_host, vals); for (auto i=0;i<numFields;++i) { for (auto j=0;j<numPoints;++j) { for (auto k=0;k<spaceDim;++k) { auto l = k + i * spaceDim + j * spaceDim * numFields; if (std::abs(vals_host(i,j,k) - basisCurls[l]) > tol) { errorFlag++; *outStream << std::setw(70) << "^^^^----FAILURE!" << "\n"; // Output the multi-index of the value where the error is: *outStream << " At multi-index { "; *outStream << i << " ";*outStream << j << " ";*outStream << k << " "; *outStream << "} computed curl component: " << vals_host(i,j,k) << " but reference curl component: " << basisCurls[l] << "\n"; } } } } } // Check all higher derivatives - must be zero. { const EOperator ops[] = { OPERATOR_D2, OPERATOR_D3, OPERATOR_D4, OPERATOR_D5, OPERATOR_D6, OPERATOR_D7, OPERATOR_D8, OPERATOR_D9, OPERATOR_D10, OPERATOR_MAX }; for (auto h=0;ops[h]!=OPERATOR_MAX;++h) { const auto op = ops[h]; const auto DkCardin = getDkCardinality(op, spaceDim); DynRankView vals("vals", numFields, numPoints, DkCardin); triBasis.getValues(vals, triNodes, op); auto vals_host = Kokkos::create_mirror_view(typename HostSpaceType::memory_space(), vals); Kokkos::deep_copy(vals_host, vals); for (auto i1=0;i1<numFields; i1++) for (auto i2=0;i2<numPoints; i2++) for (auto i3=0;i3<DkCardin; i3++) { if (std::abs(vals_host(i1,i2,i3)) > tol) { errorFlag++; *outStream << std::setw(70) << "^^^^----FAILURE!" << "\n"; // Get the multi-index of the value where the error is and the operator order const auto ord = Intrepid2::getOperatorOrder(op); *outStream << " At multi-index { "<<i1<<" "<<i2 <<" "<<i3; *outStream << "} computed D"<< ord <<" component: " << vals_host(i1,i2,i3) << " but reference D" << ord << " component: 0 \n"; } } } } } catch (std::logic_error err) { *outStream << err.what() << "\n\n"; errorFlag = -1000; } *outStream << "\n" << "===============================================================================\n" << "| TEST 4: correctness of DoF locations |\n" << "===============================================================================\n"; try { const auto numFields = triBasis.getCardinality(); const auto spaceDim = triBasis.getBaseCellTopology().getDimension(); // Check exceptions. ordinal_type nthrow = 0, ncatch = 0; #ifdef HAVE_INTREPID2_DEBUG { DynRankView ConstructWithLabel(badVals, 1,2,3); INTREPID2_TEST_ERROR_EXPECTED( triBasis.getDofCoords(badVals) ); } { DynRankView ConstructWithLabel(badVals, 4,2); INTREPID2_TEST_ERROR_EXPECTED( triBasis.getDofCoords(badVals) ); } { DynRankView ConstructWithLabel(badVals, 4,3); INTREPID2_TEST_ERROR_EXPECTED( triBasis.getDofCoords(badVals) ); } #endif if (nthrow != ncatch) { errorFlag++; *outStream << std::setw(70) << "^^^^----FAILURE!" << "\n"; *outStream << "# of catch ("<< ncatch << ") is different from # of throw (" << ncatch << ")\n"; } DynRankView ConstructWithLabel(bvals, numFields, numFields); DynRankView ConstructWithLabel(cvals, numFields, spaceDim); // Check mathematical correctness. triBasis.getDofCoords(cvals); triBasis.getValues(bvals, cvals, OPERATOR_VALUE); auto cvals_host = Kokkos::create_mirror_view(typename HostSpaceType::memory_space(), cvals); Kokkos::deep_copy(cvals_host, cvals); auto bvals_host = Kokkos::create_mirror_view(typename HostSpaceType::memory_space(), bvals); Kokkos::deep_copy(bvals_host, bvals); for (auto i=0;i<numFields;++i) { for (auto j=0;j<numFields;++j) { const ValueType expected_value = (i == j); const ValueType value = bvals_host(i,j); if (std::abs(value - expected_value) > tol) { errorFlag++; std::stringstream ss; ss << "\nValue of basis function " << i << " at (" << cvals_host(i,0) << ", " << cvals_host(i,1)<< ") is " << value << " but should be " << expected_value << "\n"; *outStream << ss.str(); } } } } catch (std::logic_error err) { *outStream << err.what() << "\n\n"; errorFlag = -1000; }; if (errorFlag != 0) std::cout << "End Result: TEST FAILED\n"; else std::cout << "End Result: TEST PASSED\n"; // reset format state of std::cout std::cout.copyfmt(oldFormatState); return errorFlag; }
int HDIV_TRI_I1_FEM_Test01(const bool verbose) { Teuchos::RCP<std::ostream> outStream; Teuchos::oblackholestream bhs; // outputs nothing if (verbose) outStream = Teuchos::rcp(&std::cout, false); else outStream = Teuchos::rcp(&bhs, false); Teuchos::oblackholestream oldFormatState; oldFormatState.copyfmt(std::cout); typedef typename Kokkos::Impl::is_space<DeviceSpaceType>::host_mirror_space::execution_space HostSpaceType ; *outStream << "DeviceSpace:: "; DeviceSpaceType::print_configuration(*outStream, false); *outStream << "HostSpace:: "; HostSpaceType::print_configuration(*outStream, false); *outStream << "===============================================================================\n" << "| |\n" << "| Unit Test (Basis_HDIV_TRI_I1_FEM) |\n" << "| |\n" << "| 1) Conversion of Dof tags into Dof ordinals and back |\n" << "| 2) Basis values for VALUE and DIV operators |\n" << "| |\n" << "| Questions? Contact Pavel Bochev ([email protected]), |\n" << "| Denis Ridzal ([email protected]), |\n" << "| Kara Peterson ([email protected]). |\n" << "| |\n" << "| Intrepid's website: http://trilinos.sandia.gov/packages/intrepid |\n" << "| Trilinos website: http://trilinos.sandia.gov |\n" << "| |\n" << "===============================================================================\n"; typedef Kokkos::DynRankView<ValueType,DeviceSpaceType> DynRankView; typedef Kokkos::DynRankView<ValueType,HostSpaceType> DynRankViewHost; #define ConstructWithLabel(obj, ...) obj(#obj, __VA_ARGS__) const ValueType tol = tolerence(); int errorFlag = 0; // for virtual function, value and point types are declared in the class typedef ValueType outputValueType; typedef ValueType pointValueType; Basis_HDIV_TRI_I1_FEM<DeviceSpaceType,outputValueType,pointValueType> triBasis; //typedef typename decltype(triBasis)::outputViewType outputViewType; //typedef typename decltype(triBasis)::pointViewType pointViewType; *outStream << "\n" << "===============================================================================\n" << "| TEST 1: Basis creation, exceptions tests |\n" << "===============================================================================\n"; try { ordinal_type nthrow = 0, ncatch = 0; #ifdef HAVE_INTREPID2_DEBUG // Define array containing the 3 vertices of the reference TRI and its 3 edge midpoints. DynRankView ConstructWithLabel(triNodes, 6, 2); // Generic array for the output values; needs to be properly resized depending on the operator type const ordinal_type numFields = triBasis.getCardinality(); const ordinal_type numPoints = triNodes.dimension(0); DynRankView vals; vals = DynRankView("vals", numFields, numPoints); // exception #1: GRAD cannot be applied to HDIV functions // resize vals to rank-3 container with dimensions (num. basis functions, num. points, arbitrary) INTREPID2_TEST_ERROR_EXPECTED( triBasis.getValues(vals, triNodes, OPERATOR_GRAD) ); // exception #2: CURL cannot be applied to HDIV functions INTREPID2_TEST_ERROR_EXPECTED( triBasis.getValues(vals, triNodes, OPERATOR_CURL) ); // Exceptions 3-7: all bf tags/bf Ids below are wrong and should cause getDofOrdinal() and // getDofTag() to access invalid array elements thereby causing bounds check exception // exception #3 INTREPID2_TEST_ERROR_EXPECTED( triBasis.getDofOrdinal(3,0,0) ); // exception #4 INTREPID2_TEST_ERROR_EXPECTED( triBasis.getDofOrdinal(1,1,1) ); // exception #5 INTREPID2_TEST_ERROR_EXPECTED( triBasis.getDofOrdinal(0,2,1) ); // exception #6 INTREPID2_TEST_ERROR_EXPECTED( triBasis.getDofTag(numFields) ); // exception #7 INTREPID2_TEST_ERROR_EXPECTED( triBasis.getDofTag(-1) ); // exception #8 INTREPID2_TEST_ERROR_EXPECTED( triBasis.getDofOrdinal(2,0,0) ); // Exceptions 9-16 test exception handling with incorrectly dimensioned input/output arrays // exception #9: input points array must be of rank-2 DynRankView ConstructWithLabel(badPoints1, 4, 5, 3); INTREPID2_TEST_ERROR_EXPECTED( triBasis.getValues(vals, badPoints1, OPERATOR_VALUE) ); // exception #10 dimension 1 in the input point array must equal space dimension of the cell DynRankView ConstructWithLabel(badPoints2, 4, triBasis.getBaseCellTopology().getDimension() + 1); INTREPID2_TEST_ERROR_EXPECTED( triBasis.getValues(vals, badPoints2, OPERATOR_VALUE) ); // exception #11 output values must be of rank-3 for OPERATOR_VALUE DynRankView ConstructWithLabel(badVals1, 4, 3); INTREPID2_TEST_ERROR_EXPECTED( triBasis.getValues(badVals1, triNodes, OPERATOR_VALUE) ); // exception #12 output values must be of rank-2 for OPERATOR_DIV DynRankView ConstructWithLabel(badVals2, 4, 3, 1); INTREPID2_TEST_ERROR_EXPECTED( triBasis.getValues(badVals2, triNodes, OPERATOR_VALUE) ); // exception #13 incorrect 0th dimension of output array for OPERATOR_VALUE (must equal number of basis functions) DynRankView ConstructWithLabel(badVals3, triBasis.getCardinality() + 1, triNodes.dimension(0), triBasis.getBaseCellTopology().getDimension()); INTREPID2_TEST_ERROR_EXPECTED( triBasis.getValues(badVals3, triNodes, OPERATOR_VALUE) ); // exception #14 incorrect 0th dimension of output array for OPERATOR_DIV (must equal number of basis functions) DynRankView ConstructWithLabel(badVals4, triBasis.getCardinality() + 1, triNodes.dimension(0)); INTREPID2_TEST_ERROR_EXPECTED( triBasis.getValues(badVals4, triNodes, OPERATOR_DIV) ); // exception #15 incorrect 1st dimension of output array (must equal number of points) DynRankView ConstructWithLabel(badVals5, triBasis.getCardinality(), triNodes.dimension(0) + 1, triBasis.getBaseCellTopology().getDimension()); INTREPID2_TEST_ERROR_EXPECTED( triBasis.getValues(badVals5, triNodes, OPERATOR_VALUE) ); // exception #16 incorrect 1st dimension of output array (must equal number of points) DynRankView ConstructWithLabel(badVals6, triBasis.getCardinality(), triNodes.dimension(0) + 1); INTREPID2_TEST_ERROR_EXPECTED( triBasis.getValues(badVals6, triNodes, OPERATOR_DIV) ); // exception #17: incorrect 2nd dimension of output array (must equal the space dimension) DynRankView ConstructWithLabel(badVals7, triBasis.getCardinality(), triNodes.dimension(0), triBasis.getBaseCellTopology().getDimension() + 1); INTREPID2_TEST_ERROR_EXPECTED( triBasis.getValues(badVals7, triNodes, OPERATOR_VALUE) ); #endif if (nthrow != ncatch) { errorFlag++; *outStream << std::setw(70) << "^^^^----FAILURE!" << "\n"; *outStream << "# of catch ("<< ncatch << ") is different from # of throw (" << nthrow << ")\n"; } } catch (std::logic_error err) { *outStream << "UNEXPECTED ERROR !!! ----------------------------------------------------------\n"; *outStream << err.what() << '\n'; *outStream << "-------------------------------------------------------------------------------" << "\n\n"; errorFlag = -1000; } *outStream << "\n" << "===============================================================================\n" << "| TEST 2: correctness of tag to enum and enum to tag lookups |\n" << "===============================================================================\n"; // all tags are on host space try { const ordinal_type numFields = triBasis.getCardinality(); const auto allTags = triBasis.getAllDofTags(); // Loop over all tags, lookup the associated dof enumeration and then lookup the tag again const ordinal_type dofTagSize = allTags.dimension(0); // Loop over all tags, lookup the associated dof enumeration and then lookup the tag again for (ordinal_type i = 0; i < dofTagSize; i++) { const auto bfOrd = triBasis.getDofOrdinal(allTags(i,0), allTags(i,1), allTags(i,2)); const auto myTag = triBasis.getDofTag(bfOrd); if( !( (myTag(0) == allTags(i, 0)) && (myTag(1) == allTags(i, 1)) && (myTag(2) == allTags(i, 2)) && (myTag(3) == allTags(i, 3)) ) ) { errorFlag++; *outStream << std::setw(70) << "^^^^----FAILURE!" << "\n"; *outStream << " getDofOrdinal( {" << allTags(i, 0) << ", " << allTags(i, 1) << ", " << allTags(i, 2) << ", " << allTags(i, 3) << "}) = " << bfOrd <<" but \n"; *outStream << " getDofTag(" << bfOrd << ") = { " << myTag(0) << ", " << myTag(1) << ", " << myTag(2) << ", " << myTag(3) << "}\n"; } } // Now do the same but loop over basis functions for( ordinal_type bfOrd = 0; bfOrd < numFields; bfOrd++) { auto myTag = triBasis.getDofTag(bfOrd); auto myBfOrd = triBasis.getDofOrdinal(myTag[0], myTag[1], myTag[2]); if( bfOrd != myBfOrd) { errorFlag++; *outStream << std::setw(70) << "^^^^----FAILURE!" << "\n"; *outStream << " getDofTag(" << bfOrd << ") = { " << myTag(0) << ", " << myTag(1) << ", " << myTag(2) << ", " << myTag(3) << "} but getDofOrdinal({" << myTag(0) << ", " << myTag(1) << ", " << myTag(2) << ", " << myTag(3) << "} ) = " << myBfOrd << "\n"; } } } catch (std::logic_error err) { *outStream << err.what() << "\n\n"; errorFlag = -1000; } *outStream \ << "\n" << "===============================================================================\n"\ << "| TEST 3: correctness of basis function values |\n"\ << "===============================================================================\n"; outStream -> precision(20); // VALUE: Correct basis values in (F,P,D) format: each group of two rows gives basis function // values at vertices followed by midpoints. This is the same array format as the output from getValues. double basisValues[] = { // basis function 0 at 3 vertices followed by 3 midpoints 0.0,-1.0, 1.0,-1.0, 0.0, 0.0, 0.5,-1.0, 0.5,-0.5, 0.0,-0.5, // basis function 1 at 3 vertices followed by 3 midpoints 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.5, 0.0, 0.5, 0.5, 0.0, 0.5, // basis function 2 at 3 vertices followed by 3 midpoints -1.0, 0.0, 0.0, 0.0, -1.0, 1.0, -0.5, 0.0, -0.5, 0.5, -1.0, 0.5 }; // DIV: each row gives the 3 correct values of the divergence of the 3 basis functions double basisDivs[] = { // 3 vertices 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, // 3 edge centers 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, }; try{ DynRankViewHost ConstructWithLabel(triNodesHost, 6, 2); triNodesHost(0,0) = 0.0; triNodesHost(0,1) = 0.0; triNodesHost(1,0) = 1.0; triNodesHost(1,1) = 0.0; triNodesHost(2,0) = 0.0; triNodesHost(2,1) = 1.0; // edge midpoints triNodesHost(3,0) = 0.5; triNodesHost(3,1) = 0.0; triNodesHost(4,0) = 0.5; triNodesHost(4,1) = 0.5; triNodesHost(5,0) = 0.0; triNodesHost(5,1) = 0.5; auto triNodes = Kokkos::create_mirror_view(typename DeviceSpaceType::memory_space(), triNodesHost); Kokkos::deep_copy(triNodes, triNodesHost); // Dimensions for the output arrays: const ordinal_type numFields = triBasis.getCardinality(); const ordinal_type numPoints = triNodes.dimension(0); const ordinal_type spaceDim = triBasis.getBaseCellTopology().getDimension(); { // Check VALUE of basis functions: resize vals to rank-3 container: DynRankView vals = DynRankView("vals", numFields, numPoints, spaceDim); triBasis.getValues(vals, triNodes, OPERATOR_VALUE); const auto vals_host = Kokkos::create_mirror_view(typename HostSpaceType::memory_space(), vals); Kokkos::deep_copy(vals_host, vals); for (ordinal_type i = 0; i < numFields; i++) { for (ordinal_type j = 0; j < numPoints; j++) { for (ordinal_type k = 0; k < spaceDim; k++) { // basisValues are in (F,P,D) format and the multiindex is (i,j,k), here's the offset: ordinal_type l = k + j * spaceDim + i * spaceDim * numPoints; if (std::abs(vals_host(i,j,k) - basisValues[l]) > tol) { errorFlag++; *outStream << std::setw(70) << "^^^^----FAILURE!" << "\n"; // Output the multi-index of the value where the error is: *outStream << " address = "<< l <<"\n"; *outStream << " At multi-index { "; *outStream << i << " ";*outStream << j << " ";*outStream << k << " "; *outStream << "} computed value: " << vals_host(i,j,k) << " but reference value: " << basisValues[l] << "\n"; } } } } } { // Check DIV of basis function: resize vals to rank-2 container DynRankView vals = DynRankView("vals", numFields, numPoints); triBasis.getValues(vals, triNodes, OPERATOR_DIV); const auto vals_host = Kokkos::create_mirror_view(typename HostSpaceType::memory_space(), vals); Kokkos::deep_copy(vals_host, vals); for (ordinal_type i = 0; i < numFields; i++) { for (ordinal_type j = 0; j < numPoints; j++) { ordinal_type l = i + j * numFields; if (std::abs(vals_host(i,j) - basisDivs[l]) > tol) { errorFlag++; *outStream << std::setw(70) << "^^^^----FAILURE!" << "\n"; // Output the multi-index of the value where the error is: *outStream << " At (Field,Point,Dim) multi-index { "; *outStream << i << " ";*outStream << j << " "; *outStream << "} computed divergence component: " << vals_host(i,j) << " but reference divergence component: " << basisDivs[l] << "\n"; } } } } } catch (std::logic_error err) { *outStream << err.what() << "\n\n"; errorFlag = -1000; } *outStream << "\n" << "===============================================================================\n" << "| TEST 4: DOF correctness (Kronecker property) |\n" << "===============================================================================\n"; try { const ordinal_type numFields = triBasis.getCardinality(); const ordinal_type spaceDim = triBasis.getBaseCellTopology().getDimension(); // Check exceptions. ordinal_type nthrow = 0, ncatch = 0; #ifdef HAVE_INTREPID2_DEBUG { DynRankView ConstructWithLabel(badVals, 1,2,3); INTREPID2_TEST_ERROR_EXPECTED( triBasis.getDofCoords(badVals)); } { DynRankView ConstructWithLabel(badVals, 4,2); INTREPID2_TEST_ERROR_EXPECTED( triBasis.getDofCoords(badVals)); } { DynRankView ConstructWithLabel(badVals, 3,3); INTREPID2_TEST_ERROR_EXPECTED( triBasis.getDofCoords(badVals)); } #endif if (nthrow != ncatch) { errorFlag++; *outStream << std::setw(70) << "^^^^----FAILURE!" << "\n"; *outStream << "# of catch ("<< ncatch << ") is different from # of throw (" << ncatch << ")\n"; } DynRankView ConstructWithLabel(bvals, numFields, numFields, spaceDim); DynRankView ConstructWithLabel(cvals, numFields, spaceDim); DynRankView ConstructWithLabel(dofCoeffs, numFields, spaceDim); // Check mathematical correctness. triBasis.getDofCoords(cvals); triBasis.getValues(bvals, cvals, OPERATOR_VALUE); triBasis.getDofCoeffs(dofCoeffs); auto cvals_host = Kokkos::create_mirror_view(typename HostSpaceType::memory_space(), cvals); Kokkos::deep_copy(cvals_host, cvals); auto bvals_host = Kokkos::create_mirror_view(typename HostSpaceType::memory_space(), bvals); Kokkos::deep_copy(bvals_host, bvals); auto dofCoeffs_host = Kokkos::create_mirror_view(typename HostSpaceType::memory_space(), dofCoeffs); Kokkos::deep_copy(dofCoeffs_host, dofCoeffs); for (ordinal_type i=0;i<numFields;++i) { for (ordinal_type j=0;j<numFields;++j) { ValueType dofValue = 0.0; for(ordinal_type d=0;d<spaceDim;++d) { dofValue += bvals_host(i,j,d)*dofCoeffs_host(j,d); } const ValueType expected_dofValue = (i == j); if (std::abs(dofValue - expected_dofValue) > tol || std::isnan(dofValue)) { errorFlag++; std::stringstream ss; ss << "\nDegree of freedom " << j << " of basis function " << i << " at (" << cvals_host(j,0) << ", " << cvals_host(j,1)<< ", " << cvals_host(j,2) << ") is " << dofValue << " but should be " << expected_dofValue << "\n"; *outStream << ss.str(); } } } } catch (std::logic_error err){ *outStream << err.what() << "\n\n"; errorFlag = -1000; }; if (errorFlag != 0) std::cout << "End Result: TEST FAILED\n"; else std::cout << "End Result: TEST PASSED\n"; // reset format state of std::cout std::cout.copyfmt(oldFormatState); return errorFlag; }
int HCURL_TRI_I1_FEM_Test01(const bool verbose) { Teuchos::RCP<std::ostream> outStream; Teuchos::oblackholestream bhs; // outputs nothing if (verbose) outStream = Teuchos::rcp(&std::cout, false); else outStream = Teuchos::rcp(&bhs, false); Teuchos::oblackholestream oldFormatState; oldFormatState.copyfmt(std::cout); typedef typename Kokkos::Impl::is_space<DeviceSpaceType>::host_mirror_space::execution_space HostSpaceType ; *outStream << "DeviceSpace:: "; DeviceSpaceType::print_configuration(*outStream, false); *outStream << "HostSpace:: "; HostSpaceType::print_configuration(*outStream, false); *outStream << "===============================================================================\n" << "| |\n" << "| Unit Test (Basis_HCURL_TRI_I1_FEM) |\n" << "| |\n" << "| 1) Conversion of Dof tags into Dof ordinals and back |\n" << "| 2) Basis values for VALUE and CURL operators |\n" << "| |\n" << "| Questions? Contact Pavel Bochev ([email protected]), |\n" << "| Denis Ridzal ([email protected]), |\n" << "| Kara Peterson ([email protected]). |\n" << "| Kyungjoo Kim ([email protected]). |\n" << "| |\n" << "| Intrepid's website: http://trilinos.sandia.gov/packages/intrepid |\n" << "| Trilinos website: http://trilinos.sandia.gov |\n" << "| |\n" << "===============================================================================\n"; typedef Kokkos::DynRankView<ValueType,DeviceSpaceType> DynRankView; typedef Kokkos::DynRankView<ValueType,HostSpaceType> DynRankViewHost; #define ConstructWithLabel(obj, ...) obj(#obj, __VA_ARGS__) const ValueType tol = tolerence(); int errorFlag = 0; // for virtual function, value and point types are declared in the class typedef ValueType outputValueType; typedef ValueType pointValueType; Basis_HCURL_TRI_I1_FEM<DeviceSpaceType,outputValueType,pointValueType> triBasis; *outStream << "\n" << "===============================================================================\n" << "| TEST 1: Basis creation, exception testing |\n" << "===============================================================================\n"; try{ ordinal_type nthrow = 0, ncatch = 0; #ifdef HAVE_INTREPID2_DEBUG // Define array containing the 3 vertices of the reference TRI and its 3 edge midpoints. DynRankView ConstructWithLabel(triNodes, 7, 2); // Generic array for the output values; needs to be properly resized depending on the operator type const ordinal_type cardinality = triBasis.getCardinality(); const ordinal_type numPoints = triNodes.extent(0); DynRankView vals; vals = DynRankView("vals", cardinality, numPoints); { // exception #1: GRAD cannot be applied to HCURL functions INTREPID2_TEST_ERROR_EXPECTED( triBasis.getValues(vals, triNodes, OPERATOR_GRAD) ); } { // exception #2: DIV cannot be applied to HCURL functions INTREPID2_TEST_ERROR_EXPECTED( triBasis.getValues(vals, triNodes, OPERATOR_DIV) ); } // Exceptions 3-7: all bf tags/bf Ids below are wrong and should cause getDofOrdinal() and // getDofTag() to access invalid array elements thereby causing bounds check exception { // exception #3 INTREPID2_TEST_ERROR_EXPECTED( triBasis.getDofOrdinal(3,0,0) ); // exception #4 INTREPID2_TEST_ERROR_EXPECTED( triBasis.getDofOrdinal(1,1,1) ); // exception #5 INTREPID2_TEST_ERROR_EXPECTED( triBasis.getDofOrdinal(0,4,1) ); // exception #6 INTREPID2_TEST_ERROR_EXPECTED( triBasis.getDofTag(cardinality) ); // exception #7 INTREPID2_TEST_ERROR_EXPECTED( triBasis.getDofTag(-1) ); } // Exceptions 8-15 test exception handling with incorrectly dimensioned input/output arrays { // exception #8: input points array must be of rank-2 DynRankView ConstructWithLabel(badPoints1, 4, 5, 3); INTREPID2_TEST_ERROR_EXPECTED( triBasis.getValues(vals, badPoints1, OPERATOR_VALUE) ); } // exception #9 dimension 1 in the input point array must equal space dimension of the cell { DynRankView ConstructWithLabel(badPoints2, 4, triBasis.getBaseCellTopology().getDimension() + 1); INTREPID2_TEST_ERROR_EXPECTED( triBasis.getValues(vals, badPoints2, OPERATOR_VALUE) ); } { // exception #10 output values must be of rank-3 for OPERATOR_VALUE in 2D DynRankView ConstructWithLabel(badVals1, 4, 3); INTREPID2_TEST_ERROR_EXPECTED( triBasis.getValues(badVals1, triNodes, OPERATOR_VALUE) ); } { // exception #11 output values must be of rank-2 for OPERATOR_CURL DynRankView ConstructWithLabel(badCurls1,4,3,2); INTREPID2_TEST_ERROR_EXPECTED( triBasis.getValues(badCurls1, triNodes, OPERATOR_CURL) ); } { // exception #12 incorrect 0th dimension of output array (must equal number of basis functions) DynRankView ConstructWithLabel(badVals2, triBasis.getCardinality() + 1, triNodes.extent(0), triBasis.getBaseCellTopology().getDimension()); INTREPID2_TEST_ERROR_EXPECTED( triBasis.getValues(badVals2, triNodes, OPERATOR_VALUE) ) ; } { // exception #13 incorrect 1st dimension of output array (must equal number of points) DynRankView ConstructWithLabel(badVals3, triBasis.getCardinality(), triNodes.extent(0) + 1, triBasis.getBaseCellTopology().getDimension() ); INTREPID2_TEST_ERROR_EXPECTED( triBasis.getValues(badVals3, triNodes, OPERATOR_VALUE) ) ; } { // exception #14: incorrect 2nd dimension of output array for VALUE (must equal the space dimension) DynRankView ConstructWithLabel(badVals4, triBasis.getCardinality(), triNodes.extent(0), triBasis.getBaseCellTopology().getDimension() - 1); INTREPID2_TEST_ERROR_EXPECTED( triBasis.getValues(badVals4, triNodes, OPERATOR_VALUE) ) ; } // exception #15: D2 cannot be applied to HCURL functions // resize vals to rank-3 container with dimensions (num. basis functions, num. points, arbitrary) // vals.resize(triBasis.getCardinality(), // triNodes.extent(0), // Intrepid2::getDkCardinality(OPERATOR_D2, triBasis.getBaseCellTopology().getDimension())); // INTREPID2_TEST_ERROR_EXPECTED( triBasis.getValues(vals, triNodes, OPERATOR_D2) ); #endif // Check if number of thrown exceptions matches the one we expect if (nthrow != ncatch) { errorFlag++; *outStream << std::setw(70) << "^^^^----FAILURE!" << "\n"; *outStream << "# of catch ("<< ncatch << ") is different from # of throw (" << nthrow << ")\n"; } } catch (std::logic_error err) { *outStream << "UNEXPECTED ERROR !!! ----------------------------------------------------------\n"; *outStream << err.what() << '\n'; *outStream << "-------------------------------------------------------------------------------" << "\n\n"; errorFlag = -1000; } *outStream << "\n" << "===============================================================================\n" << "| TEST 2: correctness of tag to enum and enum to tag lookups |\n" << "===============================================================================\n"; // all tags are on host space try{ const auto allTags = triBasis.getAllDofTags(); // Loop over all tags, lookup the associated dof enumeration and then lookup the tag again const ordinal_type dofTagSize = allTags.extent(0); for (ordinal_type i = 0; i < dofTagSize; ++i) { const auto bfOrd = triBasis.getDofOrdinal(allTags(i,0), allTags(i,1), allTags(i,2)); const auto myTag = triBasis.getDofTag(bfOrd); if( !( (myTag(0) == allTags(i,0)) && (myTag(1) == allTags(i,1)) && (myTag(2) == allTags(i,2)) && (myTag(3) == allTags(i,3)) ) ) { errorFlag++; *outStream << std::setw(70) << "^^^^----FAILURE!" << "\n"; *outStream << " getDofOrdinal( {" << allTags(i,0) << ", " << allTags(i,1) << ", " << allTags(i,2) << ", " << allTags(i,3) << "}) = " << bfOrd <<" but \n"; *outStream << " getDofTag(" << bfOrd << ") = { " << myTag(0) << ", " << myTag(1) << ", " << myTag(2) << ", " << myTag(3) << "}\n"; } } // Now do the same but loop over basis functions for( ordinal_type bfOrd = 0; bfOrd < triBasis.getCardinality(); bfOrd++) { const auto myTag = triBasis.getDofTag(bfOrd); const auto myBfOrd = triBasis.getDofOrdinal(myTag(0), myTag(1), myTag(2)); if( bfOrd != myBfOrd) { errorFlag++; *outStream << std::setw(70) << "^^^^----FAILURE!" << "\n"; *outStream << " getDofTag(" << bfOrd << ") = { " << myTag(0) << ", " << myTag(1) << ", " << myTag(2) << ", " << myTag(3) << "} but getDofOrdinal({" << myTag(0) << ", " << myTag(1) << ", " << myTag(2) << ", " << myTag(3) << "} ) = " << myBfOrd << "\n"; } } } catch (std::logic_error err){ *outStream << err.what() << "\n\n"; errorFlag = -1000; }; *outStream << "\n" << "===============================================================================\n" << "| TEST 3: correctness of basis function values |\n" << "===============================================================================\n"; outStream -> precision(20); // VALUE: correct values in (P,F,D) layout const ValueType basisValues[] = { 1.000, 0, 0, 0, 0, -1.000, 1.000, 1.000, 0, 1.000, 0, 0, 0, 0, \ -1.000, 0, -1.000, -1.000, 1.000, 0.5000, 0, 0.5000, 0, -0.5000, \ 0.5000, 0.5000, -0.5000, 0.5000, -0.5000, -0.5000, 0.5000, 0, \ -0.5000, 0, -0.5000, -1.000, 0.7500, 0.2500, -0.2500, 0.2500, \ -0.2500, -0.7500}; // CURL: correct values in (P,F) layout const ValueType basisCurls[] = { 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0 }; try{ DynRankViewHost ConstructWithLabel(triNodesHost, 7, 2); triNodesHost(0,0) = 0.0; triNodesHost(0,1) = 0.0; triNodesHost(1,0) = 1.0; triNodesHost(1,1) = 0.0; triNodesHost(2,0) = 0.0; triNodesHost(2,1) = 1.0; // edge midpoints triNodesHost(3,0) = 0.5; triNodesHost(3,1) = 0.0; triNodesHost(4,0) = 0.5; triNodesHost(4,1) = 0.5; triNodesHost(5,0) = 0.0; triNodesHost(5,1) = 0.5; // Inside Triangle triNodesHost(6,0) = 0.25; triNodesHost(6,1) = 0.25; auto triNodes = Kokkos::create_mirror_view(typename DeviceSpaceType::memory_space(), triNodesHost); Kokkos::deep_copy(triNodes, triNodesHost); // Dimensions for the output arrays: const ordinal_type cardinality = triBasis.getCardinality(); const ordinal_type numPoints = triNodes.extent(0); const ordinal_type spaceDim = triBasis.getBaseCellTopology().getDimension(); { // Check VALUE of basis functions: resize vals to rank-3 container: DynRankView ConstructWithLabel(vals, cardinality, numPoints, spaceDim); triBasis.getValues(vals, triNodes, OPERATOR_VALUE); auto vals_host = Kokkos::create_mirror_view(typename HostSpaceType::memory_space(), vals); Kokkos::deep_copy(vals_host, vals); for (ordinal_type i = 0; i < cardinality; ++i) { for (ordinal_type j = 0; j < numPoints; ++j) { for (ordinal_type k = 0; k < spaceDim; ++k) { // compute offset for (P,F,D) data layout: indices are P->j, F->i, D->k ordinal_type l = k + i * spaceDim + j * spaceDim * cardinality; if (std::abs(vals_host(i,j,k) - basisValues[l]) > tol) { errorFlag++; *outStream << std::setw(70) << "^^^^----FAILURE!" << "\n"; // Output the multi-index of the value where the error is: *outStream << " At multi-index { "; *outStream << i << " ";*outStream << j << " ";*outStream << k << " "; *outStream << "} computed value: " << vals_host(i,j,k) << " but reference value: " << basisValues[l] << "\n"; } } } } } { // Check CURL of basis function: resize vals to rank-2 container DynRankView ConstructWithLabel(vals, cardinality, numPoints); triBasis.getValues(vals, triNodes, OPERATOR_CURL); auto vals_host = Kokkos::create_mirror_view(typename HostSpaceType::memory_space(), vals); Kokkos::deep_copy(vals_host, vals); for (ordinal_type i = 0; i < cardinality; ++i) { for (ordinal_type j = 0; j < numPoints; ++j) { ordinal_type l = i + j * cardinality; if (std::abs(vals_host(i,j) - basisCurls[l]) > tol) { errorFlag++; *outStream << std::setw(70) << "^^^^----FAILURE!" << "\n"; // Output the multi-index of the value where the error is: *outStream << " At multi-index { "; *outStream << i << " ";*outStream << j << " "; *outStream << "} computed curl component: " << vals_host(i,j) << " but reference curl component: " << basisCurls[l] << "\n"; } } } } } //end try // Catch unexpected errors catch (std::logic_error err) { *outStream << err.what() << "\n\n"; errorFlag = -1000; }; *outStream << "\n" << "===============================================================================\n" << "| TEST 4: correctness of DoF locations |\n" << "===============================================================================\n"; try{ const ordinal_type cardinality = triBasis.getCardinality(); const ordinal_type spaceDim = triBasis.getBaseCellTopology().getDimension(); // Check exceptions. ordinal_type nthrow = 0, ncatch = 0; #ifdef HAVE_INTREPID2_DEBUG { DynRankView ConstructWithLabel(badVals, 1, 2, 3); INTREPID2_TEST_ERROR_EXPECTED( triBasis.getDofCoords(badVals) ); } { DynRankView ConstructWithLabel(badVals, 4, 2); INTREPID2_TEST_ERROR_EXPECTED( triBasis.getDofCoords(badVals) ); } { DynRankView ConstructWithLabel(badVals, 4, 3); INTREPID2_TEST_ERROR_EXPECTED( triBasis.getDofCoords(badVals) ); } #endif // Check if number of thrown exceptions matches the one we expect if (nthrow != ncatch) { errorFlag++; *outStream << std::setw(70) << "^^^^----FAILURE!" << "\n"; *outStream << "# of catch ("<< ncatch << ") is different from # of throw (" << ncatch << ")\n"; } // Check mathematical correctness DynRankView ConstructWithLabel(bvals, cardinality, cardinality, spaceDim); DynRankView ConstructWithLabel(cvals, cardinality, spaceDim); DynRankView ConstructWithLabel(dofCoeffs, cardinality, spaceDim); triBasis.getDofCoeffs(dofCoeffs); triBasis.getDofCoords(cvals); triBasis.getValues(bvals, cvals, OPERATOR_VALUE); auto cvals_host = Kokkos::create_mirror_view(typename HostSpaceType::memory_space(), cvals); Kokkos::deep_copy(cvals_host, cvals); auto dofCoeffs_host = Kokkos::create_mirror_view(typename HostSpaceType::memory_space(), dofCoeffs); Kokkos::deep_copy(dofCoeffs_host, dofCoeffs); auto bvals_host = Kokkos::create_mirror_view(typename HostSpaceType::memory_space(), bvals); Kokkos::deep_copy(bvals_host, bvals); char buffer[120]; for (ordinal_type i=0; i<cardinality; ++i) { for (ordinal_type j=0; j<cardinality; ++j) { double dofValue = 0.0; for(ordinal_type d=0;d<spaceDim;++d) dofValue += bvals_host(i,j,d)*dofCoeffs_host(j,d); if ((i != j) && (std::abs(dofValue - 0.0) > tol )) { errorFlag++; sprintf(buffer, "\nValue of basis function %d at (%6.4e, %6.4e) is %6.4e but should be %6.4e!\n", i, cvals_host(i,0), cvals_host(i,1), dofValue, 0.0); *outStream << buffer; } else if ((i == j) && (std::abs(dofValue - 1.0) > tol )) { errorFlag++; sprintf(buffer, "\nValue of basis function %d at (%6.4e, %6.4e) is %6.4e but should be %6.4e!\n", i, cvals_host(i,0), cvals_host(i,1), dofValue, 1.0); *outStream << buffer; } } } } catch (std::logic_error err){ *outStream << err.what() << "\n\n"; errorFlag = -1000; }; if (errorFlag != 0) std::cout << "End Result: TEST FAILED\n"; else std::cout << "End Result: TEST PASSED\n"; // reset format state of std::cout std::cout.copyfmt(oldFormatState); return errorFlag; }