diff --git a/CMakeLists.txt b/CMakeLists.txt index 99ff8b3..54fa803 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -9,9 +9,6 @@ option(MeshFields_USE_Cabana "Build with the Cabana storage backend" OFF) find_package(Kokkos REQUIRED) find_package(Omega_h REQUIRED) -#Clear the omegah compilation flags that it passes to cuda. Using the -# kokkos target, and nvcc_wrapper, provide sufficient flags. -set_property(TARGET Omega_h::omega_h PROPERTY INTERFACE_COMPILE_OPTIONS "") if(MeshFields_USE_Cabana) find_package(Cabana 0.7.0 REQUIRED) @@ -112,8 +109,8 @@ endif() enable_testing() include(CTest) -option(IS_TESTING "Build for CTest" OFF) -message(STATUS "IS_TESTING: ${IS_TESTING}") +option(MeshFields_IS_TESTING "Build for CTest" OFF) +message(STATUS "MeshFields_IS_TESTING: ${MeshFields_IS_TESTING}") #check for valgrind find_program(VALGRIND_CMD valgrind DOC "Location of the valgrind program") @@ -124,72 +121,87 @@ function(test_func_impl TEST_NAME) # need to run as a cmake script to capture assert and other 'system failures' # https://cmake.org/cmake/help/latest/prop_test/WILL_FAIL.html#prop_test:WILL_FAIL add_test(NAME ${TEST_NAME} COMMAND ${CMAKE_COMMAND} -E env ${TEST_STR}) + if(TEST ${TEST_NAME}) + set_property(TEST ${TEST_NAME} PROPERTY LABELS "meshfields::base") + endif() endfunction(test_func_impl) -function(test_func TEST_NAME) +#smoke tests that are always enabled +function(smoke_test_func TEST_NAME) test_func_impl(${TEST_NAME} ${ARGN}) if(TEST ${TEST_NAME}) - set_property(TEST ${TEST_NAME} PROPERTY LABELS "base") + set_property(TEST ${TEST_NAME} PROPERTY LABELS "meshfields::smoke") + endif() +endfunction(smoke_test_func) + +function(test_func TEST_NAME) + if(MeshFields_IS_TESTING) + test_func_impl(${TEST_NAME} ${ARGN}) endif() endfunction(test_func) # Unlike test_func, will_fail_test_func assumes the command for the test will fail function(will_fail_test_func TEST_NAME) - test_func_impl(${TEST_NAME} ${ARGN}) - set_property(TEST ${TEST_NAME} PROPERTY WILL_FAIL TRUE) - if(TEST ${TEST_NAME}) - set_property(TEST ${TEST_NAME} PROPERTY LABELS "base") + if(MeshFields_IS_TESTING) + test_func_impl(${TEST_NAME} ${ARGN}) + set_property(TEST ${TEST_NAME} PROPERTY WILL_FAIL TRUE) endif() endfunction() function(will_fail_valgrind_test_func TEST_NAME) - if(VALGRIND_CMD) - test_func_impl(${TEST_NAME} ${VALGRIND_CMD} ${ARGN}) - set_property(TEST ${TEST_NAME} PROPERTY - FAIL_REGULAR_EXPRESSION "Invalid read;Invalid write" - ) - set_property(TEST ${TEST_NAME} PROPERTY WILL_FAIL TRUE) - if(TEST ${TEST_NAME}) - set_property(TEST ${TEST_NAME} PROPERTY LABELS "base") + if(MeshFields_IS_TESTING) + if(VALGRIND_CMD) + test_func_impl(${TEST_NAME} ${VALGRIND_CMD} ${ARGN}) + set_property(TEST ${TEST_NAME} PROPERTY + FAIL_REGULAR_EXPRESSION "Invalid read;Invalid write" + ) + set_property(TEST ${TEST_NAME} PROPERTY WILL_FAIL TRUE) endif() endif() endfunction() -function(meshfields_add_exe EXE_NAME EXE_SRC) +#smoke executables are always built +function(meshfields_add_smoke_exe EXE_NAME EXE_SRC) add_executable(${EXE_NAME} ${EXE_SRC}) target_link_libraries(${EXE_NAME} PRIVATE meshfields) endfunction() -# Creating minimal reproduction of error -meshfields_add_exe(KokkosTests test/testKokkos.cpp) +function(meshfields_add_exe EXE_NAME EXE_SRC) + if(MeshFields_IS_TESTING) + add_executable(${EXE_NAME} ${EXE_SRC}) + target_link_libraries(${EXE_NAME} PRIVATE meshfields) + endif() +endfunction() + +meshfields_add_smoke_exe(KokkosTests test/testKokkos.cpp) meshfields_add_exe(SerializationTests test/testSerialize.cpp) meshfields_add_exe(ElementTests test/testElement.cpp) meshfields_add_exe(ElementJacobian1d test/testElementJacobian1d.cpp) meshfields_add_exe(ElementJacobian2d test/testElementJacobian2d.cpp) meshfields_add_exe(ElementJacobian3d test/testElementJacobian3d.cpp) meshfields_add_exe(CountIntegrator test/testCountIntegrator.cpp) -meshfields_add_exe(OmegahTriTests test/testOmegahTri.cpp) +meshfields_add_smoke_exe(OmegahTriTests test/testOmegahTri.cpp) meshfields_add_exe(ExceptionTest test/testExceptions.cpp) meshfields_add_exe(PointMapping test/testPointMapping.cpp) meshfields_add_exe(OmegahTetTest test/testOmegahTet.cpp) if(MeshFields_USE_Cabana) meshfields_add_exe(ControllerPerformance test/testControllerPerformance.cpp) - meshfields_add_exe(CabanaTests test/testCabana.cpp) - test_func(CabanaTests ./CabanaTests) + meshfields_add_smoke_exe(CabanaTests test/testCabana.cpp) + smoke_test_func(CabanaTests ./CabanaTests) test_func(ControllerPerformance ./ControllerPerformance) endif() -test_func(KokkosTests ./KokkosTests) +smoke_test_func(KokkosTests ./KokkosTests) test_func(SerializationTests ./SerializationTests) test_func(ElementTests ./ElementTests) test_func(ElementJacobian1d ./ElementJacobian1d) test_func(ElementJacobian2d ./ElementJacobian2d) test_func(ElementJacobian3d ./ElementJacobian3d) test_func(CountIntegrator ./CountIntegrator) -test_func(OmegahTriTests ./OmegahTriTests) +smoke_test_func(OmegahTriTests ./OmegahTriTests) test_func(PointMapping ./PointMapping) -test_func(OmegahTetTest, ./OmegahTetTest) +test_func(OmegahTetTest ./OmegahTetTest) if(MeshFields_USE_EXCEPTIONS) # exception caught - no error test_func(ExceptionTest ./ExceptionTest) diff --git a/src/MeshField_Element.hpp b/src/MeshField_Element.hpp index 2197a0a..d7612bf 100644 --- a/src/MeshField_Element.hpp +++ b/src/MeshField_Element.hpp @@ -170,14 +170,15 @@ struct FieldElement { */ KOKKOS_INLINE_FUNCTION ValArray getValue(int ent, Kokkos::Array localCoord) const { - assert(ent < numMeshEnts); + assert(ent >= 0); + assert(static_cast(ent) < numMeshEnts); ValArray c; const auto shapeValues = shapeFn.getValues(localCoord); - for (int ci = 0; ci < NumComponents; ++ci) + for (size_t ci = 0; ci < NumComponents; ++ci) c[ci] = 0; for (auto topo : elm2dof.getTopology()) { // element topology - for (int ni = 0; ni < shapeFn.numNodes; ++ni) { - for (int ci = 0; ci < NumComponents; ++ci) { + for (size_t ni = 0; ni < shapeFn.numNodes; ++ni) { + for (size_t ci = 0; ci < NumComponents; ++ci) { auto map = elm2dof(ni, ci, ent, topo); const auto fval = field(map.entity, map.node, map.component, map.topo); @@ -194,8 +195,8 @@ struct FieldElement { KOKKOS_INLINE_FUNCTION NodeArray getNodeValues(int ent) const { NodeArray c; for (auto topo : elm2dof.getTopology()) { // element topology - for (int ni = 0; ni < ShapeType::numNodes; ++ni) { - for (int d = 0; d < ShapeType::meshEntDim; ++d) { + for (size_t ni = 0; ni < ShapeType::numNodes; ++ni) { + for (size_t d = 0; d < ShapeType::meshEntDim; ++d) { auto map = elm2dof(ni, d, ent, topo); const auto fval = field(map.entity, map.node, map.component, map.topo); @@ -219,11 +220,12 @@ struct FieldElement { * @return the result of evaluation */ KOKKOS_INLINE_FUNCTION Real getJacobian1d(int ent) const { - assert(ent < numMeshEnts); + assert(ent >= 0); + assert(static_cast(ent) < numMeshEnts); const auto nodalGradients = shapeFn.getLocalGradients(); const auto nodeValues = getNodeValues(ent); auto g = nodalGradients[0] * nodeValues[0]; - for (int i = 1; i < shapeFn.numNodes; ++i) { + for (size_t i = 1; i < shapeFn.numNodes; ++i) { g = g + nodalGradients[i] * nodeValues[i]; } return g; @@ -328,7 +330,7 @@ struct FieldElement { KOKKOS_LAMBDA(const int &ent, LO &lerrors) { Real sum = 0; LO isError = 0; - for (int i = 0; i < localCoords.extent(1); i++) { + for (size_t i = 0; i < localCoords.extent(1); i++) { if (localCoords(ent, i) < 0) isError++; sum += localCoords(ent, i); @@ -449,7 +451,7 @@ evaluate(FieldElement &fes, Kokkos::View localCoords, KOKKOS_LAMBDA(const int &ent, LO &lerrors) { Real sum = 0; LO isError = 0; - for (int i = 0; i < localCoords.extent(1); i++) { + for (size_t i = 0; i < localCoords.extent(1); i++) { if (localCoords(ent, i) < 0) isError++; sum += localCoords(ent, i); @@ -477,7 +479,7 @@ evaluate(FieldElement &fes, Kokkos::View localCoords, LO numLocalCoords; Kokkos::deep_copy(numLocalCoords, Kokkos::subview(offsets, offsets.size() - 1)); - if (localCoords.extent(0) != numLocalCoords) { + if (localCoords.extent(0) != static_cast(numLocalCoords)) { fail("The size of dimension 0 of the local coordinates input array (%zu) " "does not match the last entry of the offsets array (%d).\n", localCoords.extent(0), numLocalCoords); @@ -491,10 +493,10 @@ evaluate(FieldElement &fes, Kokkos::View localCoords, Kokkos::Array lc; // TODO use nested parallel for? for (auto pt = offsets(ent); pt < offsets(ent + 1); pt++) { - for (int i = 0; i < localCoords.extent(1); i++) // better way? + for (size_t i = 0; i < localCoords.extent(1); i++) // better way? lc[i] = localCoords(pt, i); const auto val = fes.getValue(ent, lc); - for (int i = 0; i < numComponents; i++) + for (size_t i = 0; i < numComponents; i++) res(pt, i) = val[i]; } }); diff --git a/src/MeshField_Field.hpp b/src/MeshField_Field.hpp index f56b721..907a94d 100644 --- a/src/MeshField_Field.hpp +++ b/src/MeshField_Field.hpp @@ -115,7 +115,7 @@ template class Field { * @return the size/extent */ KOKKOS_INLINE_FUNCTION - auto size(int i) const { return slice.size(i); } + size_t size(int i) const { return slice.size(i); } /** * access the underlying field at the specified index diff --git a/src/MeshField_Integrate.hpp b/src/MeshField_Integrate.hpp index 0c16d68..100f268 100644 --- a/src/MeshField_Integrate.hpp +++ b/src/MeshField_Integrate.hpp @@ -159,7 +159,6 @@ Kokkos::View getIntegrationPointWeights( std::vector> ip) { const auto numPtsPerElm = ip.size(); const auto numMeshEnts = fes.numMeshEnts; - const auto meshEntDim = fes.MeshEntDim; Kokkos::View weights("weights", numMeshEnts * numPtsPerElm); // broadcast the points into the view - FIXME this is an inefficient use of // memory diff --git a/src/MeshField_Shape.hpp b/src/MeshField_Shape.hpp index ceafda5..e724809 100644 --- a/src/MeshField_Shape.hpp +++ b/src/MeshField_Shape.hpp @@ -8,7 +8,7 @@ namespace { template KOKKOS_INLINE_FUNCTION bool sumsToOne(Array &xi) { auto sum = 0.0; - for (int i = 0; i < xi.size(); i++) { + for (size_t i = 0; i < xi.size(); i++) { sum += xi[i]; } return (Kokkos::fabs(sum - 1) <= MeshField::MachinePrecision); @@ -17,7 +17,7 @@ template KOKKOS_INLINE_FUNCTION bool sumsToOne(Array &xi) { template KOKKOS_INLINE_FUNCTION bool greaterThanOrEqualZero(Array &xi) { auto gt = true; - for (int i = 0; i < xi.size(); i++) { + for (size_t i = 0; i < xi.size(); i++) { gt = gt && (xi[i] >= 0); } return gt; diff --git a/test/testCountIntegrator.cpp b/test/testCountIntegrator.cpp index c6361b0..669a656 100644 --- a/test/testCountIntegrator.cpp +++ b/test/testCountIntegrator.cpp @@ -74,7 +74,7 @@ void doRun(Omega_h::Mesh &mesh, CountIntegrator countInt(fes); countInt.process(fes); - assert(mesh.nelems() == countInt.getCount()); + assert(static_cast(mesh.nelems()) == countInt.getCount()); } int main(int argc, char **argv) { diff --git a/test/testKokkos.cpp b/test/testKokkos.cpp index 89d9eb0..3f35cd2 100644 --- a/test/testKokkos.cpp +++ b/test/testKokkos.cpp @@ -338,7 +338,7 @@ void kokkosControllerSizeTest() { void kokkosFieldSizeTest() { printf("== START kokkosFieldSizeTest ==\n"); const int a = 5, b = 4, c = 3, d = 2, e = 1; - const int psi[5] = {a, b, c, d, e}; + const size_t psi[5] = {a, b, c, d, e}; { using simple_static = MeshField::KokkosController @@ -96,7 +96,7 @@ void setVertices(Omega_h::Mesh &mesh, AnalyticFunction func, ShapeField field) { const auto x = coords[vtx * MeshDim]; const auto y = coords[vtx * MeshDim + 1]; const auto z = coords[vtx * MeshDim + 2]; - for (int i = 0; i < field.numComp; ++i) { + for (size_t i = 0; i < field.numComp; ++i) { field(vtx, 0, i, MeshField::Vertex) = func(x, y, z); } }; @@ -121,7 +121,7 @@ void setEdges(Omega_h::Mesh &mesh, AnalyticFunction func, ShapeField field) { (coords[left * MeshDim + 1] + coords[right * MeshDim + 1]) / 2.0; const auto z = (coords[left * MeshDim + 2] + coords[right * MeshDim + 2]) / 2.0; - for (int i = 0; i < field.numComp; ++i) { + for (size_t i = 0; i < field.numComp; ++i) { field(edge, 0, i, MeshField::Edge) = func(x, y, z); } }; @@ -137,7 +137,7 @@ createElmAreaCoords(size_t numElements, numElements * NumPtsPerElem); Kokkos::parallel_for( "setLocalCoords", numElements, KOKKOS_LAMBDA(const int &elm) { - for (int pt = 0; pt < NumPtsPerElem; pt++) { + for (size_t pt = 0; pt < NumPtsPerElem; pt++) { lc(elm * NumPtsPerElem + pt, 0) = coords[pt * 4 + 0]; lc(elm * NumPtsPerElem + pt, 1) = coords[pt * 4 + 1]; lc(elm * NumPtsPerElem + pt, 2) = coords[pt * 4 + 2]; diff --git a/test/testOmegahTri.cpp b/test/testOmegahTri.cpp index 8e055ed..7c261df 100644 --- a/test/testOmegahTri.cpp +++ b/test/testOmegahTri.cpp @@ -64,7 +64,7 @@ bool checkResult(Omega_h::Mesh &mesh, Result &result, CoordField coordField, const auto x = globalCoords(pt, 0); const auto y = globalCoords(pt, 1); const auto expected = func(x, y); - for (int i = 0; i < numComp; ++i) { + for (size_t i = 0; i < numComp; ++i) { const auto computed = result(pt, i); MeshField::LO isError = 0; if (Kokkos::fabs(computed - expected) > @@ -92,7 +92,7 @@ void setVertices(Omega_h::Mesh &mesh, AnalyticFunction func, ShapeField field) { // - TODO should be encoded in the field? const auto x = coords[vtx * MeshDim]; const auto y = coords[vtx * MeshDim + 1]; - for (int i = 0; i < field.numComp; ++i) { + for (size_t i = 0; i < field.numComp; ++i) { field(vtx, 0, i, MeshField::Vertex) = func(x, y); } }; @@ -115,7 +115,7 @@ void setEdges(Omega_h::Mesh &mesh, AnalyticFunction func, ShapeField field) { const auto x = (coords[left * MeshDim] + coords[right * MeshDim]) / 2.0; const auto y = (coords[left * MeshDim + 1] + coords[right * MeshDim + 1]) / 2.0; - for (int i = 0; i < field.numComp; ++i) { + for (size_t i = 0; i < field.numComp; ++i) { field(edge, 0, i, MeshField::Edge) = func(x, y); } }; @@ -131,7 +131,7 @@ createElmAreaCoords(size_t numElements, numElements * NumPtsPerElem); Kokkos::parallel_for( "setLocalCoords", numElements, KOKKOS_LAMBDA(const int &elm) { - for (int pt = 0; pt < NumPtsPerElem; pt++) { + for (size_t pt = 0; pt < NumPtsPerElem; pt++) { lc(elm * NumPtsPerElem + pt, 0) = coords[pt * 3 + 0]; lc(elm * NumPtsPerElem + pt, 1) = coords[pt * 3 + 1]; lc(elm * NumPtsPerElem + pt, 2) = coords[pt * 3 + 2];