Merge branch 'master' of https://gitlab.kitware.com/vtk/vtk-m into add-16-cell-metrics

This commit is contained in:
Hank Childs 2019-09-23 22:21:32 -07:00
commit 338b87d9f8
262 changed files with 12425 additions and 3856 deletions

@ -1,539 +0,0 @@
##============================================================================
## Copyright (c) Kitware, Inc.
## All rights reserved.
## See LICENSE.txt for details.
##
## This software is distributed WITHOUT ANY WARRANTY; without even
## the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
## PURPOSE. See the above copyright notice for more information.
##============================================================================
#.rst:
# FindOpenMP
# ----------
#
# Finds OpenMP support
#
# This module can be used to detect OpenMP support in a compiler. If
# the compiler supports OpenMP, the flags required to compile with
# OpenMP support are returned in variables for the different languages.
# The variables may be empty if the compiler does not need a special
# flag to support OpenMP.
#
# Variables
# ^^^^^^^^^
#
# The module exposes the components ``C``, ``CXX``, and ``Fortran``.
# Each of these controls the various languages to search OpenMP support for.
#
# Depending on the enabled components the following variables will be set:
#
# ``OpenMP_FOUND``
# Variable indicating that OpenMP flags for all requested languages have been found.
# If no components are specified, this is true if OpenMP settings for all enabled languages
# were detected.
# ``OpenMP_VERSION``
# Minimal version of the OpenMP standard detected among the requested languages,
# or all enabled languages if no components were specified.
#
# This module will set the following variables per language in your
# project, where ``<lang>`` is one of C, CXX, or Fortran:
#
# ``OpenMP_<lang>_FOUND``
# Variable indicating if OpenMP support for ``<lang>`` was detected.
# ``OpenMP_<lang>_FLAGS``
# OpenMP compiler flags for ``<lang>``, separated by spaces.
#
# For linking with OpenMP code written in ``<lang>``, the following
# variables are provided:
#
# ``OpenMP_<lang>_LIB_NAMES``
# :ref:`;-list <CMake Language Lists>` of libraries for OpenMP programs for ``<lang>``.
# ``OpenMP_<libname>_LIBRARY``
# Location of the individual libraries needed for OpenMP support in ``<lang>``.
# ``OpenMP_<lang>_LIBRARIES``
# A list of libraries needed to link with OpenMP code written in ``<lang>``.
#
# Additionally, the module provides :prop_tgt:`IMPORTED` targets:
#
# ``OpenMP::OpenMP_<lang>``
# Target for using OpenMP from ``<lang>``.
#
# Specifically for Fortran, the module sets the following variables:
#
# ``OpenMP_Fortran_HAVE_OMPLIB_HEADER``
# Boolean indicating if OpenMP is accessible through ``omp_lib.h``.
# ``OpenMP_Fortran_HAVE_OMPLIB_MODULE``
# Boolean indicating if OpenMP is accessible through the ``omp_lib`` Fortran module.
#
# The module will also try to provide the OpenMP version variables:
#
# ``OpenMP_<lang>_SPEC_DATE``
# Date of the OpenMP specification implemented by the ``<lang>`` compiler.
# ``OpenMP_<lang>_VERSION_MAJOR``
# Major version of OpenMP implemented by the ``<lang>`` compiler.
# ``OpenMP_<lang>_VERSION_MINOR``
# Minor version of OpenMP implemented by the ``<lang>`` compiler.
# ``OpenMP_<lang>_VERSION``
# OpenMP version implemented by the ``<lang>`` compiler.
#
# The specification date is formatted as given in the OpenMP standard:
# ``yyyymm`` where ``yyyy`` and ``mm`` represents the year and month of
# the OpenMP specification implemented by the ``<lang>`` compiler.
cmake_policy(PUSH)
cmake_policy(SET CMP0012 NEW) # if() recognizes numbers and booleans
cmake_policy(SET CMP0054 NEW) # if() quoted variables not dereferenced
cmake_policy(SET CMP0057 NEW) # if IN_LIST
function(_OPENMP_FLAG_CANDIDATES LANG)
if(NOT OpenMP_${LANG}_FLAG)
unset(OpenMP_FLAG_CANDIDATES)
set(OMP_FLAG_GNU "-fopenmp")
set(OMP_FLAG_Clang "-fopenmp=libomp" "-fopenmp=libiomp5" "-fopenmp")
set(OMP_FLAG_AppleClang "-Xclang -fopenmp")
set(OMP_FLAG_HP "+Oopenmp")
if(WIN32)
set(OMP_FLAG_Intel "-Qopenmp")
elseif(CMAKE_${LANG}_COMPILER_ID STREQUAL "Intel" AND
"${CMAKE_${LANG}_COMPILER_VERSION}" VERSION_LESS "15.0.0.20140528")
set(OMP_FLAG_Intel "-openmp")
else()
set(OMP_FLAG_Intel "-qopenmp")
endif()
set(OMP_FLAG_MIPSpro "-mp")
set(OMP_FLAG_MSVC "-openmp")
set(OMP_FLAG_PathScale "-openmp")
set(OMP_FLAG_NAG "-openmp")
set(OMP_FLAG_Absoft "-openmp")
set(OMP_FLAG_PGI "-mp")
set(OMP_FLAG_Flang "-fopenmp")
set(OMP_FLAG_SunPro "-xopenmp")
set(OMP_FLAG_XL "-qsmp=omp")
# Cray compiler activate OpenMP with -h omp, which is enabled by default.
set(OMP_FLAG_Cray " " "-h omp")
# If we know the correct flags, use those
if(DEFINED OMP_FLAG_${CMAKE_${LANG}_COMPILER_ID})
set(OpenMP_FLAG_CANDIDATES "${OMP_FLAG_${CMAKE_${LANG}_COMPILER_ID}}")
# Fall back to reasonable default tries otherwise
else()
set(OpenMP_FLAG_CANDIDATES "-openmp" "-fopenmp" "-mp" " ")
endif()
set(OpenMP_${LANG}_FLAG_CANDIDATES "${OpenMP_FLAG_CANDIDATES}" PARENT_SCOPE)
else()
set(OpenMP_${LANG}_FLAG_CANDIDATES "${OpenMP_${LANG}_FLAG}" PARENT_SCOPE)
endif()
endfunction()
# sample openmp source code to test
set(OpenMP_C_CXX_TEST_SOURCE
"
#include <omp.h>
int main() {
#ifdef _OPENMP
int n = omp_get_max_threads();
return 0;
#else
breaks_on_purpose
#endif
}
")
# in Fortran, an implementation may provide an omp_lib.h header
# or omp_lib module, or both (OpenMP standard, section 3.1)
# Furthmore !$ is the Fortran equivalent of #ifdef _OPENMP (OpenMP standard, 2.2.2)
# Without the conditional compilation, some compilers (e.g. PGI) might compile OpenMP code
# while not actually enabling OpenMP, building code sequentially
set(OpenMP_Fortran_TEST_SOURCE
"
program test
@OpenMP_Fortran_INCLUDE_LINE@
!$ integer :: n
n = omp_get_num_threads()
end program test
"
)
function(_OPENMP_WRITE_SOURCE_FILE LANG SRC_FILE_CONTENT_VAR SRC_FILE_NAME SRC_FILE_FULLPATH)
set(WORK_DIR ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/FindOpenMP)
if("${LANG}" STREQUAL "C")
set(SRC_FILE "${WORK_DIR}/${SRC_FILE_NAME}.c")
file(WRITE "${SRC_FILE}" "${OpenMP_C_CXX_${SRC_FILE_CONTENT_VAR}}")
elseif("${LANG}" STREQUAL "CXX")
set(SRC_FILE "${WORK_DIR}/${SRC_FILE_NAME}.cpp")
file(WRITE "${SRC_FILE}" "${OpenMP_C_CXX_${SRC_FILE_CONTENT_VAR}}")
elseif("${LANG}" STREQUAL "Fortran")
set(SRC_FILE "${WORK_DIR}/${SRC_FILE_NAME}.f90")
file(WRITE "${SRC_FILE}_in" "${OpenMP_Fortran_${SRC_FILE_CONTENT_VAR}}")
configure_file("${SRC_FILE}_in" "${SRC_FILE}" @ONLY)
endif()
set(${SRC_FILE_FULLPATH} "${SRC_FILE}" PARENT_SCOPE)
endfunction()
include(CMakeParseImplicitLinkInfo)
function(_OPENMP_GET_FLAGS LANG FLAG_MODE OPENMP_FLAG_VAR OPENMP_LIB_NAMES_VAR)
_OPENMP_FLAG_CANDIDATES("${LANG}")
_OPENMP_WRITE_SOURCE_FILE("${LANG}" "TEST_SOURCE" OpenMPTryFlag _OPENMP_TEST_SRC)
unset(OpenMP_VERBOSE_COMPILE_OPTIONS)
separate_arguments(OpenMP_VERBOSE_OPTIONS NATIVE_COMMAND "${CMAKE_${LANG}_VERBOSE_FLAG}")
foreach(_VERBOSE_OPTION IN LISTS OpenMP_VERBOSE_OPTIONS)
if(NOT _VERBOSE_OPTION MATCHES "^-Wl,")
list(APPEND OpenMP_VERBOSE_COMPILE_OPTIONS ${_VERBOSE_OPTION})
endif()
endforeach()
foreach(OPENMP_FLAG IN LISTS OpenMP_${LANG}_FLAG_CANDIDATES)
set(OPENMP_FLAGS_TEST "${OPENMP_FLAG}")
if(OpenMP_VERBOSE_COMPILE_OPTIONS)
string(APPEND OPENMP_FLAGS_TEST " ${OpenMP_VERBOSE_COMPILE_OPTIONS}")
endif()
string(REGEX REPLACE "[-/=+]" "" OPENMP_PLAIN_FLAG "${OPENMP_FLAG}")
try_compile( OpenMP_COMPILE_RESULT_${FLAG_MODE}_${OPENMP_PLAIN_FLAG} ${CMAKE_BINARY_DIR} ${_OPENMP_TEST_SRC}
CMAKE_FLAGS "-DCOMPILE_DEFINITIONS:STRING=${OPENMP_FLAGS_TEST}"
LINK_LIBRARIES ${CMAKE_${LANG}_VERBOSE_FLAG}
OUTPUT_VARIABLE OpenMP_TRY_COMPILE_OUTPUT
)
if(OpenMP_COMPILE_RESULT_${FLAG_MODE}_${OPENMP_PLAIN_FLAG})
set("${OPENMP_FLAG_VAR}" "${OPENMP_FLAG}" PARENT_SCOPE)
if(CMAKE_${LANG}_VERBOSE_FLAG)
unset(OpenMP_${LANG}_IMPLICIT_LIBRARIES)
unset(OpenMP_${LANG}_IMPLICIT_LINK_DIRS)
unset(OpenMP_${LANG}_IMPLICIT_FWK_DIRS)
unset(OpenMP_${LANG}_LOG_VAR)
file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
"Detecting ${LANG} OpenMP compiler ABI info compiled with the following output:\n${OpenMP_TRY_COMPILE_OUTPUT}\n\n")
cmake_parse_implicit_link_info("${OpenMP_TRY_COMPILE_OUTPUT}"
OpenMP_${LANG}_IMPLICIT_LIBRARIES
OpenMP_${LANG}_IMPLICIT_LINK_DIRS
OpenMP_${LANG}_IMPLICIT_FWK_DIRS
OpenMP_${LANG}_LOG_VAR
"${CMAKE_${LANG}_IMPLICIT_OBJECT_REGEX}"
)
file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
"Parsed ${LANG} OpenMP implicit link information from above output:\n${OpenMP_${LANG}_LOG_VAR}\n\n")
unset(_OPENMP_LIB_NAMES)
foreach(_OPENMP_IMPLICIT_LIB IN LISTS OpenMP_${LANG}_IMPLICIT_LIBRARIES)
get_filename_component(_OPENMP_IMPLICIT_LIB_DIR "${_OPENMP_IMPLICIT_LIB}" DIRECTORY)
get_filename_component(_OPENMP_IMPLICIT_LIB_NAME "${_OPENMP_IMPLICIT_LIB}" NAME)
get_filename_component(_OPENMP_IMPLICIT_LIB_PLAIN "${_OPENMP_IMPLICIT_LIB}" NAME_WE)
string(REGEX REPLACE "([][+.*?()^$])" "\\\\\\1" _OPENMP_IMPLICIT_LIB_PLAIN_ESC "${_OPENMP_IMPLICIT_LIB_PLAIN}")
string(REGEX REPLACE "([][+.*?()^$])" "\\\\\\1" _OPENMP_IMPLICIT_LIB_PATH_ESC "${_OPENMP_IMPLICIT_LIB}")
if(NOT ( "${_OPENMP_IMPLICIT_LIB}" IN_LIST CMAKE_${LANG}_IMPLICIT_LINK_LIBRARIES
OR "${CMAKE_${LANG}_STANDARD_LIBRARIES}" MATCHES "(^| )(-Wl,)?(-l)?(${_OPENMP_IMPLICIT_LIB_PLAIN_ESC}|${_OPENMP_IMPLICIT_LIB_PATH_ESC})( |$)"
OR "${CMAKE_${LANG}_LINK_EXECUTABLE}" MATCHES "(^| )(-Wl,)?(-l)?(${_OPENMP_IMPLICIT_LIB_PLAIN_ESC}|${_OPENMP_IMPLICIT_LIB_PATH_ESC})( |$)" ) )
if(_OPENMP_IMPLICIT_LIB_DIR)
set(OpenMP_${_OPENMP_IMPLICIT_LIB_PLAIN}_LIBRARY "${_OPENMP_IMPLICIT_LIB}" CACHE FILEPATH
"Path to the ${_OPENMP_IMPLICIT_LIB_PLAIN} library for OpenMP")
else()
find_library(OpenMP_${_OPENMP_IMPLICIT_LIB_PLAIN}_LIBRARY
NAMES "${_OPENMP_IMPLICIT_LIB_NAME}"
DOC "Path to the ${_OPENMP_IMPLICIT_LIB_PLAIN} library for OpenMP"
HINTS ${OpenMP_${LANG}_IMPLICIT_LINK_DIRS}
CMAKE_FIND_ROOT_PATH_BOTH
NO_DEFAULT_PATH
)
endif()
mark_as_advanced(OpenMP_${_OPENMP_IMPLICIT_LIB_PLAIN}_LIBRARY)
list(APPEND _OPENMP_LIB_NAMES ${_OPENMP_IMPLICIT_LIB_PLAIN})
endif()
endforeach()
set("${OPENMP_LIB_NAMES_VAR}" "${_OPENMP_LIB_NAMES}" PARENT_SCOPE)
else()
# We do not know how to extract implicit OpenMP libraries for this compiler.
# Assume that it handles them automatically, e.g. the Intel Compiler on
# Windows should put the dependency in its object files.
set("${OPENMP_LIB_NAMES_VAR}" "" PARENT_SCOPE)
endif()
break()
elseif(CMAKE_${LANG}_COMPILER_ID STREQUAL "AppleClang"
AND CMAKE_${LANG}_COMPILER_VERSION VERSION_GREATER_EQUAL "7.0")
# Check for separate OpenMP library on AppleClang 7+
find_library(OpenMP_libomp_LIBRARY
NAMES omp gomp iomp5
HINTS ${CMAKE_${LANG}_IMPLICIT_LINK_DIRECTORIES}
)
mark_as_advanced(OpenMP_libomp_LIBRARY)
if(OpenMP_libomp_LIBRARY)
try_compile( OpenMP_COMPILE_RESULT_${FLAG_MODE}_${OPENMP_PLAIN_FLAG} ${CMAKE_BINARY_DIR} ${_OPENMP_TEST_SRC}
CMAKE_FLAGS "-DCOMPILE_DEFINITIONS:STRING=${OPENMP_FLAGS_TEST}"
LINK_LIBRARIES ${CMAKE_${LANG}_VERBOSE_FLAG} ${OpenMP_libomp_LIBRARY}
OUTPUT_VARIABLE OpenMP_TRY_COMPILE_OUTPUT
)
if(OpenMP_COMPILE_RESULT_${FLAG_MODE}_${OPENMP_PLAIN_FLAG})
set("${OPENMP_FLAG_VAR}" "${OPENMP_FLAG}" PARENT_SCOPE)
set("${OPENMP_LIB_NAMES_VAR}" "libomp" PARENT_SCOPE)
break()
endif()
endif()
endif()
set("${OPENMP_LIB_NAMES_VAR}" "NOTFOUND" PARENT_SCOPE)
set("${OPENMP_FLAG_VAR}" "NOTFOUND" PARENT_SCOPE)
endforeach()
unset(OpenMP_VERBOSE_COMPILE_OPTIONS)
endfunction()
set(OpenMP_C_CXX_CHECK_VERSION_SOURCE
"
#include <stdio.h>
#include <omp.h>
const char ompver_str[] = { 'I', 'N', 'F', 'O', ':', 'O', 'p', 'e', 'n', 'M',
'P', '-', 'd', 'a', 't', 'e', '[',
('0' + ((_OPENMP/100000)%10)),
('0' + ((_OPENMP/10000)%10)),
('0' + ((_OPENMP/1000)%10)),
('0' + ((_OPENMP/100)%10)),
('0' + ((_OPENMP/10)%10)),
('0' + ((_OPENMP/1)%10)),
']', '\\0' };
int main()
{
puts(ompver_str);
return 0;
}
")
set(OpenMP_Fortran_CHECK_VERSION_SOURCE
"
program omp_ver
@OpenMP_Fortran_INCLUDE_LINE@
integer, parameter :: zero = ichar('0')
integer, parameter :: ompv = openmp_version
character, dimension(24), parameter :: ompver_str =&
(/ 'I', 'N', 'F', 'O', ':', 'O', 'p', 'e', 'n', 'M', 'P', '-',&
'd', 'a', 't', 'e', '[',&
char(zero + mod(ompv/100000, 10)),&
char(zero + mod(ompv/10000, 10)),&
char(zero + mod(ompv/1000, 10)),&
char(zero + mod(ompv/100, 10)),&
char(zero + mod(ompv/10, 10)),&
char(zero + mod(ompv/1, 10)), ']' /)
print *, ompver_str
end program omp_ver
")
function(_OPENMP_GET_SPEC_DATE LANG SPEC_DATE)
_OPENMP_WRITE_SOURCE_FILE("${LANG}" "CHECK_VERSION_SOURCE" OpenMPCheckVersion _OPENMP_TEST_SRC)
set(BIN_FILE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/FindOpenMP/ompver_${LANG}.bin")
string(REGEX REPLACE "[-/=+]" "" OPENMP_PLAIN_FLAG "${OPENMP_FLAG}")
try_compile(OpenMP_SPECTEST_${LANG}_${OPENMP_PLAIN_FLAG} "${CMAKE_BINARY_DIR}" "${_OPENMP_TEST_SRC}"
CMAKE_FLAGS "-DCOMPILE_DEFINITIONS:STRING=${OpenMP_${LANG}_FLAGS}"
COPY_FILE ${BIN_FILE})
if(${OpenMP_SPECTEST_${LANG}_${OPENMP_PLAIN_FLAG}})
file(STRINGS ${BIN_FILE} specstr LIMIT_COUNT 1 REGEX "INFO:OpenMP-date")
set(regex_spec_date ".*INFO:OpenMP-date\\[0*([^]]*)\\].*")
if("${specstr}" MATCHES "${regex_spec_date}")
set(${SPEC_DATE} "${CMAKE_MATCH_1}" PARENT_SCOPE)
endif()
endif()
endfunction()
macro(_OPENMP_SET_VERSION_BY_SPEC_DATE LANG)
set(OpenMP_SPEC_DATE_MAP
# Preview versions
"201611=5.0" # OpenMP 5.0 preview 1
# Combined versions, 2.5 onwards
"201511=4.5"
"201307=4.0"
"201107=3.1"
"200805=3.0"
"200505=2.5"
# C/C++ version 2.0
"200203=2.0"
# Fortran version 2.0
"200011=2.0"
# Fortran version 1.1
"199911=1.1"
# C/C++ version 1.0 (there's no 1.1 for C/C++)
"199810=1.0"
# Fortran version 1.0
"199710=1.0"
)
if(OpenMP_${LANG}_SPEC_DATE)
string(REGEX MATCHALL "${OpenMP_${LANG}_SPEC_DATE}=([0-9]+)\\.([0-9]+)" _version_match "${OpenMP_SPEC_DATE_MAP}")
else()
set(_version_match "")
endif()
if(NOT _version_match STREQUAL "")
set(OpenMP_${LANG}_VERSION_MAJOR ${CMAKE_MATCH_1})
set(OpenMP_${LANG}_VERSION_MINOR ${CMAKE_MATCH_2})
set(OpenMP_${LANG}_VERSION "${OpenMP_${LANG}_VERSION_MAJOR}.${OpenMP_${LANG}_VERSION_MINOR}")
else()
unset(OpenMP_${LANG}_VERSION_MAJOR)
unset(OpenMP_${LANG}_VERSION_MINOR)
unset(OpenMP_${LANG}_VERSION)
endif()
unset(_version_match)
unset(OpenMP_SPEC_DATE_MAP)
endmacro()
foreach(LANG IN ITEMS C CXX)
if(CMAKE_${LANG}_COMPILER_LOADED)
if(NOT DEFINED OpenMP_${LANG}_FLAGS OR "${OpenMP_${LANG}_FLAGS}" STREQUAL "NOTFOUND"
OR NOT DEFINED OpenMP_${LANG}_LIB_NAMES OR "${OpenMP_${LANG}_LIB_NAMES}" STREQUAL "NOTFOUND")
_OPENMP_GET_FLAGS("${LANG}" "${LANG}" OpenMP_${LANG}_FLAGS_WORK OpenMP_${LANG}_LIB_NAMES_WORK)
endif()
set(OpenMP_${LANG}_FLAGS "${OpenMP_${LANG}_FLAGS_WORK}"
CACHE STRING "${LANG} compiler flags for OpenMP parallelization")
set(OpenMP_${LANG}_LIB_NAMES "${OpenMP_${LANG}_LIB_NAMES_WORK}"
CACHE STRING "${LANG} compiler libraries for OpenMP parallelization")
mark_as_advanced(OpenMP_${LANG}_FLAGS OpenMP_${LANG}_LIB_NAMES)
endif()
endforeach()
if(CMAKE_Fortran_COMPILER_LOADED)
if(NOT DEFINED OpenMP_Fortran_FLAGS OR "${OpenMP_Fortran_FLAGS}" STREQUAL "NOTFOUND"
OR NOT DEFINED OpenMP_Fortran_LIB_NAMES OR "${OpenMP_Fortran_LIB_NAMES}" STREQUAL "NOTFOUND"
OR NOT DEFINED OpenMP_Fortran_HAVE_OMPLIB_MODULE)
set(OpenMP_Fortran_INCLUDE_LINE "use omp_lib\n implicit none")
_OPENMP_GET_FLAGS("Fortran" "FortranHeader" OpenMP_Fortran_FLAGS_WORK OpenMP_Fortran_LIB_NAMES_WORK)
if(OpenMP_Fortran_FLAGS_WORK)
set(OpenMP_Fortran_HAVE_OMPLIB_MODULE TRUE CACHE BOOL INTERNAL "")
endif()
set(OpenMP_Fortran_FLAGS "${OpenMP_Fortran_FLAGS_WORK}"
CACHE STRING "Fortran compiler flags for OpenMP parallelization")
set(OpenMP_Fortran_LIB_NAMES "${OpenMP_Fortran_LIB_NAMES_WORK}"
CACHE STRING "Fortran compiler libraries for OpenMP parallelization")
mark_as_advanced(OpenMP_Fortran_FLAGS OpenMP_Fortran_LIB_NAMES)
endif()
if(NOT DEFINED OpenMP_Fortran_FLAGS OR "${OpenMP_Fortran_FLAGS}" STREQUAL "NOTFOUND"
OR NOT DEFINED OpenMP_Fortran_LIB_NAMES OR "${OpenMP_Fortran_LIB_NAMES}" STREQUAL "NOTFOUND"
OR NOT DEFINED OpenMP_Fortran_HAVE_OMPLIB_HEADER)
set(OpenMP_Fortran_INCLUDE_LINE "implicit none\n include 'omp_lib.h'")
_OPENMP_GET_FLAGS("Fortran" "FortranModule" OpenMP_Fortran_FLAGS_WORK OpenMP_Fortran_LIB_NAMES_WORK)
if(OpenMP_Fortran_FLAGS_WORK)
set(OpenMP_Fortran_HAVE_OMPLIB_HEADER TRUE CACHE BOOL INTERNAL "")
endif()
set(OpenMP_Fortran_FLAGS "${OpenMP_Fortran_FLAGS_WORK}"
CACHE STRING "Fortran compiler flags for OpenMP parallelization")
set(OpenMP_Fortran_LIB_NAMES "${OpenMP_Fortran_LIB_NAMES}"
CACHE STRING "Fortran compiler libraries for OpenMP parallelization")
endif()
if(OpenMP_Fortran_HAVE_OMPLIB_MODULE)
set(OpenMP_Fortran_INCLUDE_LINE "use omp_lib\n implicit none")
else()
set(OpenMP_Fortran_INCLUDE_LINE "implicit none\n include 'omp_lib.h'")
endif()
endif()
if(NOT OpenMP_FIND_COMPONENTS)
set(OpenMP_FINDLIST C CXX Fortran)
else()
set(OpenMP_FINDLIST ${OpenMP_FIND_COMPONENTS})
endif()
unset(_OpenMP_MIN_VERSION)
include(FindPackageHandleStandardArgs)
foreach(LANG IN LISTS OpenMP_FINDLIST)
if(CMAKE_${LANG}_COMPILER_LOADED)
if (NOT OpenMP_${LANG}_SPEC_DATE AND OpenMP_${LANG}_FLAGS)
_OPENMP_GET_SPEC_DATE("${LANG}" OpenMP_${LANG}_SPEC_DATE_INTERNAL)
set(OpenMP_${LANG}_SPEC_DATE "${OpenMP_${LANG}_SPEC_DATE_INTERNAL}" CACHE
INTERNAL "${LANG} compiler's OpenMP specification date")
_OPENMP_SET_VERSION_BY_SPEC_DATE("${LANG}")
endif()
set(OpenMP_${LANG}_FIND_QUIETLY ${OpenMP_FIND_QUIETLY})
set(OpenMP_${LANG}_FIND_REQUIRED ${OpenMP_FIND_REQUIRED})
set(OpenMP_${LANG}_FIND_VERSION ${OpenMP_FIND_VERSION})
set(OpenMP_${LANG}_FIND_VERSION_EXACT ${OpenMP_FIND_VERSION_EXACT})
set(_OPENMP_${LANG}_REQUIRED_VARS OpenMP_${LANG}_FLAGS)
if("${OpenMP_${LANG}_LIB_NAMES}" STREQUAL "NOTFOUND")
set(_OPENMP_${LANG}_REQUIRED_LIB_VARS OpenMP_${LANG}_LIB_NAMES)
else()
foreach(_OPENMP_IMPLICIT_LIB IN LISTS OpenMP_${LANG}_LIB_NAMES)
list(APPEND _OPENMP_${LANG}_REQUIRED_LIB_VARS OpenMP_${_OPENMP_IMPLICIT_LIB}_LIBRARY)
endforeach()
endif()
find_package_handle_standard_args(OpenMP_${LANG}
REQUIRED_VARS OpenMP_${LANG}_FLAGS ${_OPENMP_${LANG}_REQUIRED_LIB_VARS}
VERSION_VAR OpenMP_${LANG}_VERSION
)
if(OpenMP_${LANG}_FOUND)
if(DEFINED OpenMP_${LANG}_VERSION)
if(NOT _OpenMP_MIN_VERSION OR _OpenMP_MIN_VERSION VERSION_GREATER OpenMP_${LANG}_VERSION)
set(_OpenMP_MIN_VERSION OpenMP_${LANG}_VERSION)
endif()
endif()
set(OpenMP_${LANG}_LIBRARIES "")
foreach(_OPENMP_IMPLICIT_LIB IN LISTS OpenMP_${LANG}_LIB_NAMES)
list(APPEND OpenMP_${LANG}_LIBRARIES "${OpenMP_${_OPENMP_IMPLICIT_LIB}_LIBRARY}")
endforeach()
if(NOT TARGET OpenMP::OpenMP_${LANG})
add_library(OpenMP::OpenMP_${LANG} INTERFACE IMPORTED)
endif()
if(OpenMP_${LANG}_FLAGS)
separate_arguments(_OpenMP_${LANG}_OPTIONS NATIVE_COMMAND "${OpenMP_${LANG}_FLAGS}")
set_property(TARGET OpenMP::OpenMP_${LANG} PROPERTY
INTERFACE_COMPILE_OPTIONS "$<$<COMPILE_LANGUAGE:${LANG}>:${_OpenMP_${LANG}_OPTIONS}>")
unset(_OpenMP_${LANG}_OPTIONS)
endif()
if(OpenMP_${LANG}_LIBRARIES)
set_property(TARGET OpenMP::OpenMP_${LANG} PROPERTY
INTERFACE_LINK_LIBRARIES "${OpenMP_${LANG}_LIBRARIES}")
endif()
endif()
endif()
endforeach()
unset(_OpenMP_REQ_VARS)
foreach(LANG IN ITEMS C CXX Fortran)
if((NOT OpenMP_FIND_COMPONENTS AND CMAKE_${LANG}_COMPILER_LOADED) OR LANG IN_LIST OpenMP_FIND_COMPONENTS)
list(APPEND _OpenMP_REQ_VARS "OpenMP_${LANG}_FOUND")
endif()
endforeach()
find_package_handle_standard_args(OpenMP
REQUIRED_VARS ${_OpenMP_REQ_VARS}
VERSION_VAR ${_OpenMP_MIN_VERSION}
HANDLE_COMPONENTS)
set(OPENMP_FOUND ${OpenMP_FOUND})
if(CMAKE_Fortran_COMPILER_LOADED AND OpenMP_Fortran_FOUND)
if(NOT DEFINED OpenMP_Fortran_HAVE_OMPLIB_MODULE)
set(OpenMP_Fortran_HAVE_OMPLIB_MODULE FALSE CACHE BOOL INTERNAL "")
endif()
if(NOT DEFINED OpenMP_Fortran_HAVE_OMPLIB_HEADER)
set(OpenMP_Fortran_HAVE_OMPLIB_HEADER FALSE CACHE BOOL INTERNAL "")
endif()
endif()
if(NOT ( CMAKE_C_COMPILER_LOADED OR CMAKE_CXX_COMPILER_LOADED OR CMAKE_Fortran_COMPILER_LOADED ))
message(SEND_ERROR "FindOpenMP requires the C, CXX or Fortran languages to be enabled")
endif()
unset(OpenMP_C_CXX_TEST_SOURCE)
unset(OpenMP_Fortran_TEST_SOURCE)
unset(OpenMP_C_CXX_CHECK_VERSION_SOURCE)
unset(OpenMP_Fortran_CHECK_VERSION_SOURCE)
unset(OpenMP_Fortran_INCLUDE_LINE)
cmake_policy(POP)

@ -67,7 +67,7 @@ find_path(BUILD_DIR CMakeCache.txt .)
get_filename_component(abs_build_dir ${BUILD_DIR} ABSOLUTE)
get_filename_component(build_dir_name ${abs_build_dir} NAME)
set(EXCEPTIONS ${EXCEPTIONS} ${build_dir_name}/*)
message("${EXCEPTIONS}")
message("Copyright Check Exceptions: ${EXCEPTIONS}")
# Gets the current year (if possible).
function (get_year var)

@ -41,6 +41,23 @@ target_link_libraries(vtkm_compiler_flags
# setup that we need C++11 support
target_compile_features(vtkm_compiler_flags INTERFACE cxx_std_11)
# setup our static libraries so that a separate ELF section
# is generated for each function. This allows for the linker to
# remove unused sections. This allows for programs that use VTK-m
# to have the smallest binary impact as they can drop any VTK-m symbol
# they don't use.
if(VTKM_COMPILER_IS_MSVC)
target_compile_options(vtkm_compiler_flags INTERFACE /Gy)
if(TARGET vtkm::cuda)
target_compile_options(vtkm_compiler_flags INTERFACE $<$<COMPILE_LANGUAGE:CUDA>:-Xcompiler="/Gy">)
endif()
elseif(NOT VTKM_COMPILER_IS_PGI) #can't find an equivalant PGI flag
target_compile_options(vtkm_compiler_flags INTERFACE $<$<COMPILE_LANGUAGE:CXX>:-ffunction-sections>)
if(TARGET vtkm::cuda)
target_compile_options(vtkm_compiler_flags INTERFACE $<$<COMPILE_LANGUAGE:CUDA>:-Xcompiler=-ffunction-sections>)
endif()
endif()
# Enable large object support so we can have 2^32 addressable sections
if(VTKM_COMPILER_IS_MSVC)
target_compile_options(vtkm_compiler_flags INTERFACE $<$<COMPILE_LANGUAGE:CXX>:/bigobj>)

@ -14,7 +14,9 @@
#
# vtkm_rendering Target that contains all the rendering code
#
# vtkm_filter Target that contains all of VTK-m filters
# vtkm_filter Target that contains all of VTK-m pre-built filters
#
# vtkm_source Target that contains all of VTK-m pre-built sources
#
# vtkm::tbb Target that contains tbb related link information
# implicitly linked to by `vtkm_cont` if tbb is enabled

@ -86,7 +86,7 @@ endif()
if(VTKm_ENABLE_OPENMP AND NOT TARGET vtkm::openmp)
cmake_minimum_required(VERSION 3.9...3.15 FATAL_ERROR)
cmake_minimum_required(VERSION 3.12...3.15 FATAL_ERROR)
find_package(OpenMP 4.0 REQUIRED COMPONENTS CXX QUIET)
add_library(vtkm::openmp INTERFACE IMPORTED GLOBAL)

@ -135,34 +135,82 @@ function(vtkm_get_cuda_flags settings_var)
endif()
endfunction()
#-----------------------------------------------------------------------------
# Add to a target linker flags that allow unused VTK-m functions to be dropped,
# which helps keep binary sizes down. This works as VTK-m is compiled with
# ffunction-sections which allows for the linker to remove unused functions.
# If you are building a program that loads runtime plugins that can call
# VTK-m this most likely shouldn't be used as symbols the plugin expects
# to exist will be removed.
#
# add_library(lib_that_uses_vtkm ...)
# vtkm_add_drop_unused_function_flags(lib_that_uses_vtkm)
# target_link_libraries(lib_that_uses_vtkm PRIVATE vtkm_filter)
#
function(vtkm_add_drop_unused_function_flags uses_vtkm_target)
get_target_property(lib_type ${uses_vtkm_target} TYPE)
if(${lib_type} STREQUAL "SHARED_LIBRARY" OR
${lib_type} STREQUAL "MODULE_LIBRARY" OR
${lib_type} STREQUAL "EXECUTABLE" )
if(APPLE)
#OSX Linker uses a different flag for this
set_property(TARGET ${uses_vtkm_target} APPEND_STRING PROPERTY
LINK_FLAGS " -Wl,-dead_strip")
elseif(VTKM_COMPILER_IS_GNU OR VTKM_COMPILER_IS_CLANG)
set_property(TARGET ${uses_vtkm_target} APPEND_STRING PROPERTY
LINK_FLAGS " -Wl,--gc-sections")
endif()
endif()
endfunction()
#-----------------------------------------------------------------------------
# Add a relevant information to target that wants to use VTK-m.
#
# This is a higher order function to allow build-systems that use VTK-m
# to compose add_library/add_executable and the required information to have
# VTK-m enabled.
# This higher order function allow build-systems that use VTK-m
# to use `add_library` or `add_executable` calls but still have an
# easy to way to get the required information to have VTK-m using
# compilation units compile correctly.
#
# vtkm_add_target_information(
# target
# target[s]
# [ DROP_UNUSED_SYMBOLS ]
# [ MODIFY_CUDA_FLAGS ]
# [ EXTENDS_VTKM ]
# [ DEVICE_SOURCES <source_list>
# [ DEVICE_SOURCES <source_list> ]
# )
#
# Usage:
# add_library(lib_that_uses_vtkm STATIC a.cxx)
# vtkm_add_target_information(lib_that_uses_vtkm
# DROP_UNUSED_SYMBOLS
# MODIFY_CUDA_FLAGS
# DEVICE_SOURCES a.cxx
# )
# target_link_libraries(lib_that_uses_vtkm PRIVATE vtkm_filter)
#
# MODIFY_CUDA_FLAGS: If enabled will add the required -arch=<ver> flags
# that VTK-m was compiled with. This functionality is also provided by the
# the standalone `vtkm_get_cuda_flags` function.
# DROP_UNUSED_SYMBOLS: If enabled will apply the appropiate link
# flags to drop unused VTK-m symbols. This works as VTK-m is compiled with
# -ffunction-sections which allows for the linker to remove unused functions.
# If you are building a program that loads runtime plugins that can call
# VTK-m this most likely shouldn't be used as symbols the plugin expects
# to exist will be removed.
# Enabling this will help keep library sizes down when using static builds
# of VTK-m as only the functions you call will be kept. This can have a
# dramatic impact on the size of the resulting executable / shared library.
#
# DEVICE_SOURCES: The collection of source files that are used by `target` that
#
# MODIFY_CUDA_FLAGS: If enabled will add the required -arch=<ver> flags
# that VTK-m was compiled with. If you have multiple libraries that use
# VTK-m calling `vtkm_add_target_information` multiple times with
# `MODIFY_CUDA_FLAGS` will cause duplicate compiler flags. To resolve this issue
# you can; pass all targets and sources to a single `vtkm_add_target_information`
# call, have the first one use `MODIFY_CUDA_FLAGS`, or use the provided
# standalone `vtkm_get_cuda_flags` function.
#
# DEVICE_SOURCES: The collection of source files that are used by `target(s)` that
# need to be marked as going to a special compiler for certain device adapters
# such as CUDA.
#
@ -191,13 +239,36 @@ endfunction()
#
#
function(vtkm_add_target_information uses_vtkm_target)
set(options MODIFY_CUDA_FLAGS EXTENDS_VTKM)
set(options DROP_UNUSED_SYMBOLS MODIFY_CUDA_FLAGS EXTENDS_VTKM)
set(multiValueArgs DEVICE_SOURCES)
cmake_parse_arguments(VTKm_TI
"${options}" "${oneValueArgs}" "${multiValueArgs}"
${ARGN}
)
if(VTKm_TI_MODIFY_CUDA_FLAGS)
vtkm_get_cuda_flags(CMAKE_CUDA_FLAGS)
set(CMAKE_CUDA_FLAGS ${CMAKE_CUDA_FLAGS} PARENT_SCOPE)
endif()
set(targets ${uses_vtkm_target})
foreach(item IN LISTS VTKm_TI_UNPARSED_ARGUMENTS)
if(TARGET ${item})
list(APPEND targets ${item})
endif()
endforeach()
# set the required target properties
set_target_properties(${targets} PROPERTIES POSITION_INDEPENDENT_CODE ON)
set_target_properties(${targets} PROPERTIES CUDA_SEPARABLE_COMPILATION ON)
if(VTKm_TI_DROP_UNUSED_SYMBOLS)
foreach(target IN LISTS targets)
vtkm_add_drop_unused_function_flags(${target})
endforeach()
endif()
# Validate that following:
# - We are building with CUDA enabled.
# - We are building a VTK-m library or a library that wants cross library
@ -206,35 +277,28 @@ function(vtkm_add_target_information uses_vtkm_target)
# This is required as CUDA currently doesn't support device side calls across
# dynamic library boundaries.
if(TARGET vtkm::cuda)
get_target_property(lib_type ${uses_vtkm_target} TYPE)
get_target_property(requires_static vtkm::cuda requires_static_builds)
if(requires_static AND ${lib_type} STREQUAL "SHARED_LIBRARY" AND VTKm_TI_EXTENDS_VTKM)
#We provide different error messages based on if we are building VTK-m
#or being called by a consumer of VTK-m. We use PROJECT_NAME so that we
#produce the correct error message when VTK-m is a subdirectory include
#of another project
if(PROJECT_NAME STREQUAL "VTKm")
message(SEND_ERROR "${uses_vtkm_target} needs to be built STATIC as CUDA doesn't"
" support virtual methods across dynamic library boundaries. You"
" need to set the CMake option BUILD_SHARED_LIBS to `OFF`.")
else()
message(SEND_ERROR "${uses_vtkm_target} needs to be built STATIC as CUDA doesn't"
" support virtual methods across dynamic library boundaries. You"
" should either explicitly call add_library with the `STATIC` keyword"
" or set the CMake option BUILD_SHARED_LIBS to `OFF`.")
endif()
endif()
set_source_files_properties(${VTKm_TI_DEVICE_SOURCES} PROPERTIES LANGUAGE "CUDA")
endif()
foreach(target IN LISTS targets)
get_target_property(lib_type ${target} TYPE)
get_target_property(requires_static vtkm::cuda requires_static_builds)
set_target_properties(${uses_vtkm_target} PROPERTIES POSITION_INDEPENDENT_CODE ON)
set_target_properties(${uses_vtkm_target} PROPERTIES CUDA_SEPARABLE_COMPILATION ON)
if(VTKm_TI_MODIFY_CUDA_FLAGS)
vtkm_get_cuda_flags(CMAKE_CUDA_FLAGS)
set(CMAKE_CUDA_FLAGS ${CMAKE_CUDA_FLAGS} PARENT_SCOPE)
if(requires_static AND ${lib_type} STREQUAL "SHARED_LIBRARY" AND VTKm_TI_EXTENDS_VTKM)
#We provide different error messages based on if we are building VTK-m
#or being called by a consumer of VTK-m. We use PROJECT_NAME so that we
#produce the correct error message when VTK-m is a subdirectory include
#of another project
if(PROJECT_NAME STREQUAL "VTKm")
message(SEND_ERROR "${target} needs to be built STATIC as CUDA doesn't"
" support virtual methods across dynamic library boundaries. You"
" need to set the CMake option BUILD_SHARED_LIBS to `OFF`.")
else()
message(SEND_ERROR "${target} needs to be built STATIC as CUDA doesn't"
" support virtual methods across dynamic library boundaries. You"
" should either explicitly call add_library with the `STATIC` keyword"
" or set the CMake option BUILD_SHARED_LIBS to `OFF`.")
endif()
endif()
endforeach()
endif()
endfunction()

@ -144,16 +144,19 @@ EXCLUDE += @VTKm_SOURCE_DIR@/vtkm/exec/cuda/internal/ExecutionPol
EXCLUDE_SYMLINKS = NO
EXCLUDE_PATTERNS = */testing/*
EXCLUDE_PATTERNS = */benchmarking/*
EXCLUDE_PATTERNS += */examples/*
EXCLUDE_PATTERNS += */testing/*
EXCLUDE_PATTERNS += */thirdparty/*
EXCLUDE_PATTERNS += UnitTest*
EXCLUDE_PATTERNS += */vtkmdiy/fmt/*
EXCLUDE_PATTERNS += */vtkmdiy/thread/*
EXCLUDE_SYMBOLS = thrust
EXCLUDE_SYMBOLS += detail
EXCLUDE_SYMBOLS += placeholders
EXCLUDE_SYMBOLS += benchmarking
EXCLUDE_SYMBOLS += detail
EXCLUDE_SYMBOLS += internal
EXCLUDE_SYMBOLS += kx
EXCLUDE_SYMBOLS += placeholders
EXCLUDE_SYMBOLS += *VTK_M_*_EXPORT*
EXAMPLE_PATH =

@ -29,6 +29,8 @@ include(VTKmWrappers)
#
# [DEFINES] : extra defines that need to be set for all unit test sources
#
# [LABEL] : CTest Label to associate to this set of tests
#
# [TEST_ARGS] : arguments that should be passed on the command line to the
# test executable
#
@ -45,7 +47,7 @@ function(vtkm_unit_tests)
set(options)
set(global_options ${options} MPI ALL_BACKENDS)
set(oneValueArgs BACKEND NAME)
set(oneValueArgs BACKEND NAME LABEL)
set(multiValueArgs SOURCES LIBRARIES DEFINES TEST_ARGS)
cmake_parse_arguments(VTKm_UT
"${global_options}" "${oneValueArgs}" "${multiValueArgs}"
@ -97,6 +99,9 @@ function(vtkm_unit_tests)
set(test_prog "UnitTests_${kit}")
endif()
# For Testing Purposes, we will set the default logging level to INFO
list(APPEND vtkm_default_test_log_level "-v" "INFO")
if(VTKm_UT_MPI)
# for MPI tests, suffix test name and add MPI_Init/MPI_Finalize calls.
set(test_prog "${test_prog}_mpi")
@ -111,8 +116,10 @@ function(vtkm_unit_tests)
create_test_sourcelist(test_sources ${test_prog}.cxx ${VTKm_UT_SOURCES} ${extraArgs})
add_executable(${test_prog} ${test_prog}.cxx ${VTKm_UT_SOURCES})
vtkm_add_drop_unused_function_flags(${test_prog})
target_compile_definitions(${test_prog} PRIVATE ${VTKm_UT_DEFINES})
#if all backends are enabled, we can use cuda compiler to handle all possible backends.
set(device_sources )
if(TARGET vtkm::cuda AND enable_all_backends)
@ -154,16 +161,18 @@ function(vtkm_unit_tests)
if(VTKm_UT_MPI AND VTKm_ENABLE_MPI)
add_test(NAME ${tname}${upper_backend}
COMMAND ${MPIEXEC} ${MPIEXEC_NUMPROC_FLAG} 3 ${MPIEXEC_PREFLAGS}
$<TARGET_FILE:${test_prog}> ${tname} ${device_command_line_argument} ${VTKm_UT_TEST_ARGS}
${MPIEXEC_POSTFLAGS}
$<TARGET_FILE:${test_prog}> ${tname} ${device_command_line_argument}
${vtkm_default_test_log_level} ${VTKm_UT_TEST_ARGS} ${MPIEXEC_POSTFLAGS}
)
else()
add_test(NAME ${tname}${upper_backend}
COMMAND ${test_prog} ${tname} ${device_command_line_argument} ${VTKm_UT_TEST_ARGS}
COMMAND ${test_prog} ${tname} ${device_command_line_argument}
${vtkm_default_test_log_level} ${VTKm_UT_TEST_ARGS}
)
endif()
set_tests_properties("${tname}${upper_backend}" PROPERTIES
LABELS "${upper_backend};${VTKm_UT_LABEL}"
TIMEOUT ${timeout}
RUN_SERIAL ${run_serial}
FAIL_REGULAR_EXPRESSION "runtime error"

@ -83,7 +83,6 @@ vtkm_option(VTKm_ENABLE_TBB "Enable TBB support" OFF)
vtkm_option(VTKm_ENABLE_OPENMP "Enable OpenMP support" OFF)
vtkm_option(VTKm_ENABLE_RENDERING "Enable rendering library" ON)
vtkm_option(VTKm_ENABLE_BENCHMARKS "Enable VTKm Benchmarking" OFF)
vtkm_option(VTKm_ENABLE_LOGGING "Enable VTKm Logging" OFF)
vtkm_option(VTKm_ENABLE_MPI "Enable MPI support" OFF)
vtkm_option(VTKm_ENABLE_DOCUMENTATION "Build Doxygen documentation" OFF)
vtkm_option(VTKm_ENABLE_EXAMPLES "Build examples" OFF)
@ -98,6 +97,12 @@ endif()
vtkm_option(VTKm_USE_DOUBLE_PRECISION "Use double precision for floating point calculations" OFF)
vtkm_option(VTKm_USE_64BIT_IDS "Use 64-bit indices." ON)
# VTK-m will turn on logging by default, but will set the default
# logging level to WARN. This option should not be visible by default
# in the GUI, as ERROR and WARN level logging should not interfere
# with the performance of vtk-m
vtkm_option(VTKm_ENABLE_LOGGING "Enable VTKm Logging" ON)
# When VTK-m is embedded into larger projects they may desire to turn off
# VTK-m internal assert checks when in debug mode to improve debug runtime
# performance.
@ -124,6 +129,7 @@ set(VTKm_BUILD_SHARED_LIBS ${BUILD_SHARED_LIBS})
vtkm_option(VTKm_ENABLE_DEVELOPER_FLAGS "Enable compiler flags that are useful while developing VTK-m" ON)
mark_as_advanced(
VTKm_ENABLE_LOGGING
VTKm_NO_ASSERT
VTKm_INSTALL_ONLY_LIBRARIES
VTKm_USE_DEFAULT_SYMBOL_VISIBILITY
@ -244,7 +250,6 @@ if(NOT VTKm_INSTALL_ONLY_LIBRARIES)
${VTKm_SOURCE_DIR}/CMake/FindTBB.cmake
${VTKm_SOURCE_DIR}/CMake/FindMPI.cmake
${VTKm_SOURCE_DIR}/CMake/FindOpenGL.cmake
${VTKm_SOURCE_DIR}/CMake/FindOpenMP.cmake
DESTINATION ${VTKm_INSTALL_CMAKE_MODULE_DIR}
)

@ -59,14 +59,14 @@ VTK-m Requires:
+ C++11 Compiler. VTK-m has been confirmed to work with the following
+ GCC 4.8+
+ Clang 3.3+
+ Clang 5.0+
+ XCode 5.0+
+ MSVC 2015+
+ Intel 17.0.4+
+ [CMake](http://www.cmake.org/download/)
+ CMake 3.8+
+ CMake 3.9+ (for OpenMP support)
+ CMake 3.11+ (for Visual Studio generator)
+ CMake 3.12+ (for OpenMP support)
+ CMake 3.13+ (for CUDA support)
Optional dependencies are:

@ -46,8 +46,8 @@
#include <vtkm/io/reader/VTKDataSetReader.h>
#include <vtkm/source/Wavelet.h>
#include <vtkm/worklet/DispatcherMapField.h>
#include <vtkm/worklet/WaveletGenerator.h>
#include <vtkm/worklet/WorkletMapField.h>
#include <cctype> // for std::tolower
@ -142,7 +142,6 @@ using UnstructuredCellList =
using AllCellList = vtkm::ListTagJoin<StructuredCellList, UnstructuredCellList>;
using CoordinateList = vtkm::ListTagBase<vtkm::Vec3f_32, vtkm::Vec3f_64>;
class BenchmarkFilterPolicy : public vtkm::filter::PolicyBase<BenchmarkFilterPolicy>
{
@ -152,8 +151,6 @@ public:
using StructuredCellSetList = StructuredCellList;
using UnstructuredCellSetList = UnstructuredCellList;
using AllCellSetList = AllCellList;
using CoordinateTypeList = CoordinateList;
};
// Class implementing all filter benchmarks:
@ -307,7 +304,7 @@ class BenchmarkFilters
{
Timer timer{ DeviceAdapter() };
timer.Start();
auto result = this->Filter.Execute(InputDataSet, BenchmarkFilterPolicy());
auto result = this->Filter.Execute(InputDataSet);
(void)result;
return timer.GetElapsedTime();
}
@ -374,7 +371,7 @@ class BenchmarkFilters
{
Timer timer{ DeviceAdapter() };
timer.Start();
auto result = this->Filter.Execute(InputDataSet, BenchmarkFilterPolicy());
auto result = this->Filter.Execute(InputDataSet);
(void)result;
return timer.GetElapsedTime();
}
@ -400,7 +397,7 @@ class BenchmarkFilters
{
Timer timer{ DeviceAdapter() };
timer.Start();
auto result = this->Filter.Execute(InputDataSet, BenchmarkFilterPolicy());
auto result = this->Filter.Execute(InputDataSet);
(void)result;
return timer.GetElapsedTime();
}
@ -501,7 +498,7 @@ class BenchmarkFilters
{
Timer timer{ DeviceAdapter() };
timer.Start();
auto result = this->Filter.Execute(InputDataSet, BenchmarkFilterPolicy());
auto result = this->Filter.Execute(InputDataSet);
(void)result;
return timer.GetElapsedTime();
}
@ -547,7 +544,7 @@ class BenchmarkFilters
{
Timer timer{ DeviceAdapter() };
timer.Start();
auto result = this->Filter.Execute(InputDataSet, BenchmarkFilterPolicy());
auto result = this->Filter.Execute(InputDataSet);
(void)result;
return timer.GetElapsedTime();
}
@ -954,7 +951,7 @@ void CreateFields(bool needPointScalars, bool needCellScalars, bool needPointVec
vtkm::filter::PointAverage avg;
avg.SetActiveField(CellScalarsName, vtkm::cont::Field::Association::CELL_SET);
avg.SetOutputFieldName("GeneratedPointScalars");
auto outds = avg.Execute(InputDataSet, BenchmarkFilterPolicy());
auto outds = avg.Execute(InputDataSet);
InputDataSet.AddField(
outds.GetField("GeneratedPointScalars", vtkm::cont::Field::Association::POINTS));
PointScalarsName = "GeneratedPointScalars";
@ -977,7 +974,7 @@ void CreateFields(bool needPointScalars, bool needCellScalars, bool needPointVec
vtkm::filter::VectorMagnitude mag;
mag.SetActiveField(PointVectorsName, vtkm::cont::Field::Association::POINTS);
mag.SetOutputFieldName("GeneratedPointScalars");
auto outds = mag.Execute(InputDataSet, BenchmarkFilterPolicy());
auto outds = mag.Execute(InputDataSet);
InputDataSet.AddField(
outds.GetField("GeneratedPointScalars", vtkm::cont::Field::Association::POINTS));
PointScalarsName = "GeneratedPointScalars";
@ -999,7 +996,7 @@ void CreateFields(bool needPointScalars, bool needCellScalars, bool needPointVec
vtkm::filter::CellAverage avg;
avg.SetActiveField(PointScalarsName, vtkm::cont::Field::Association::POINTS);
avg.SetOutputFieldName("GeneratedCellScalars");
auto outds = avg.Execute(InputDataSet, BenchmarkFilterPolicy());
auto outds = avg.Execute(InputDataSet);
InputDataSet.AddField(
outds.GetField("GeneratedCellScalars", vtkm::cont::Field::Association::CELL_SET));
CellScalarsName = "GeneratedCellScalars";
@ -1357,10 +1354,10 @@ int BenchmarkBody(int argc, char** argv, const vtkm::cont::InitializeResult& con
{
std::cout << "Generating " << waveletDim << "x" << waveletDim << "x" << waveletDim
<< " wavelet...\n";
vtkm::worklet::WaveletGenerator gen;
gen.SetExtent({ 0 }, { waveletDim });
vtkm::source::Wavelet source;
source.SetExtent({ 0 }, { waveletDim });
InputDataSet = gen.GenerateDataSet(config.Device);
InputDataSet = source.Execute();
}
if (tetra)

@ -19,12 +19,15 @@ function(add_benchmark)
add_executable(${exe_name} ${VTKm_AB_FILE})
target_link_libraries(${exe_name} PRIVATE ${VTKm_AB_LIBS})
vtkm_add_drop_unused_function_flags(${exe_name})
vtkm_add_target_information(${exe_name})
set_target_properties(${exe_name} PROPERTIES
RUNTIME_OUTPUT_DIRECTORY ${VTKm_EXECUTABLE_OUTPUT_PATH}
CXX_VISIBILITY_PRESET "hidden"
CUDA_VISIBILITY_PRESET "hidden"
CUDA_SEPARABLE_COMPILATION ON
)
vtkm_add_target_information(${exe_name} DEVICE_SOURCES ${VTKm_AB_FILE})
endfunction()
@ -39,7 +42,7 @@ set(benchmarks
)
foreach (benchmark ${benchmarks})
add_benchmark(NAME ${benchmark} FILE ${benchmark}.cxx LIBS vtkm_filter)
add_benchmark(NAME ${benchmark} FILE ${benchmark}.cxx LIBS vtkm_source vtkm_filter)
endforeach ()
if(TARGET vtkm_rendering)

@ -15,7 +15,7 @@ coding and because we expect vtkm to have continual interaction with VTK.
form. Various copyright specific details are referenced in the LICENSE.txt
file.
```
```
//==========================================================================
// Copyright (c) Kitware, Inc.
// All rights reserved.
@ -25,7 +25,7 @@ coding and because we expect vtkm to have continual interaction with VTK.
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the above copyright notice for more information.
//==========================================================================
```
```
+ The CopyrightStatement test checks all files for a similar statement.
The test will print out a suggested text that can be copied and pasted
@ -41,22 +41,21 @@ coding and because we expect vtkm to have continual interaction with VTK.
directory, with non alphanumeric characters, such as / and . replaced
with underscores. The `#endif` part of the guard at the bottom of the
file should include the guard name in a comment. For example, the
vtkm/cont/ArrayHandle.h header contains the guard
```cpp
#ifndef vtk_m_cont_ArrayHandle_h
#define vtk_m_cont_ArrayHandle_h
```
at the top and
```cpp
#endif //vtk_m_cont_ArrayHandle_h
```
at the bottom.
vtkm/cont/ArrayHandle.h header contains the guard demostrated below.
The unique use of vtk_m over vtkm is to allow auto-complete engines the
ability to differentiate between the header guards and VTKM_ macros
that are used within the code base.
```cpp
#ifndef vtk_m_cont_ArrayHandle_h
#define vtk_m_cont_ArrayHandle_h
// All ArrayHandle code here
#endif //vtk_m_cont_ArrayHandle_h
```
+ The VTK-m toolkit has several nested namespaces. The declaration of
each namespace should be on its own line, and the code inside the
namespace bracket should not be indented. The closing brace at the
@ -64,7 +63,7 @@ coding and because we expect vtkm to have continual interaction with VTK.
the namespace. Namespaces can be grouped as desired. The following is a
valid use of namespaces.
```cpp
```cpp
namespace vtkm {
namespace cont {
namespace detail {
@ -73,7 +72,7 @@ class InternalClass;
class ExposedClass;
}
} // namespace vtkm::cont
```
```
+ Multiple inheritance is not allowed in VTK-m classes.
@ -170,7 +169,7 @@ for (auto v : vector)
or detail class clearly associated with it, the reference can be
shortened to `internal::` or `detail::`.
+ use `this->` inside of methods when accessing class methods and
+ Use `this->` inside of methods when accessing class methods and
instance variables to distinguish between local variables and instance
variables.

@ -0,0 +1,244 @@
# Add `ArrayHandleDecorator`.
`ArrayHandleDecorator` is given a `DecoratorImpl` class and a list of one or
more source `ArrayHandle`s. There are no restrictions on the size or type of
the source `ArrayHandle`s.
The decorator implementation class is described below:
```
struct ExampleDecoratorImplementation
{
// Takes one portal for each source array handle (only two shown).
// Returns a functor that defines:
//
// ValueType operator()(vtkm::Id id) const;
//
// which takes an index and returns a value which should be produced by
// the source arrays somehow. This ValueType will be the ValueType of the
// ArrayHandleDecorator.
//
// Both SomeFunctor::operator() and CreateFunctor must be const.
//
template <typename Portal1Type, typename Portal2Type>
SomeFunctor CreateFunctor(Portal1Type portal1, Portal2Type portal2) const;
// Takes one portal for each source array handle (only two shown).
// Returns a functor that defines:
//
// void operator()(vtkm::Id id, ValueType val) const;
//
// which takes an index and a value, which should be used to modify one
// or more of the source arrays.
//
// CreateInverseFunctor is optional; if not provided, the
// ArrayHandleDecorator will be read-only. In addition, if all of the
// source ArrayHandles are read-only, the inverse functor will not be used
// and the ArrayHandleDecorator will be read only.
//
// Both SomeInverseFunctor::operator() and CreateInverseFunctor must be
// const.
//
template <typename Portal1Type, typename Portal2Type>
SomeInverseFunctor CreateInverseFunctor(Portal1Type portal1,
Portal2Type portal2) const;
};
```
Some example implementation classes are provided below:
Reverse a ScanExtended:
```
// Decorator implementation that reverses the ScanExtended operation.
//
// The resulting ArrayHandleDecorator will take an array produced by the
// ScanExtended algorithm and return the original ScanExtended input.
//
// Some interesting things about this:
// - The ArrayHandleDecorator's ValueType will not be the same as the
// ScanPortal's ValueType. The Decorator ValueType is determined by the
// return type of Functor::operator().
// - The ScanPortal has more values than the ArrayHandleDecorator. The
// number of values the ArrayHandleDecorator should hold is set during
// construction and may differ from the arrays it holds.
template <typename ValueType>
struct ScanExtendedToNumIndicesDecorImpl
{
template <typename ScanPortalType>
struct Functor
{
ScanPortalType ScanPortal;
VTKM_EXEC_CONT
ValueType operator()(vtkm::Id idx) const
{
return static_cast<ValueType>(this->ScanPortal.Get(idx + 1) -
this->ScanPortal.Get(idx));
}
};
template <typename ScanPortalType>
Functor<ScanPortalType> CreateFunctor(ScanPortalType portal) const
{
return {portal};
}
};
auto numIndicesOrig = vtkm::cont::make_ArrayHandleCounting(ValueType{0},
ValueType{1},
ARRAY_SIZE);
vtkm::cont::ArrayHandle<vtkm::Id> scan;
vtkm::cont::Algorithm::ScanExtended(
vtkm::cont::make_ArrayHandleCast<vtkm::Id>(numIndicesOrig),
scan);
auto numIndicesDecor = vtkm::cont::make_ArrayHandleDecorator(
ARRAY_SIZE,
ScanExtendedToNumIndicesDecorImpl<ValueType>{},
scan);
```
Combine two other `ArrayHandle`s using an arbitrary binary operation:
```
// Decorator implementation that demonstrates how to create functors that
// hold custom state. Here, the functors have a customizable Operation
// member.
//
// This implementation is used to create a read-only ArrayHandleDecorator
// that combines the values in two other ArrayHandles using an arbitrary
// binary operation (e.g. vtkm::Maximum, vtkm::Add, etc).
template <typename ValueType, typename OperationType>
struct BinaryOperationDecorImpl
{
OperationType Operation;
// The functor use to read values. Note that it holds extra state in
// addition to the portals.
template <typename Portal1Type, typename Portal2Type>
struct Functor
{
Portal1Type Portal1;
Portal2Type Portal2;
OperationType Operation;
VTKM_EXEC_CONT
ValueType operator()(vtkm::Id idx) const
{
return this->Operation(static_cast<ValueType>(this->Portal1.Get(idx)),
static_cast<ValueType>(this->Portal2.Get(idx)));
}
};
// A non-variadic example of a factory function to produce a functor. This
// is where the extra state is passed into the functor.
template <typename P1T, typename P2T>
Functor<P1T, P2T> CreateFunctor(P1T p1, P2T p2) const
{
return {p1, p2, this->Operation};
}
};
BinaryOperationDecorImpl<ValueType, vtkm::Maximum> factory{vtkm::Maximum{}};
auto decorArray = vtkm::cont::make_ArrayHandleDecorator(ARRAY_SIZE,
factory,
array1,
array2);
```
A factory that does a complex and invertible operation on three portals:
```
// Decorator implemenation that demonstrates how to write invertible functors
// that combine three array handles with complex access logic. The resulting
// ArrayHandleDecorator can be both read from and written to.
//
// Constructs functors that take three portals.
//
// The first portal's values are accessed in reverse order.
// The second portal's values are accessed in normal order.
// The third portal's values are accessed via ((idx + 3) % size).
//
// Functor will return the max of the first two added to the third.
//
// InverseFunctor will update the third portal such that the Functor would
// return the indicated value.
struct InvertibleDecorImpl
{
// The functor used for reading data from the three portals.
template <typename Portal1Type, typename Portal2Type, typename Portal3Type>
struct Functor
{
using ValueType = typename Portal1Type::ValueType;
Portal1Type Portal1;
Portal2Type Portal2;
Portal3Type Portal3;
VTKM_EXEC_CONT ValueType operator()(vtkm::Id idx) const
{
const auto idx1 = this->Portal1.GetNumberOfValues() - idx - 1;
const auto idx2 = idx;
const auto idx3 = (idx + 3) % this->Portal3.GetNumberOfValues();
const auto v1 = this->Portal1.Get(idx1);
const auto v2 = this->Portal2.Get(idx2);
const auto v3 = this->Portal3.Get(idx3);
return vtkm::Max(v1, v2) + v3;
}
};
// The functor used for writing. Only Portal3 is written to, the other
// portals may be read-only.
template <typename Portal1Type, typename Portal2Type, typename Portal3Type>
struct InverseFunctor
{
using ValueType = typename Portal1Type::ValueType;
Portal1Type Portal1;
Portal2Type Portal2;
Portal3Type Portal3;
VTKM_EXEC_CONT void operator()(vtkm::Id idx, const ValueType &vIn) const
{
const auto v1 = this->Portal1.Get(this->Portal1.GetNumberOfValues() - idx - 1);
const auto v2 = this->Portal2.Get(idx);
const auto vNew = static_cast<ValueType>(vIn - vtkm::Max(v1, v2));
this->Portal3.Set((idx + 3) % this->Portal3.GetNumberOfValues(), vNew);
}
};
// Factory function that takes 3 portals as input and creates an instance
// of Functor with them. Variadic template parameters are used here, but are
// not necessary.
template <typename... PortalTs>
Functor<typename std::decay<PortalTs>::type...>
CreateFunctor(PortalTs&&... portals) const
{
VTKM_STATIC_ASSERT(sizeof...(PortalTs) == 3);
return {std::forward<PortalTs>(portals)...};
}
// Factory function that takes 3 portals as input and creates an instance
// of InverseFunctor with them. Variadic template parameters are used here,
// but are not necessary.
template <typename... PortalTs>
InverseFunctor<typename std::decay<PortalTs>::type...>
CreateInverseFunctor(PortalTs&&... portals) const
{
VTKM_STATIC_ASSERT(sizeof...(PortalTs) == 3);
return {std::forward<PortalTs>(portals)...};
}
};
// Note that only ah3 must be writable for ahInv to be writable. ah1 and ah2
// may be read-only arrays.
auto ahInv = vtkm::cont::make_ArrayHandleDecorator(ARRAY_SIZE,
InvertibleDecorImpl{},
ah1,
ah2,
ah3);
```

@ -0,0 +1,16 @@
# Added Source class hierarchy
A new class hierarchy for dataset source was added. The intention is to
consolidate and refactor various (procedural) dataset generators for unit
tests, especially the multiple copy&past-ed implementations of the Tangle
field. As they are compiled into a library rather than as header files,
we also expect the overall compile time to decrease.
The public interface of dataset source is modeled after Filter. A new DataSet
is returned by calling the Execute() method of the dataset source, for example:
```cpp
vtkm::Id3 dims(4, 4, 4);
vtkm::source::Tangle tangle(dims);
vtkm::cont::DataSet dataSet = tangle.Execute();
```

@ -0,0 +1,80 @@
# CMake vtkm_add_target_information() makes using vtk-m easier
This higher order function allow build-systems that use VTK-m
to use `add_library` or `add_executable` calls but still have an
easy to way to get the required information to have VTK-m using
compilation units compile correctly.
```cmake
vtkm_add_target_information(
target[s]
[ DROP_UNUSED_SYMBOLS ]
[ MODIFY_CUDA_FLAGS ]
[ EXTENDS_VTKM ]
[ DEVICE_SOURCES <source_list> ]
)
```
Usage:
```cmake
add_library(lib_that_uses_vtkm STATIC a.cxx)
vtkm_add_target_information(lib_that_uses_vtkm
MODIFY_CUDA_FLAGS
DEVICE_SOURCES a.cxx
)
target_link_libraries(lib_that_uses_vtkm PRIVATE vtkm_filter)
```
## Options to vtkm_add_target_information
- DROP_UNUSED_SYMBOLS: If enabled will apply the appropiate link
flags to drop unused VTK-m symbols. This works as VTK-m is compiled with
-ffunction-sections which allows for the linker to remove unused functions.
If you are building a program that loads runtime plugins that can call
VTK-m this most likely shouldn't be used as symbols the plugin expects
to exist will be removed.
Enabling this will help keep library sizes down when using static builds
of VTK-m as only the functions you call will be kept. This can have a
dramatic impact on the size of the resulting executable / shared library.
- MODIFY_CUDA_FLAGS: If enabled will add the required -arch=<ver> flags
that VTK-m was compiled with. If you have multiple libraries that use
VTK-m calling `vtkm_add_target_information` multiple times with
`MODIFY_CUDA_FLAGS` will cause duplicate compiler flags. To resolve this issue
you can; pass all targets and sources to a single `vtkm_add_target_information`
call, have the first one use `MODIFY_CUDA_FLAGS`, or use the provided
standalone `vtkm_get_cuda_flags` function.
- DEVICE_SOURCES: The collection of source files that are used by `target(s)` that
need to be marked as going to a special compiler for certain device adapters
such as CUDA.
- EXTENDS_VTKM: Some programming models have restrictions on how types can be used,
passed across library boundaries, and derived from.
For example CUDA doesn't allow device side calls across dynamic library boundaries,
and requires all polymorphic classes to be reachable at dynamic library/executable
link time.
To accommodate these restrictions we need to handle the following allowable
use-cases:
- Object library: do nothing, zero restrictions
- Executable: do nothing, zero restrictions
- Static library: do nothing, zero restrictions
- Dynamic library:
- Wanting to use VTK-m as implementation detail, doesn't expose VTK-m
types to consumers. This is supported no matter if CUDA is enabled.
- Wanting to extend VTK-m and provide these types to consumers.
This is only supported when CUDA isn't enabled. Otherwise we need to ERROR!
- Wanting to pass known VTK-m types across library boundaries for others
to use in filters/worklets. This is only supported when CUDA isn't enabled. Otherwise we need to ERROR!
For most consumers they can ignore the `EXTENDS_VTKM` property as the default will be correct.
The `vtkm_add_target_information` higher order function leverages the `vtkm_add_drop_unused_function_flags` and
`vtkm_get_cuda_flags` functions which can be used by VTK-m consuming applications.
The `vtkm_add_drop_unused_function_flags` function implements all the behavior of `DROP_UNUSED_SYMBOLS` for a single
target.
The `vtkm_get_cuda_flags` function implements a general form of `MODIFY_CUDA_FLAGS` but instead of modiyfing
the `CMAKE_CUDA_FLAGS` it will add the flags to any variable passed to it.

@ -0,0 +1,73 @@
# Provide pre-built filters in the vtkm_filter library.
VTK-m now provides the following pre built versions of
the following filters as part of the vtkm_filter library,
when executed with the default types.
- CellAverage
- CleanGrid
- ClipWithField
- ClipWithImplicitFunction
- Contour
- ExternalFaces
- ExtractStuctured
- PointAverage
- Threshold
- VectorMagnitude
The decision on providing a subset of filters as a library
was based on balancing the resulting library size and cross domain
applicibaility of the filter. So the initial set of algorithms
have been selected by looking at what is commonly used by
current VTK-m consuming applications.
By default types we mean that no explicit user policy has been
passed to the `Execute` method on these filters. For example
the following will use the pre-build `Threshold` and `CleanGrid`
filters:
```cpp
vtkm::cont::DataSet input = ...;
//convert input to an unstructured grid
vtkm::filter::CleanGrid clean;
auto cleaned = clean.Execute(input);
vtkm::filter::Threshold threshold;
threshold.SetLowerThreshold(60.1);
threshold.SetUpperThreshold(60.1);
threshold.SetActiveField("pointvar");
threshold.SetFieldsToPass("cellvar");
auto output = threshold.Execute(cleaned);
...
```
While the following, even though it is a subset of the default
policy will need to be compiled by the consuming library by
including the relevant `.hxx` files
```cpp
#include <vtkm/filter/CleanGrid.hxx>
#include <vtkm/filter/Threshold.hxx>
...
struct CustomPolicy : vtkm::filter::PolicyBase<CustomPolicy>
{
// Defaults are the same as PolicyDefault expect for the field types
using FieldTypeList = vtkm::ListTagBase<vtkm::FloatDefault, vtkm::Vec3f>;
};
...
vtkm::cont::DataSet input = ...;
//convert input to an unstructured grid
vtkm::filter::CleanGrid clean;
auto cleaned = clean.Execute(input, CustomPolicy{});
vtkm::filter::Threshold threshold;
threshold.SetLowerThreshold(60.1);
threshold.SetUpperThreshold(60.1);
threshold.SetActiveField("pointvar");
threshold.SetFieldsToPass("cellvar");
auto output = threshold.Execute(cleaned, CustomPolicy{});
...
```

@ -17,5 +17,5 @@ add_executable(Clipping Clipping.cxx)
target_link_libraries(Clipping PRIVATE vtkm_filter)
vtkm_add_target_information(Clipping
MODIFY_CUDA_FLAGS
DROP_UNUSED_SYMBOLS MODIFY_CUDA_FLAGS
DEVICE_SOURCES Clipping.cxx)

@ -16,12 +16,11 @@ find_package(VTKm REQUIRED QUIET)
add_executable(ContourTreeMesh2D ContourTreeMesh2D.cxx)
target_link_libraries(ContourTreeMesh2D vtkm_filter)
vtkm_add_target_information(ContourTreeMesh2D
DEVICE_SOURCES ContourTreeMesh2D.cxx)
add_executable(ContourTreeMesh3D ContourTreeMesh3D.cxx)
target_link_libraries(ContourTreeMesh3D vtkm_filter)
vtkm_add_target_information(ContourTreeMesh3D
vtkm_add_target_information(ContourTreeMesh2D ContourTreeMesh3D
DROP_UNUSED_SYMBOLS
MODIFY_CUDA_FLAGS
DEVICE_SOURCES ContourTreeMesh3D.cxx)
DEVICE_SOURCES
ContourTreeMesh2D.cxx ContourTreeMesh3D.cxx)

@ -50,22 +50,46 @@
## Hamish Carr (University of Leeds), Gunther H. Weber (LBNL), and
## Oliver Ruebel (LBNL)
##==============================================================================
cmake_minimum_required(VERSION 3.8...3.15 FATAL_ERROR)
#Find the VTK-m package
# Find the VTK-m package
find_package(VTKm REQUIRED QUIET)
add_executable(ContourTree ContourTreeApp.cxx)
target_link_libraries(ContourTree vtkm_filter)
vtkm_add_target_information(ContourTree
MODIFY_CUDA_FLAGS
####################################
# Serial
####################################
add_executable(ContourTree_Augmented ContourTreeApp.cxx)
target_link_libraries(ContourTree_Augmented vtkm_filter)
vtkm_add_target_information(ContourTree_Augmented
DROP_UNUSED_SYMBOLS MODIFY_CUDA_FLAGS
DEVICE_SOURCES ContourTreeApp.cxx)
####################################
# Debug algorithm build
####################################
# target_compile_definitions(ContourTree PRIVATE DEBUG_PRINT)
if(TARGET vtkm::tbb)
# TBB 2D/3D/MC
target_compile_definitions(ContourTree PRIVATE ENABLE_SET_NUM_THREADS)
option (VTKM_EXAMPLE_CONTOURTREE_ENABLE_DEBUG_PRINT Off)
if (VTKM_EXAMPLE_CONTOURTREE_ENABLE_DEBUG_PRINT)
target_compile_definitions(ContourTree_Augmented PRIVATE "DEBUG_PRINT")
endif()
if (TARGET vtkm::tbb)
target_compile_definitions(ContourTree_Augmented PRIVATE "ENABLE_SET_NUM_THREADS")
endif()
####################################
# MPI
####################################
if (VTKm_ENABLE_MPI)
add_executable(ContourTree_Augmented_MPI ContourTreeApp.cxx)
target_link_libraries(ContourTree_Augmented_MPI vtkm_filter)
vtkm_add_target_information(ContourTree_Augmented_MPI
MODIFY_CUDA_FLAGS
DEVICE_SOURCES ContourTreeApp.cxx)
target_compile_definitions(ContourTree_Augmented_MPI PRIVATE "WITH_MPI")
option (VTKM_EXAMPLE_CONTOURTREE_ENABLE_DEBUG_PRINT Off)
if (VTKM_EXAMPLE_CONTOURTREE_ENABLE_DEBUG_PRINT)
target_compile_definitions(ContourTree_Augmented_MPI PRIVATE "DEBUG_PRINT")
endif()
if (TARGET vtkm::tbb)
target_compile_definitions(ContourTree_Augmented_MPI PRIVATE "ENABLE_SET_NUM_THREADS")
endif()
endif()

@ -2,10 +2,20 @@
// Copyright (c) Kitware, Inc.
// All rights reserved.
// See LICENSE.txt for details.
//
// This software is distributed WITHOUT ANY WARRANTY; without even
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the above copyright notice for more information.
//
// Copyright 2014 National Technology & Engineering Solutions of Sandia, LLC (NTESS).
// Copyright 2014 UT-Battelle, LLC.
// Copyright 2014 Los Alamos National Security.
//
// Under the terms of Contract DE-NA0003525 with NTESS,
// the U.S. Government retains certain rights in this software.
//
// Under the terms of Contract DE-AC52-06NA25396 with Los Alamos National
// Laboratory (LANL), the U.S. Government retains certain rights in
// this software.
//============================================================================
// Copyright (c) 2018, The Regents of the University of California, through
// Lawrence Berkeley National Laboratory (subject to receipt of any required approvals
@ -50,32 +60,47 @@
// Oliver Ruebel (LBNL)
//==============================================================================
#define DEBUG_TIMING
#ifdef ENABLE_SET_NUM_THREADS
#include "tbb/task_scheduler_init.h"
#endif
#include <vtkm/Types.h>
#include <vtkm/cont/ArrayHandle.h>
#include <vtkm/cont/DataSet.h>
#include <vtkm/cont/DataSetBuilderUniform.h>
#include <vtkm/cont/DataSetFieldAdd.h>
#include <vtkm/cont/Initialize.h>
#include <vtkm/cont/RuntimeDeviceTracker.h>
#include <vtkm/cont/Timer.h>
#include <vtkm/filter/ContourTreeUniformAugmented.h>
#include <vtkm/worklet/contourtree_augmented/PrintVectors.h>
#include <vtkm/worklet/contourtree_augmented/ProcessContourTree.h>
#include <vtkm/worklet/contourtree_augmented/Types.h>
#include <vtkm/worklet/contourtree_augmented/processcontourtree/Branch.h>
#ifdef ENABLE_SET_NUM_THREADS
#include "tbb/task_scheduler_init.h"
#endif
// clang-format off
VTKM_THIRDPARTY_PRE_INCLUDE
#include <vtkm/thirdparty/diy/Configure.h>
#include <vtkm/thirdparty/diy/diy.h>
VTKM_THIRDPARTY_POST_INCLUDE
// clang-format on
#ifdef WITH_MPI
#include <mpi.h>
#endif
#include <fstream>
#include <iomanip>
#include <iostream>
#include <stdio.h>
#include <string>
#include <utility>
#include <vector>
#define DEBUG_TIMING
using ValueType = vtkm::Float32;
using BranchType = vtkm::worklet::contourtree_augmented::process_contourtree_inc::Branch<ValueType>;
namespace cppp2_ns = vtkm::worklet::contourtree_augmented;
// Simple helper class for parsing the command line options
@ -84,10 +109,10 @@ class ParseCL
public:
ParseCL() {}
void parse(std::vector<std::string>::size_type argc, char** argv)
void parse(int& argc, char** argv)
{
mCLOptions.resize(std::vector<std::string>::size_type(argc));
for (std::vector<std::string>::size_type i = 1; i < argc; ++i)
mCLOptions.resize(static_cast<std::size_t>(argc));
for (std::size_t i = 1; i < static_cast<std::size_t>(argc); ++i)
{
this->mCLOptions[i] = std::string(argv[i]);
}
@ -105,7 +130,7 @@ public:
}
else
{
return static_cast<vtkm::Id>(it - this->mCLOptions.begin());
return (it - this->mCLOptions.begin());
}
}
@ -113,10 +138,10 @@ public:
std::string getOption(const std::string& option) const
{
vtkm::Id index = this->findOption(option);
std::size_t index = static_cast<std::size_t>(this->findOption(option));
if (index >= 0)
{
std::string val = this->mCLOptions[std::vector<std::string>::size_type(index)];
std::string val = this->mCLOptions[index];
auto valPos = val.find("=");
if (valPos)
{
@ -137,40 +162,151 @@ private:
// Compute and render an isosurface for a uniform grid example
int main(int argc, char* argv[])
{
auto opts = vtkm::cont::InitializeOptions::DefaultAnyDevice;
vtkm::cont::InitializeResult config = vtkm::cont::Initialize(argc, argv, opts);
#ifdef WITH_MPI
// Setup the MPI environment.
MPI_Init(&argc, &argv);
auto comm = MPI_COMM_WORLD;
// Tell VTK-m which communicator it should use.
vtkm::cont::EnvironmentTracker::SetCommunicator(vtkmdiy::mpi::communicator(comm));
// get the rank and size
int rank, size;
MPI_Comm_rank(comm, &rank);
MPI_Comm_size(comm, &size);
int numBlocks = size;
int blocksPerRank = 1;
if (rank == 0)
{
std::cout << "Running with MPI. #ranks=" << size << std::endl;
}
#else
std::cout << "Single node run" << std::endl;
int rank = 0;
#endif
vtkm::cont::Timer totalTime;
totalTime.Start();
vtkm::Float64 prevTime = 0;
vtkm::Float64 currTime = 0;
vtkm::cont::Timer totalTime;
totalTime.Start();
if (rank == 0)
{
std::cout << "ContourTreePPP2Mesh <options> <fileName>" << std::endl;
}
////////////////////////////////////////////
// Parse the command line options
////////////////////////////////////////////
ParseCL parser;
parser.parse(std::vector<std::string>::size_type(argc), argv);
parser.parse(argc, argv);
std::string filename = parser.getOptions().back();
bool computeRegularStructure = true;
unsigned int computeRegularStructure = 1; // 1=fully augmented
bool useMarchingCubes = false;
bool computeBranchDecomposition = true;
bool printContourTree = false;
if (parser.hasOption("--augmentTree"))
computeRegularStructure = std::stoi(parser.getOption("--augmentTree"));
computeRegularStructure =
static_cast<unsigned int>(std::stoi(parser.getOption("--augmentTree")));
if (parser.hasOption("--mc"))
useMarchingCubes = true;
if (parser.hasOption("--printCT"))
printContourTree = true;
if (parser.hasOption("--branchDecomp"))
computeBranchDecomposition = std::stoi(parser.getOption("--branchDecomp"));
// We need the fully augmented tree to compute the branch decomposition
if (computeBranchDecomposition && (computeRegularStructure != 1))
{
std::cout << "Regular structure is required for branch decomposition."
" Disabling branch decomposition"
<< std::endl;
computeBranchDecomposition = false;
}
std::string device("default");
if (parser.hasOption("--device"))
{
device = parser.getOption("--device");
auto& rtTracker = vtkm::cont::GetRuntimeDeviceTracker();
if (device == "serial" && rtTracker.CanRunOn(vtkm::cont::DeviceAdapterTagSerial()))
{
rtTracker.ForceDevice(vtkm::cont::DeviceAdapterTagSerial());
}
else if (device == "openmp" && rtTracker.CanRunOn(vtkm::cont::DeviceAdapterTagOpenMP()))
{
rtTracker.ForceDevice(vtkm::cont::DeviceAdapterTagOpenMP());
}
else if (device == "tbb" && rtTracker.CanRunOn(vtkm::cont::DeviceAdapterTagTBB()))
{
rtTracker.ForceDevice(vtkm::cont::DeviceAdapterTagTBB());
}
else if (device == "cuda" && rtTracker.CanRunOn(vtkm::cont::DeviceAdapterTagCuda()))
{
rtTracker.ForceDevice(vtkm::cont::DeviceAdapterTagCuda());
}
else
{
std::cout << "Invalid or unavialable device adapter: " << device << std::endl;
return EXIT_FAILURE;
}
}
#ifdef ENABLE_SET_NUM_THREADS
int numThreads = tbb::task_scheduler_init::default_num_threads();
if (parser.hasOption("--numThreads"))
{
if (device == "default" &&
vtkm::cont::GetRuntimeDeviceTracker().CanRunOn(vtkm::cont::DeviceAdapterTagTBB()))
{
std::cout << "--numThreads specified without device. Forcing device as tbb.";
device = "tbb";
vtkm::cont::GetRuntimeDeviceTracker().ForceDevice(vtkm::cont::DeviceAdapterTagTBB());
}
numThreads = std::stoi(parser.getOption("--numThreads"));
if (device != "tbb")
{
std::cout << "numThreads will be ignored for devices other than tbb";
}
}
tbb::task_scheduler_init schedulerInit(numThreads);
#endif
if (argc < 2 || parser.hasOption("--help") || parser.hasOption("-h"))
// Iso value selection parameters
// Approach to be used to select contours based on the tree
vtkm::Id contourType = 0;
// Error away from critical point
ValueType eps = 0.00001f;
// Number of iso levels to be selected. By default we disable the isovalue selection.
vtkm::Id numLevels = 0;
// Number of components the tree should be simplified to
vtkm::Id numComp = numLevels + 1;
// Method to be used to compute the relevant iso values
vtkm::Id contourSelectMethod = 0;
bool usePersistenceSorter = true;
if (parser.hasOption("--levels"))
numLevels = std::stoi(parser.getOption("--levels"));
if (parser.hasOption("--type"))
contourType = std::stoi(parser.getOption("--type"));
if (parser.hasOption("--eps"))
eps = std::stof(parser.getOption("--eps"));
if (parser.hasOption("--method"))
contourSelectMethod = std::stoi(parser.getOption("--method"));
if (parser.hasOption("--comp"))
numComp = std::stoi(parser.getOption("--comp"));
if (contourSelectMethod == 0)
numComp = numLevels + 1;
if (parser.hasOption("--useVolumeSorter"))
usePersistenceSorter = false;
if ((numLevels > 0) && (!computeBranchDecomposition))
{
std::cout << "Iso level selection only available when branch decomposition is enabled."
" Disabling iso value selection"
<< std::endl;
numLevels = 0;
}
if (rank == 0 && (argc < 2 || parser.hasOption("--help") || parser.hasOption("-h")))
{
std::cout << "Parameter is <fileName>" << std::endl;
std::cout << "File is expected to be ASCII with either: " << std::endl;
@ -184,37 +320,118 @@ int main(int argc, char* argv[])
std::cout << "--mc Use marching cubes interpolation for contour tree calculation. "
"(Default=False)"
<< std::endl;
std::cout << "--augmentTree Compute the augmented contour tree. (Default=True)"
std::cout << "--augmentTree 1 = compute the fully augmented contour tree (Default)"
<< std::endl;
std::cout << " 2 = compute the boundary augmented contour tree " << std::endl;
std::cout << " 0 = no augmentation. NOTE: When using MPI, local ranks use"
<< std::endl;
std::cout << " boundary augmentation to support parallel merge of blocks"
<< std::endl;
std::cout << "--branchDecomp Compute the volume branch decomposition for the contour tree. "
"Requires --augmentTree (Default=True)"
<< std::endl;
std::cout << "--printCT Print the contour tree. (Default=False)" << std::endl;
std::cout << "--device Set the device to use (serial, openmp, tbb, cuda). "
"Use the default device if unspecified"
<< std::endl;
#ifdef ENABLE_SET_NUM_THREADS
std::cout << "--numThreads Specify the number of threads to use. Available only with TBB."
std::cout << "--numThreads Specifiy the number of threads to use. Available only with TBB."
<< std::endl;
#endif
std::cout << config.Usage << std::endl;
return 0;
std::cout << std::endl;
std::cout << "Isovalue selection options: (require --branchDecomp=1 and augmentTree=1)"
<< std::endl;
std::cout << "--levels=<int> Number of iso-contour levels to be used (default=0, i.e., "
"disable isovalue computation)"
<< std::endl;
std::cout << "--comp=<int> Number of components the contour tree should be simplified to. "
"Only used if method==1. (default=0)"
<< std::endl;
std::cout
<< "--eps=<float> Floating point offset awary from the critical point. (default=0.00001)"
<< std::endl;
std::cout << "--type=<int> Approach to be used for selection of iso-values. 0=saddle+-eps; "
"1=mid point between saddle and extremum, 2=extremum+-eps. (default=0)"
<< std::endl;
std::cout << "--method=<int> Method used for selecting relevant iso-values. (default=0)"
<< std::endl;
#ifdef WITH_MPI
MPI_Finalize();
#endif
return EXIT_SUCCESS;
}
std::cout << "ContourTree <options> <fileName>" << std::endl;
std::cout << "Settings:" << std::endl;
std::cout << " filename=" << filename << std::endl;
std::cout << " mc=" << useMarchingCubes << std::endl;
std::cout << " augmentTree=" << computeRegularStructure << std::endl;
std::cout << " branchDecomp=" << computeBranchDecomposition << std::endl;
#ifdef ENABLE_SET_NUM_THREADS
std::cout << " numThreads=" << numThreads << std::endl;
if (rank == 0)
{
std::cout << "Settings:" << std::endl;
std::cout << " filename=" << filename << std::endl;
std::cout << " device=" << device << std::endl;
std::cout << " mc=" << useMarchingCubes << std::endl;
std::cout << " augmentTree=" << computeRegularStructure << std::endl;
std::cout << " branchDecomp=" << computeBranchDecomposition << std::endl;
#ifdef WITH_MPI
std::cout << " nblocks=" << numBlocks << std::endl;
#endif
std::cout << config.Usage << std::endl;
std::cout << std::endl;
#ifdef ENABLE_SET_NUM_THREADS
std::cout << " numThreads=" << numThreads << std::endl;
#endif
std::cout << " computeIsovalues=" << (numLevels > 0) << std::endl;
if (numLevels > 0)
{
std::cout << " levels=" << numLevels << std::endl;
std::cout << " eps=" << eps << std::endl;
std::cout << " comp" << numComp << std::endl;
std::cout << " type=" << contourType << std::endl;
std::cout << " method=" << contourSelectMethod << std::endl;
std::cout << " mc=" << useMarchingCubes << std::endl;
std::cout << " use" << (usePersistenceSorter ? "PersistenceSorter" : "VolumeSorter")
<< std::endl;
}
std::cout << std::endl;
}
currTime = totalTime.GetElapsedTime();
vtkm::Float64 startUpTime = currTime - prevTime;
prevTime = currTime;
// Redirect stdout to file if we are using MPI with Debugging
#ifdef WITH_MPI
#ifdef DEBUG_PRINT
// From https://www.unix.com/302983597-post2.html
char* cstr_filename = new char[15];
snprintf(cstr_filename, sizeof(filename), "cout_%d.log", rank);
int out = open(cstr_filename, O_RDWR | O_CREAT | O_APPEND, 0600);
if (-1 == out)
{
perror("opening cout.log");
return 255;
}
snprintf(cstr_filename, sizeof(cstr_filename), "cerr_%d.log", rank);
int err = open(cstr_filename, O_RDWR | O_CREAT | O_APPEND, 0600);
if (-1 == err)
{
perror("opening cerr.log");
return 255;
}
int save_out = dup(fileno(stdout));
int save_err = dup(fileno(stderr));
if (-1 == dup2(out, fileno(stdout)))
{
perror("cannot redirect stdout");
return 255;
}
if (-1 == dup2(err, fileno(stderr)))
{
perror("cannot redirect stderr");
return 255;
}
delete[] cstr_filename;
#endif
#endif
///////////////////////////////////////////////
// Read the input data
///////////////////////////////////////////////
@ -223,42 +440,54 @@ int main(int argc, char* argv[])
return 0;
// Read the dimensions of the mesh, i.e,. number of elementes in x, y, and z
std::vector<vtkm::Id> dims;
std::vector<std::size_t> dims;
std::string line;
getline(inFile, line);
std::istringstream linestream(line);
vtkm::Id dimVertices;
std::size_t dimVertices;
while (linestream >> dimVertices)
{
dims.push_back(dimVertices);
}
// Compute the number of vertices, i.e., xdim * ydim * zdim
auto nDims = dims.size();
std::vector<vtkm::Float32>::size_type nVertices = std::vector<vtkm::Float32>::size_type(
std::accumulate(dims.begin(), dims.end(), vtkm::Id(1), std::multiplies<vtkm::Id>()));
unsigned short nDims = static_cast<unsigned short>(dims.size());
std::size_t nVertices = static_cast<std::size_t>(
std::accumulate(dims.begin(), dims.end(), 1, std::multiplies<std::size_t>()));
// Print the mesh metadata
std::cout << "Number of dimensions: " << nDims << std::endl;
std::cout << "Number of mesh vertices: " << nVertices << std::endl;
if (rank == 0)
{
std::cout << "Number of dimensions: " << nDims << std::endl;
std::cout << "Number of mesh vertices: " << nVertices << std::endl;
}
// Check the the number of dimensiosn is either 2D or 3D
if (nDims < 2 || nDims > 3)
bool invalidNumDimensions = (nDims < 2 || nDims > 3);
bool invalidMCOption = (useMarchingCubes && nDims != 3);
if (rank == 0)
{
std::cout << "The input mesh is " << nDims << "D. Input data must be either 2D or 3D."
<< std::endl;
return 0;
if (invalidNumDimensions)
{
std::cout << "The input mesh is " << nDims << "D. Input data must be either 2D or 3D."
<< std::endl;
}
if (invalidMCOption)
{
std::cout << "The input mesh is " << nDims
<< "D. Contour tree using marching cubes only supported for 3D data." << std::endl;
}
}
if (useMarchingCubes && nDims != 3)
if (invalidNumDimensions || invalidMCOption)
{
std::cout << "The input mesh is " << nDims
<< "D. Contour tree using marching cubes only supported for 3D data." << std::endl;
return 0;
#ifdef WITH_MPI
MPI_Finalize();
#endif
return EXIT_SUCCESS;
}
// read data
std::vector<vtkm::Float32> values(nVertices);
for (std::vector<vtkm::Float32>::size_type vertex = 0; vertex < nVertices; vertex++)
// Read data
std::vector<ValueType> values(nVertices);
for (std::size_t vertex = 0; vertex < nVertices; ++vertex)
{
inFile >> values[vertex];
}
@ -269,64 +498,190 @@ int main(int argc, char* argv[])
currTime = totalTime.GetElapsedTime();
vtkm::Float64 dataReadTime = currTime - prevTime;
prevTime = currTime;
// build the input dataset
vtkm::cont::DataSetBuilderUniform dsb;
vtkm::cont::DataSet inDataSet;
// 2D data
if (nDims == 2)
#ifndef WITH_MPI // construct regular, single-block VTK-M input dataset
vtkm::cont::DataSet inDataSet; // Single block dataset
{
vtkm::Id2 vdims;
vdims[0] = dims[0];
vdims[1] = dims[1];
inDataSet = dsb.Create(vdims);
// build the input dataset
// 2D data
if (nDims == 2)
{
vtkm::Id2 vdims;
vdims[0] = static_cast<vtkm::Id>(dims[0]);
vdims[1] = static_cast<vtkm::Id>(dims[1]);
inDataSet = dsb.Create(vdims);
}
// 3D data
else
{
vtkm::Id3 vdims;
vdims[0] = static_cast<vtkm::Id>(dims[0]);
vdims[1] = static_cast<vtkm::Id>(dims[1]);
vdims[2] = static_cast<vtkm::Id>(dims[2]);
inDataSet = dsb.Create(vdims);
}
vtkm::cont::DataSetFieldAdd dsf;
dsf.AddPointField(inDataSet, "values", values);
}
// 3D data
else
#else // Create a multi-block dataset for multi-block DIY-paralle processing
vtkm::cont::PartitionedDataSet inDataSet; // Partitioned variant of the input dataset
vtkm::Id3 blocksPerDim =
nDims == 3 ? vtkm::Id3(1, 1, numBlocks) : vtkm::Id3(1, numBlocks, 1); // Decompose the data into
vtkm::Id3 globalSize = nDims == 3 ? vtkm::Id3(static_cast<vtkm::Id>(dims[0]),
static_cast<vtkm::Id>(dims[1]),
static_cast<vtkm::Id>(dims[2]))
: vtkm::Id3(static_cast<vtkm::Id>(dims[0]),
static_cast<vtkm::Id>(dims[1]),
static_cast<vtkm::Id>(0));
vtkm::cont::ArrayHandle<vtkm::Id3> localBlockIndices;
vtkm::cont::ArrayHandle<vtkm::Id3> localBlockOrigins;
vtkm::cont::ArrayHandle<vtkm::Id3> localBlockSizes;
localBlockIndices.Allocate(blocksPerRank);
localBlockOrigins.Allocate(blocksPerRank);
localBlockSizes.Allocate(blocksPerRank);
auto localBlockIndicesPortal = localBlockIndices.GetPortalControl();
auto localBlockOriginsPortal = localBlockOrigins.GetPortalControl();
auto localBlockSizesPortal = localBlockSizes.GetPortalControl();
{
vtkm::Id3 vdims;
vdims[0] = dims[0];
vdims[1] = dims[1];
vdims[2] = dims[2];
inDataSet = dsb.Create(vdims);
vtkm::Id lastDimSize =
(nDims == 2) ? static_cast<vtkm::Id>(dims[1]) : static_cast<vtkm::Id>(dims[2]);
if (size > (lastDimSize / 2.))
{
if (rank == 0)
{
std::cout << "Number of ranks to large for data. Use " << lastDimSize / 2
<< "or fewer ranks" << std::endl;
}
MPI_Finalize();
return EXIT_FAILURE;
}
vtkm::Id standardBlockSize = (vtkm::Id)(lastDimSize / numBlocks);
vtkm::Id blockSize = standardBlockSize;
vtkm::Id blockSliceSize =
nDims == 2 ? static_cast<vtkm::Id>(dims[0]) : static_cast<vtkm::Id>((dims[0] * dims[1]));
vtkm::Id blockNumValues = blockSize * blockSliceSize;
vtkm::Id startBlock = blocksPerRank * rank;
vtkm::Id endBlock = startBlock + blocksPerRank;
for (vtkm::Id blockIndex = startBlock; blockIndex < endBlock; ++blockIndex)
{
vtkm::Id localBlockIndex = blockIndex - startBlock;
vtkm::Id blockStart = blockIndex * blockNumValues;
vtkm::Id blockEnd = blockStart + blockNumValues;
if (blockIndex < (numBlocks - 1)) // add overlap between regions
{
blockEnd += blockSliceSize;
}
else
{
blockEnd = lastDimSize * blockSliceSize;
}
vtkm::Id currBlockSize = (vtkm::Id)((blockEnd - blockStart) / blockSliceSize);
vtkm::cont::DataSet ds;
// 2D data
if (nDims == 2)
{
vtkm::Id2 vdims;
vdims[0] = static_cast<vtkm::Id>(currBlockSize);
vdims[1] = static_cast<vtkm::Id>(dims[0]);
vtkm::Vec<ValueType, 2> origin(0, blockIndex * blockSize);
vtkm::Vec<ValueType, 2> spacing(1, 1);
ds = dsb.Create(vdims, origin, spacing);
localBlockIndicesPortal.Set(localBlockIndex, vtkm::Id3(blockIndex, 0, 0));
localBlockOriginsPortal.Set(localBlockIndex,
vtkm::Id3((blockStart / blockSliceSize), 0, 0));
localBlockSizesPortal.Set(localBlockIndex,
vtkm::Id3(currBlockSize, static_cast<vtkm::Id>(dims[0]), 0));
}
// 3D data
else
{
vtkm::Id3 vdims;
vdims[0] = static_cast<vtkm::Id>(dims[0]);
vdims[1] = static_cast<vtkm::Id>(dims[1]);
vdims[2] = static_cast<vtkm::Id>(currBlockSize);
vtkm::Vec<ValueType, 3> origin(0, 0, (blockIndex * blockSize));
vtkm::Vec<ValueType, 3> spacing(1, 1, 1);
ds = dsb.Create(vdims, origin, spacing);
localBlockIndicesPortal.Set(localBlockIndex, vtkm::Id3(0, 0, blockIndex));
localBlockOriginsPortal.Set(localBlockIndex,
vtkm::Id3(0, 0, (blockStart / blockSliceSize)));
localBlockSizesPortal.Set(
localBlockIndex,
vtkm::Id3(static_cast<vtkm::Id>(dims[0]), static_cast<vtkm::Id>(dims[1]), currBlockSize));
}
std::vector<vtkm::Float32> subValues((values.begin() + blockStart),
(values.begin() + blockEnd));
vtkm::cont::DataSetFieldAdd dsf;
dsf.AddPointField(ds, "values", subValues);
inDataSet.AppendPartition(ds);
}
}
vtkm::cont::DataSetFieldAdd dsf;
dsf.AddPointField(inDataSet, "values", values);
#endif // WITH_MPI construct input dataset
currTime = totalTime.GetElapsedTime();
vtkm::Float64 buildDatasetTime = currTime - prevTime;
prevTime = currTime;
// Output data set is pairs of saddle and peak vertex IDs
vtkm::cont::DataSet result;
// Convert the mesh of values into contour tree, pairs of vertex ids
vtkm::filter::ContourTreePPP2 filter(useMarchingCubes, computeRegularStructure);
#ifdef WITH_MPI
filter.SetSpatialDecomposition(
blocksPerDim, globalSize, localBlockIndices, localBlockOrigins, localBlockSizes);
#endif
filter.SetActiveField("values");
result = filter.Execute(inDataSet); //, std::string("values"));
// Execute the contour tree analysis. NOTE: If MPI is used the result will be
// a vtkm::cont::PartitionedDataSet instead of a vtkm::cont::DataSet
auto result = filter.Execute(inDataSet);
currTime = totalTime.GetElapsedTime();
vtkm::Float64 computeContourTreeTime = currTime - prevTime;
prevTime = currTime;
#ifdef DEBUG_TIMING
std::cout << "-------------------------------------------------------------" << std::endl;
std::cout << "-------------------Contour Tree Timings----------------------" << std::endl;
// Get the timings from the contour tree computation
const std::vector<std::pair<std::string, vtkm::Float64>>& contourTreeTimings =
filter.GetTimings();
for (std::vector<std::pair<std::string, vtkm::Float64>>::size_type i = 0;
i < contourTreeTimings.size();
i++)
std::cout << std::setw(42) << std::left << contourTreeTimings[i].first << ": "
<< contourTreeTimings[i].second << " seconds" << std::endl;
#ifdef WITH_MPI
#ifdef DEBUG_PRINT
if (rank == 0)
{
std::cout << "----- rank=" << rank << " ----Final Contour Tree Data----------------------------"
<< std::endl;
filter.GetContourTree().PrintContent();
vtkm::worklet::contourtree_augmented::printIndices("Mesh Sort Order", filter.GetSortOrder());
}
#endif
#endif
#ifdef DEBUG_TIMING
if (rank == 0)
{
std::cout << "----------------------- " << rank << " --------------------------------------"
<< std::endl;
std::cout << "-------------------Contour Tree Timings----------------------" << std::endl;
// Get the timings from the contour tree computation
const std::vector<std::pair<std::string, vtkm::Float64>>& contourTreeTimings =
filter.GetTimings();
for (std::size_t i = 0; i < contourTreeTimings.size(); ++i)
std::cout << std::setw(42) << std::left << contourTreeTimings[i].first << ": "
<< contourTreeTimings[i].second << " seconds" << std::endl;
}
#endif
////////////////////////////////////////////
// Compute the branch decomposition
////////////////////////////////////////////
if (computeBranchDecomposition)
if (rank == 0 && computeBranchDecomposition && computeRegularStructure)
{
// TODO: Change timing to use logging in vtkm/cont/Logging.h
vtkm::cont::Timer branchDecompTimer;
branchDecompTimer.Start();
// compute the volume for each hyperarc and superarc
@ -343,7 +698,6 @@ int main(int argc, char* argv[])
hyperarcDependentWeight); // (output)
std::cout << std::setw(42) << std::left << "Compute Volume Weights"
<< ": " << branchDecompTimer.GetElapsedTime() << " seconds" << std::endl;
branchDecompTimer.Reset();
branchDecompTimer.Start();
// compute the branch decomposition by volume
@ -363,7 +717,86 @@ int main(int argc, char* argv[])
branchParent); // (output)
std::cout << std::setw(42) << std::left << "Compute Volume Branch Decomposition"
<< ": " << branchDecompTimer.GetElapsedTime() << " seconds" << std::endl;
//----main branch decompostion end
//----Isovalue seleciton start
if (numLevels > 0) // if compute isovalues
{
// Get the data values for computing the explicit branch decomposition
// TODO Can we cast the handle we get from GetData() instead of doing a CopyTo?
#ifdef WITH_MPI
vtkm::cont::ArrayHandle<ValueType> dataField;
result.GetPartitions()[0].GetField(0).GetData().CopyTo(dataField);
bool dataFieldIsSorted = true;
#else
vtkm::cont::ArrayHandle<ValueType> dataField;
inDataSet.GetField(0).GetData().CopyTo(dataField);
bool dataFieldIsSorted = false;
#endif
// create explicit representation of the branch decompostion from the array representation
BranchType* branchDecompostionRoot =
cppp2_ns::ProcessContourTree::ComputeBranchDecomposition<ValueType>(
filter.GetContourTree().superparents,
filter.GetContourTree().supernodes,
whichBranch,
branchMinimum,
branchMaximum,
branchSaddle,
branchParent,
filter.GetSortOrder(),
dataField,
dataFieldIsSorted);
#ifdef DEBUG_PRINT
branchDecompostionRoot->print(std::cout);
#endif
// Simplify the contour tree of the branch decompostion
branchDecompostionRoot->simplifyToSize(numComp, usePersistenceSorter);
// Compute the relevant iso-values
std::vector<ValueType> isoValues;
switch (contourSelectMethod)
{
default:
case 0:
{
branchDecompostionRoot->getRelevantValues(static_cast<int>(contourType), eps, isoValues);
}
break;
case 1:
{
vtkm::worklet::contourtree_augmented::process_contourtree_inc::PiecewiseLinearFunction<
ValueType>
plf;
branchDecompostionRoot->accumulateIntervals(static_cast<int>(contourType), eps, plf);
isoValues = plf.nLargest(static_cast<unsigned int>(numLevels));
}
break;
}
// Print the compute iso values
std::cout << std::endl;
std::cout << "Isovalue Suggestions" << std::endl;
std::cout << "====================" << std::endl;
std::sort(isoValues.begin(), isoValues.end());
std::cout << "Isovalues: ";
for (ValueType val : isoValues)
std::cout << val << " ";
std::cout << std::endl;
// Unique isovalues
std::vector<ValueType>::iterator it = std::unique(isoValues.begin(), isoValues.end());
isoValues.resize(static_cast<std::size_t>(std::distance(isoValues.begin(), it)));
std::cout << isoValues.size() << " Unique Isovalues: ";
for (ValueType val : isoValues)
std::cout << val << " ";
std::cout << std::endl;
std::cout << std::endl;
} //end if compute isovalue
}
currTime = totalTime.GetElapsedTime();
vtkm::Float64 computeBranchDecompTime = currTime - prevTime;
prevTime = currTime;
@ -372,8 +805,8 @@ int main(int argc, char* argv[])
//vtkm::cont::ArrayHandle<vtkm::Pair<vtkm::Id, vtkm::Id> > saddlePeak;
//resultField.GetData().CopyTo(saddlePeak);
// dump out contour tree for comparison
if (printContourTree)
// Dump out contour tree for comparison
if (rank == 0 && printContourTree)
{
std::cout << "Contour Tree" << std::endl;
std::cout << "============" << std::endl;
@ -384,7 +817,19 @@ int main(int argc, char* argv[])
}
#ifdef DEBUG_TIMING
std::cout << "-------------------------------------------------------------" << std::endl;
#ifdef WITH_MPI
// Force a simple round-robin on the ranks for the summary prints. Its not perfect for MPI but
// it works well enough to sort the summaries from the ranks for small-scale debugging.
if (rank > 0)
{
int temp;
MPI_Status status;
MPI_Recv(&temp, 1, MPI_INT, (rank - 1), 0, comm, &status);
}
#endif
std::cout << "---------------------------" << rank << "----------------------------------"
<< std::endl;
std::cout << "--------------------------Totals-----------------------------" << std::endl;
std::cout << std::setw(42) << std::left << "Start-up"
<< ": " << startUpTime << " seconds" << std::endl;
@ -401,14 +846,14 @@ int main(int argc, char* argv[])
}
currTime = totalTime.GetElapsedTime();
//vtkm::Float64 miscTime = currTime - startUpTime - dataReadTime - buildDatasetTime - computeContourTreeTime;
//if (computeBranchDecomposition) miscTime -= computeBranchDecompTime;
//if(computeBranchDecomposition) miscTime -= computeBranchDecompTime;
//std::cout<<std::setw(42)<<std::left<<"Misc. Times"<<": "<<miscTime<<" seconds"<<std::endl;
std::cout << std::setw(42) << std::left << "Total Time"
<< ": " << currTime << " seconds" << std::endl;
std::cout << "-------------------------------------------------------------" << std::endl;
std::cout << "----------------Contour Tree Array Sizes---------------------" << std::endl;
const vtkm::worklet::contourtree_augmented::ContourTree& ct = filter.GetContourTree();
const cppp2_ns::ContourTree& ct = filter.GetContourTree();
std::cout << std::setw(42) << std::left << "#Nodes"
<< ": " << ct.nodes.GetNumberOfValues() << std::endl;
std::cout << std::setw(42) << std::left << "#Arcs"
@ -427,8 +872,20 @@ int main(int argc, char* argv[])
<< ": " << ct.hypernodes.GetNumberOfValues() << std::endl;
std::cout << std::setw(42) << std::left << "#Hyperarcs"
<< ": " << ct.hyperarcs.GetNumberOfValues() << std::endl;
std::cout << std::flush;
#ifdef WITH_MPI
// Let the next rank know that it is time to print their summary.
if (rank < (size - 1))
{
int message = 1;
MPI_Send(&message, 1, MPI_INT, (rank + 1), 0, comm);
}
#endif
#endif // DEBUG_TIMING
return 0;
#ifdef WITH_MPI
MPI_Finalize();
#endif
return EXIT_SUCCESS;
}

@ -18,9 +18,8 @@ add_executable(CosmoHaloFinder CosmoHaloFinder.cxx)
target_link_libraries(CosmoCenterFinder PRIVATE vtkm_filter)
target_link_libraries(CosmoHaloFinder PRIVATE vtkm_filter)
vtkm_add_target_information(CosmoCenterFinder
vtkm_add_target_information(CosmoCenterFinder CosmoHaloFinder
DROP_UNUSED_SYMBOLS
MODIFY_CUDA_FLAGS
DEVICE_SOURCES CosmoCenterFinder.cxx)
vtkm_add_target_information(CosmoHaloFinder
MODIFY_CUDA_FLAGS
DEVICE_SOURCES CosmoHaloFinder.cxx)
DEVICE_SOURCES
CosmoCenterFinder.cxx CosmoHaloFinder.cxx)

@ -15,8 +15,8 @@ find_package(VTKm REQUIRED QUIET)
if(TARGET vtkm_rendering)
add_executable(Demo Demo.cxx)
target_link_libraries(Demo PRIVATE vtkm_rendering)
target_link_libraries(Demo PRIVATE vtkm_filter vtkm_rendering)
vtkm_add_target_information(Demo
MODIFY_CUDA_FLAGS
DROP_UNUSED_SYMBOLS MODIFY_CUDA_FLAGS
DEVICE_SOURCES Demo.cxx)
endif()

@ -21,6 +21,6 @@ if(TARGET OpenGL::GL AND
add_executable(GameOfLife GameOfLife.cxx LoadShaders.h)
target_link_libraries(GameOfLife PRIVATE vtkm_filter OpenGL::GL GLEW::GLEW GLUT::GLUT)
vtkm_add_target_information(GameOfLife
MODIFY_CUDA_FLAGS
DROP_UNUSED_SYMBOLS MODIFY_CUDA_FLAGS
DEVICE_SOURCES GameOfLife.cxx)
endif()

@ -17,5 +17,5 @@ add_executable(HelloWorklet HelloWorklet.cxx)
target_link_libraries(HelloWorklet PRIVATE vtkm_filter)
vtkm_add_target_information(HelloWorklet
MODIFY_CUDA_FLAGS
DROP_UNUSED_SYMBOLS MODIFY_CUDA_FLAGS
DEVICE_SOURCES HelloWorklet.cxx)

@ -16,6 +16,6 @@ if (VTKm_ENABLE_MPI)
add_executable(Histogram Histogram.cxx HistogramMPI.h HistogramMPI.hxx)
target_link_libraries(Histogram PRIVATE vtkm_filter)
vtkm_add_target_information(Histogram
MODIFY_CUDA_FLAGS
DROP_UNUSED_SYMBOLS MODIFY_CUDA_FLAGS
DEVICE_SOURCES Histogram.cxx)
endif()

@ -15,5 +15,5 @@ find_package(VTKm REQUIRED QUIET)
add_executable(Lagrangian lagrangian.cxx ABCfield.h)
target_link_libraries(Lagrangian PRIVATE vtkm_filter)
vtkm_add_target_information(Lagrangian
MODIFY_CUDA_FLAGS
DROP_UNUSED_SYMBOLS MODIFY_CUDA_FLAGS
DEVICE_SOURCES lagrangian.cxx)

@ -18,7 +18,7 @@ find_package(VTKm REQUIRED QUIET)
add_executable(ftle LagrangianStructures.cxx)
target_link_libraries(ftle PRIVATE vtkm_cont vtkm_worklet)
vtkm_add_target_information(ftle
MODIFY_CUDA_FLAGS
DROP_UNUSED_SYMBOLS MODIFY_CUDA_FLAGS
DEVICE_SOURCES LagrangianStructures.cxx)
if(TARGET vtkm::tbb)
target_compile_definitions(ftle PRIVATE BUILDING_TBB_VERSION)

@ -33,5 +33,5 @@ if(TARGET vtkm::tbb)
endif()
vtkm_add_target_information(MeshQuality
MODIFY_CUDA_FLAGS
DROP_UNUSED_SYMBOLS MODIFY_CUDA_FLAGS
DEVICE_SOURCES MeshQuality.cxx)

@ -29,5 +29,5 @@ set(srcs
add_executable(MultiBackend ${srcs} ${headers})
target_link_libraries(MultiBackend PRIVATE vtkm_filter Threads::Threads)
vtkm_add_target_information(MultiBackend
MODIFY_CUDA_FLAGS
DROP_UNUSED_SYMBOLS MODIFY_CUDA_FLAGS
DEVICE_SOURCES ${srcs})

@ -14,7 +14,7 @@ project(Oscillator CXX)
find_package(VTKm REQUIRED QUIET)
add_executable(Oscillator Oscillator.cxx)
target_link_libraries(Oscillator PRIVATE vtkm_filter)
target_link_libraries(Oscillator PRIVATE vtkm_source)
vtkm_add_target_information(Oscillator
MODIFY_CUDA_FLAGS
DROP_UNUSED_SYMBOLS MODIFY_CUDA_FLAGS
DEVICE_SOURCES Oscillator.cxx)

@ -22,7 +22,7 @@
#include <vtkm/cont/TryExecute.h>
#include <vtkm/filter/OscillatorSource.h>
#include <vtkm/source/Oscillator.h>
#if !defined(_WIN32) || defined(__CYGWIN__)
#include <unistd.h> /* unlink */
@ -58,7 +58,7 @@ static inline std::string& trim(std::string& s)
// ----------------------------------------------------------------------------
void read_oscillators(std::string filePath, vtkm::filter::OscillatorSource& filter)
void read_oscillators(std::string filePath, vtkm::source::Oscillator& source)
{
std::ifstream in(filePath);
if (!in)
@ -87,15 +87,15 @@ void read_oscillators(std::string filePath, vtkm::filter::OscillatorSource& filt
if (stype == "damped")
{
filter.AddDamped(x, y, z, r, omega0, zeta);
source.AddDamped(x, y, z, r, omega0, zeta);
}
else if (stype == "decaying")
{
filter.AddDecaying(x, y, z, r, omega0, zeta);
source.AddDecaying(x, y, z, r, omega0, zeta);
}
else if (stype == "periodic")
{
filter.AddPeriodic(x, y, z, r, omega0, zeta);
source.AddPeriodic(x, y, z, r, omega0, zeta);
}
}
}
@ -303,22 +303,19 @@ int main(int argc, char** argv)
std::cout << " - end: " << endTime << std::endl;
std::cout << "=======================================\n" << std::endl;
vtkm::cont::DataSetBuilderUniform builder;
vtkm::cont::DataSet dataset = builder.Create(vtkm::Id3(sizeX, sizeY, sizeZ));
vtkm::filter::OscillatorSource filter;
read_oscillators(oscillatorConfigFile, filter);
vtkm::source::Oscillator source(vtkm::Id3{ sizeX, sizeY, sizeZ });
read_oscillators(oscillatorConfigFile, source);
std::cout << "=========== start computation ============" << std::endl;
int count = 0;
while (currentTime < endTime)
{
filter.SetTime(currentTime);
vtkm::cont::DataSet rdata = filter.Execute(dataset);
source.SetTime(currentTime);
vtkm::cont::DataSet rdata = source.Execute();
if (generateOutput)
{
vtkm::cont::ArrayHandle<vtkm::Float64> tmp;
rdata.GetField("oscillation", vtkm::cont::Field::Association::POINTS).GetData().CopyTo(tmp);
rdata.GetField("scalars", vtkm::cont::Field::Association::POINTS).GetData().CopyTo(tmp);
double* values = tmp.GetStorage().GetArray();
writeData(outputDirectory, count++, sizeX, sizeY, sizeZ, values);
}

@ -16,7 +16,7 @@ find_package(VTKm REQUIRED QUIET)
add_executable(Particle_Advection ParticleAdvection.cxx)
target_link_libraries(Particle_Advection PRIVATE vtkm_filter)
vtkm_add_target_information(Particle_Advection
MODIFY_CUDA_FLAGS
DROP_UNUSED_SYMBOLS MODIFY_CUDA_FLAGS
DEVICE_SOURCES ParticleAdvection.cxx)
if(TARGET vtkm::tbb)
target_compile_definitions(Particle_Advection PRIVATE BUILDING_TBB_VERSION)

@ -13,8 +13,8 @@ project(PolyLineArchimedeanHelix CXX)
find_package(VTKm REQUIRED QUIET)
if (VTKm_ENABLE_RENDERING)
add_executable(PolyLineArchimedeanHelix PolyLineArchimedeanHelix.cxx)
if(TARGET vtkm::cuda)
set_source_files_properties(PolyLineArchimedeanHelix.cxx PROPERTIES LANGUAGE "CUDA")
endif()
target_link_libraries(PolyLineArchimedeanHelix PRIVATE vtkm_filter vtkm_cont vtkm_rendering)
vtkm_add_target_information(PolyLineArchimedeanHelix
DROP_UNUSED_SYMBOLS MODIFY_CUDA_FLAGS
DEVICE_SOURCES PolyLineArchimedeanHelix.cxx)
target_link_libraries(PolyLineArchimedeanHelix PRIVATE vtkm_filter vtkm_rendering)
endif()

@ -67,7 +67,10 @@ void TubeThatSpiral(vtkm::FloatDefault radius, vtkm::Id numLineSegments, vtkm::I
// This generates a new pointset, and new cell set.
vtkm::cont::ArrayHandle<vtkm::Vec3f> tubePoints;
vtkm::cont::CellSetSingleType<> tubeCells;
tubeWorklet.Run(ds.GetCoordinateSystem(), ds.GetCellSet(), tubePoints, tubeCells);
tubeWorklet.Run(ds.GetCoordinateSystem().GetData().Cast<vtkm::cont::ArrayHandle<vtkm::Vec3f>>(),
ds.GetCellSet(),
tubePoints,
tubeCells);
vtkm::cont::DataSet tubeDataset;
tubeDataset.AddCoordinateSystem(vtkm::cont::CoordinateSystem("coords", tubePoints));

@ -15,5 +15,5 @@ find_package(VTKm REQUIRED QUIET)
add_executable(RedistributePoints RedistributePoints.cxx RedistributePoints.h)
target_link_libraries(RedistributePoints PRIVATE vtkm_filter)
vtkm_add_target_information(RedistributePoints
MODIFY_CUDA_FLAGS
DROP_UNUSED_SYMBOLS MODIFY_CUDA_FLAGS
DEVICE_SOURCES RedistributePoints.cxx)

@ -17,6 +17,6 @@ find_package(VTKm REQUIRED QUIET)
add_executable(Temporal_Advection TemporalAdvection.cxx)
vtkm_add_target_information(Temporal_Advection
MODIFY_CUDA_FLAGS
DROP_UNUSED_SYMBOLS MODIFY_CUDA_FLAGS
DEVICE_SOURCES TemporalAdvection.cxx)
target_link_libraries(Temporal_Advection PRIVATE vtkm_filter)

@ -82,7 +82,7 @@ int main(int argc, char** argv)
pathlineFilter.SetNextDataSet(ds2);
// 2. The current and next times, these times will be used to interpolate
// the velocities for particle positions in space and time.
pathlineFilter.SetCurrentTime(time1);
pathlineFilter.SetPreviousTime(time1);
pathlineFilter.SetNextTime(time2);
// 3. Maximum number of steps the particle is allowed to take until termination.
pathlineFilter.SetNumberOfSteps(numSteps);

@ -16,13 +16,11 @@ find_package(VTKm REQUIRED QUIET)
add_executable(Tetrahedralize Tetrahedralize.cxx)
target_link_libraries(Tetrahedralize PRIVATE vtkm_filter)
vtkm_add_target_information(Tetrahedralize
MODIFY_CUDA_FLAGS
DEVICE_SOURCES Tetrahedralize.cxx)
add_executable(Triangulate Triangulate.cxx)
target_link_libraries(Triangulate PRIVATE vtkm_filter)
vtkm_add_target_information(Triangulate
vtkm_add_target_information(Tetrahedralize Triangulate
DROP_UNUSED_SYMBOLS
MODIFY_CUDA_FLAGS
DEVICE_SOURCES Triangulate.cxx)
DEVICE_SOURCES
Tetrahedralize.cxx Triangulate.cxx)

@ -101,3 +101,6 @@ add_subdirectory(interop)
#-----------------------------------------------------------------------------
#add the io folder
add_subdirectory(io)
#add the source folder
add_subdirectory(source)

@ -13,7 +13,7 @@
namespace vtkm
{
enum struct CellClassification
enum CellClassification : vtkm::UInt8
{
NORMAL = 0, //Valid cell
GHOST = 1 << 0, //Ghost cell

@ -46,6 +46,12 @@
* vtkm::cont::cuda includes the code to implement the VTK-m Control Environment
* for the CUDA-based device adapter.
*
* \namespace vtkm::cont::openmp
* \brief OPenMP implementation for Control Environment.
*
* vtkm::cont::openmp includes the code to implement the VTK-m Control Environment
* for the OpenMP-based device adapter.
*
* \namespace vtkm::cont::serial
* \brief Serial implementation for Control Environment.
*
@ -71,6 +77,12 @@
* vtkm::exec::cuda includes the code to implement the VTK-m Execution Environment
* for the CUDA-based device adapter.
*
* \namespace vtkm::exec::openmp
* \brief CUDA implementation for Execution Environment.
*
* vtkm::exec::openmp includes the code to implement the VTK-m Execution Environment
* for the OpenMP device adapter.
*
* \namespace vtkm::exec::serial
* \brief CUDA implementation for Execution Environment.
*
@ -104,7 +116,7 @@
* vtkm and OpenGL.
*
* \namespace vtkm::io
* \brief VTK-m IO
* \brief VTK-m File input and output classes
*
* vtkm::io defines API for basic reading of VTK files. Intended to be used for
* examples and testing.
@ -114,6 +126,11 @@
*
* vtkm::rendering defines API for
*
* \namespace vtkm::source
* \brief VTK-m Input source such as Wavelet
*
* vtkm::source is the collection of predefined sources that generate data.
*
* \namespace vtkm::testing
* \brief Internal testing classes
*

@ -183,6 +183,26 @@ struct VTKM_NEVER_EXPORT VecTraits<const T> : VecTraits<T>
{
};
#if defined(VTKM_GCC) && (__GNUC__ <= 5)
namespace detail
{
template <typename NewT, vtkm::IdComponent Size>
struct VecReplaceComponentTypeGCC4or5
{
using type = vtkm::Vec<NewT, Size>;
};
template <typename T, vtkm::IdComponent Size, typename NewT>
struct VecReplaceBaseComponentTypeGCC4or5
{
using type =
vtkm::Vec<typename vtkm::VecTraits<T>::template ReplaceBaseComponentType<NewT>, Size>;
};
} // namespace detail
#endif // GCC Version 4.8
template <typename T, vtkm::IdComponent Size>
struct VTKM_NEVER_EXPORT VecTraits<vtkm::Vec<T, Size>>
{
@ -247,26 +267,42 @@ struct VTKM_NEVER_EXPORT VecTraits<vtkm::Vec<T, Size>>
vector[component] = value;
}
/// \brief Get a vector of the same type but with a different component.
///
/// This type resolves to another vector with a different component type. For example,
/// vtkm::VecTraits<vtkm::Vec<T, N>>::ReplaceComponentType<T2> is vtkm::Vec<T2, N>.
/// This replacement is not recursive. So VecTraits<Vec<Vec<T, M>, N>::ReplaceComponentType<T2>
/// is vtkm::Vec<T2, N>.
///
/// \brief Get a vector of the same type but with a different component.
///
/// This type resolves to another vector with a different component type. For example,
/// vtkm::VecTraits<vtkm::Vec<T, N>>::ReplaceComponentType<T2> is vtkm::Vec<T2, N>.
/// This replacement is not recursive. So VecTraits<Vec<Vec<T, M>, N>::ReplaceComponentType<T2>
/// is vtkm::Vec<T2, N>.
///@{
#if defined(VTKM_GCC) && (__GNUC__ <= 5)
// Silly workaround for bug in GCC <= 5
template <typename NewComponentType>
using ReplaceComponentType =
typename detail::VecReplaceComponentTypeGCC4or5<NewComponentType, Size>::type;
#else // !GCC <= 5
template <typename NewComponentType>
using ReplaceComponentType = vtkm::Vec<NewComponentType, Size>;
#endif
///@}
/// \brief Get a vector of the same type but with a different base component.
///
/// This type resolves to another vector with a different base component type. The replacement
/// is recursive for nested types. For example,
/// VecTraits<Vec<Vec<T, M>, N>::ReplaceComponentType<T2> is Vec<Vec<T2, M>, N>.
///
/// \brief Get a vector of the same type but with a different base component.
///
/// This type resolves to another vector with a different base component type. The replacement
/// is recursive for nested types. For example,
/// VecTraits<Vec<Vec<T, M>, N>::ReplaceComponentType<T2> is Vec<Vec<T2, M>, N>.
///@{
#if defined(VTKM_GCC) && (__GNUC__ <= 5)
// Silly workaround for bug in GCC <= 5
template <typename NewComponentType>
using ReplaceBaseComponentType =
typename detail::VecReplaceBaseComponentTypeGCC4or5<T, Size, NewComponentType>::type;
#else // !GCC <= 5
template <typename NewComponentType>
using ReplaceBaseComponentType = vtkm::Vec<
typename vtkm::VecTraits<ComponentType>::template ReplaceBaseComponentType<NewComponentType>,
Size>;
#endif
///@}
/// Converts whatever type this vector is into the standard VTKm Tuple.
///

@ -123,8 +123,6 @@ struct CountSetBitsFunctor
struct FillFunctor
{
vtkm::Id PopCount{ 0 };
template <typename Device, typename... Args>
VTKM_CONT bool operator()(Device, Args&&... args)
{

@ -24,6 +24,8 @@
#include <vtkm/cont/Storage.h>
#include <vtkm/cont/StorageBasic.h>
#include <vtkm/internal/ArrayPortalHelpers.h>
#include <algorithm>
#include <iterator>
#include <memory>
@ -74,37 +76,16 @@ struct IsInValidArrayHandle
{
};
namespace detail
{
template <typename ArrayHandle>
struct IsWritableArrayHandleImpl
{
private:
template <typename U,
typename S = decltype(std::declval<U>().Set(vtkm::Id{},
std::declval<typename U::ValueType>()))>
static std::true_type hasSet(int);
template <typename U>
static std::false_type hasSet(...);
using PortalType = typename ArrayHandle::PortalControl;
public:
using type = decltype(hasSet<PortalType>(0));
static constexpr bool value = type::value;
};
}
/// Checks to see if the ArrayHandle allows
/// writing, as some ArrayHandles (Implicit) don't support writing.
/// This check is compatible with the C++11 type_traits.
/// It contains a typedef named type that is either
/// Checks to see if the ArrayHandle allows writing, as some ArrayHandles
/// (Implicit) don't support writing. These will be defined as either
/// std::true_type or std::false_type.
/// Both of these have a typedef named value with the respective boolean value.
///
/// \sa vtkm::internal::PortalSupportsSets
///
template <typename ArrayHandle>
using IsWritableArrayHandle = typename detail::IsWritableArrayHandleImpl<ArrayHandle>::type;
using IsWritableArrayHandle =
vtkm::internal::PortalSupportsSets<typename std::decay<ArrayHandle>::type::PortalControl>;
/// @}
/// Checks to see if the given object is an array handle. This check is
/// compatible with C++11 type_traits. It a typedef named \c type that is
@ -694,6 +675,7 @@ VTKM_NEVER_EXPORT VTKM_CONT inline void printSummary_ArrayHandle(
//=============================================================================
// Specializations of serialization related classes
/// @cond SERIALIZATION
namespace vtkm
{
namespace cont
@ -735,6 +717,7 @@ struct Serialization<vtkm::cont::ArrayHandle<T>>
};
} // diy
/// @endcond SERIALIZATION
#ifndef vtk_m_cont_ArrayHandle_hxx
#include <vtkm/cont/ArrayHandle.hxx>

@ -419,5 +419,6 @@ VTKM_CONT void Serialization<vtkm::cont::ArrayHandle<T>>::load(BinaryBuffer& bb,
}
}
} // diy
/// @endcond SERIALIZATION
#endif //vtk_m_cont_ArrayHandle_hxx

@ -37,6 +37,14 @@ public:
using PortalTypeSecond = PortalTypeSecond_;
using PortalTypeThird = PortalTypeThird_;
using set_supported_p1 = vtkm::internal::PortalSupportsSets<PortalTypeFirst>;
using set_supported_p2 = vtkm::internal::PortalSupportsSets<PortalTypeSecond>;
using set_supported_p3 = vtkm::internal::PortalSupportsSets<PortalTypeThird>;
using Writable = std::integral_constant<bool,
set_supported_p1::value && set_supported_p2::value &&
set_supported_p3::value>;
VTKM_SUPPRESS_EXEC_WARNINGS
VTKM_EXEC_CONT
ArrayPortalCartesianProduct()
@ -97,9 +105,11 @@ public:
this->PortalFirst.Get(i1), this->PortalSecond.Get(i2), this->PortalThird.Get(i3));
}
VTKM_SUPPRESS_EXEC_WARNINGS
VTKM_EXEC_CONT
void Set(vtkm::Id index, const ValueType& value) const
template <typename Writable_ = Writable,
typename = typename std::enable_if<Writable_::value>::type>
VTKM_EXEC_CONT void Set(vtkm::Id index, const ValueType& value) const
{
VTKM_ASSERT(index >= 0);
VTKM_ASSERT(index < this->GetNumberOfValues());
@ -422,6 +432,7 @@ VTKM_CONT
//=============================================================================
// Specializations of serialization related classes
/// @cond SERIALIZATION
namespace vtkm
{
namespace cont
@ -489,5 +500,6 @@ struct Serialization<
{
};
} // diy
/// @endcond SERIALIZATION
#endif //vtk_m_cont_ArrayHandleCartesianProduct_h

@ -154,6 +154,7 @@ VTKM_CONT
//=============================================================================
// Specializations of serialization related classes
/// @cond SERIALIZATION
namespace vtkm
{
@ -203,5 +204,6 @@ struct Serialization<vtkm::cont::ArrayHandleCast<T, AH>>
};
} // diy
/// @endcond SERIALIZATION
#endif // vtk_m_cont_ArrayHandleCast_h

@ -17,6 +17,8 @@
#include <vtkmtaotuple/include/Tuple.h>
#include <vtkm/internal/brigand.hpp>
#include <type_traits>
namespace vtkm
@ -373,11 +375,18 @@ struct ArraySizeValidator
}
};
template <typename PortalList>
using AllPortalsAreWritable =
typename brigand::all<PortalList,
brigand::bind<vtkm::internal::PortalSupportsSets, brigand::_1>>::type;
} // end namespace compvec
template <typename PortalTuple>
class VTKM_ALWAYS_EXPORT ArrayPortalCompositeVector
{
using Writable = compvec::AllPortalsAreWritable<PortalTuple>;
public:
using ValueType = typename compvec::GetValueType<PortalTuple>::ValueType;
@ -459,8 +468,9 @@ public:
return result;
}
VTKM_EXEC_CONT
void Set(vtkm::Id index, const ValueType& value) const
template <typename Writable_ = Writable,
typename = typename std::enable_if<Writable_::value>::type>
VTKM_EXEC_CONT void Set(vtkm::Id index, const ValueType& value) const
{
SetImpl<0, PortalTuple>::Exec(this->Portals, value, index);
}
@ -532,21 +542,21 @@ public:
void Allocate(vtkm::Id numValues)
{
VTKM_ASSERT(this->Valid);
return ForEachArray::Allocate(this->Arrays, numValues);
ForEachArray::Allocate(this->Arrays, numValues);
}
VTKM_CONT
void Shrink(vtkm::Id numValues)
{
VTKM_ASSERT(this->Valid);
return ForEachArray::Shrink(this->Arrays, numValues);
ForEachArray::Shrink(this->Arrays, numValues);
}
VTKM_CONT
void ReleaseResources()
{
VTKM_ASSERT(this->Valid);
return ForEachArray::ReleaseResources(this->Arrays);
ForEachArray::ReleaseResources(this->Arrays);
}
VTKM_CONT
@ -715,7 +725,7 @@ VTKM_CONT ArrayHandleCompositeVector<ArrayTs...> make_ArrayHandleCompositeVector
//=============================================================================
// Specializations of serialization related classes
/// @cond SERIALIZATION
namespace vtkm
{
namespace cont
@ -829,5 +839,6 @@ struct Serialization<vtkm::cont::ArrayHandle<
{
};
} // diy
/// @endcond SERIALIZATION
#endif //vtk_m_ArrayHandleCompositeVector_h

@ -22,6 +22,10 @@ namespace internal
template <typename PortalType1, typename PortalType2>
class VTKM_ALWAYS_EXPORT ArrayPortalConcatenate
{
using WritableP1 = vtkm::internal::PortalSupportsSets<PortalType1>;
using WritableP2 = vtkm::internal::PortalSupportsSets<PortalType2>;
using Writable = std::integral_constant<bool, WritableP1::value && WritableP2::value>;
public:
using ValueType = typename PortalType1::ValueType;
@ -58,18 +62,27 @@ public:
ValueType Get(vtkm::Id index) const
{
if (index < this->portal1.GetNumberOfValues())
{
return this->portal1.Get(index);
}
else
{
return this->portal2.Get(index - this->portal1.GetNumberOfValues());
}
}
VTKM_EXEC_CONT
void Set(vtkm::Id index, const ValueType& value) const
template <typename Writable_ = Writable,
typename = typename std::enable_if<Writable_::value>::type>
VTKM_EXEC_CONT void Set(vtkm::Id index, const ValueType& value) const
{
if (index < this->portal1.GetNumberOfValues())
{
this->portal1.Set(index, value);
}
else
{
this->portal2.Set(index - this->portal1.GetNumberOfValues(), value);
}
}
VTKM_EXEC_CONT
@ -314,6 +327,7 @@ VTKM_CONT ArrayHandleConcatenate<ArrayHandleType1, ArrayHandleType2> make_ArrayH
//=============================================================================
// Specializations of serialization related classes
/// @cond SERIALIZATION
namespace vtkm
{
namespace cont
@ -376,5 +390,6 @@ struct Serialization<
{
};
} // diy
/// @endcond SERIALIZATION
#endif //vtk_m_cont_ArrayHandleConcatenate_h

@ -75,6 +75,7 @@ vtkm::cont::ArrayHandleConstant<T> make_ArrayHandleConstant(T value, vtkm::Id nu
//=============================================================================
// Specializations of serialization related classes
/// @cond SERIALIZATION
namespace vtkm
{
namespace cont
@ -108,5 +109,6 @@ struct Serialization<vtkm::cont::ArrayHandleConstant<T>>
};
} // diy
/// @endcond SERIALIZATION
#endif //vtk_m_cont_ArrayHandleConstant_h

@ -81,12 +81,6 @@ public:
return ValueType(this->Start + this->Step * ValueType(static_cast<ComponentType>(index)));
}
VTKM_EXEC_CONT
void Set(vtkm::Id vtkmNotUsed(index), const ValueType& vtkmNotUsed(value)) const
{
VTKM_ASSERT(false && "Cannot write to read-only counting array.");
}
private:
ValueType Start;
ValueType Step;
@ -95,11 +89,10 @@ private:
/// A convenience class that provides a typedef to the appropriate tag for
/// a counting storage.
template <typename ConstantValueType>
template <typename ValueType>
struct ArrayHandleCountingTraits
{
using Tag =
vtkm::cont::StorageTagImplicit<vtkm::cont::internal::ArrayPortalCounting<ConstantValueType>>;
using Tag = vtkm::cont::StorageTagImplicit<vtkm::cont::internal::ArrayPortalCounting<ValueType>>;
};
} // namespace internal
@ -140,6 +133,7 @@ make_ArrayHandleCounting(CountingValueType start, CountingValueType step, vtkm::
//=============================================================================
// Specializations of serialization related classes
/// @cond SERIALIZATION
namespace vtkm
{
namespace cont
@ -203,5 +197,6 @@ struct Serialization<
{
};
} // diy
/// @endcond SERIALIZATION
#endif //vtk_m_cont_ArrayHandleCounting_h

@ -0,0 +1,890 @@
//============================================================================
// Copyright (c) Kitware, Inc.
// All rights reserved.
// See LICENSE.txt for details.
//
// This software is distributed WITHOUT ANY WARRANTY; without even
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the above copyright notice for more information.
//============================================================================
#ifndef vtk_m_ArrayHandleDecorator_h
#define vtk_m_ArrayHandleDecorator_h
#include <vtkm/cont/ArrayHandle.h>
#include <vtkm/cont/Storage.h>
#include <vtkm/StaticAssert.h>
#include <vtkm/VecTraits.h>
#include <vtkm/internal/ArrayPortalHelpers.h>
#include <vtkm/internal/brigand.hpp>
#include <vtkmtaotuple/include/Tuple.h>
#include <vtkmtaotuple/include/tao/seq/make_integer_sequence.hpp>
#include <type_traits>
#include <utility>
namespace vtkm
{
namespace cont
{
namespace internal
{
namespace decor
{
// Generic InverseFunctor implementation that does nothing.
struct NoOpInverseFunctor
{
NoOpInverseFunctor() = default;
template <typename... Ts>
VTKM_EXEC_CONT NoOpInverseFunctor(Ts...)
{
}
template <typename VT>
VTKM_EXEC_CONT void operator()(vtkm::Id, VT) const
{
}
};
} // namespace decor
// The portal for ArrayHandleDecorator. Get calls FunctorType::operator(), and
// Set calls InverseFunctorType::operator(), but only if the DecoratorImpl
// provides an inverse.
template <typename ValueType_, typename FunctorType_, typename InverseFunctorType_>
class VTKM_ALWAYS_EXPORT ArrayPortalDecorator
{
public:
using ValueType = ValueType_;
using FunctorType = FunctorType_;
using InverseFunctorType = InverseFunctorType_;
using ReadOnly = std::is_same<InverseFunctorType, decor::NoOpInverseFunctor>;
VTKM_EXEC_CONT
ArrayPortalDecorator() {}
VTKM_CONT
ArrayPortalDecorator(FunctorType func, InverseFunctorType iFunc, vtkm::Id numValues)
: Functor(func)
, InverseFunctor(iFunc)
, NumberOfValues(numValues)
{
}
VTKM_EXEC_CONT
vtkm::Id GetNumberOfValues() const { return this->NumberOfValues; }
VTKM_EXEC_CONT
ValueType Get(vtkm::Id index) const { return this->Functor(index); }
template <typename ReadOnly_ = ReadOnly,
typename = typename std::enable_if<!ReadOnly_::value>::type>
VTKM_EXEC_CONT void Set(vtkm::Id index, const ValueType& value) const
{
this->InverseFunctor(index, value);
}
private:
FunctorType Functor;
InverseFunctorType InverseFunctor;
vtkm::Id NumberOfValues;
};
namespace decor
{
// Ensures that all types in variadic container ArrayHandleList are subclasses
// of ArrayHandleBase.
template <typename ArrayHandleList>
using AllAreArrayHandles =
brigand::all<ArrayHandleList, std::is_base_of<ArrayHandleBase, brigand::_1>>;
namespace detail
{
// Tests whether DecoratorImplT has a CreateInverseFunctor(Portals...) method.
template <typename DecoratorImplT, typename PortalList>
struct IsFunctorInvertibleImpl;
template <typename DecoratorImplT, template <typename...> class List, typename... PortalTs>
struct IsFunctorInvertibleImpl<DecoratorImplT, List<PortalTs...>>
{
private:
using PortalList = brigand::list<typename std::decay<PortalTs>::type...>;
template <
typename T,
typename U = decltype(std::declval<T>().CreateInverseFunctor(std::declval<PortalTs>()...))>
static std::true_type InverseExistsTest(int);
template <typename T>
static std::false_type InverseExistsTest(...);
public:
using type = decltype(InverseExistsTest<DecoratorImplT>(0));
};
// Deduces the type returned by DecoratorImplT::CreateFunctor when given
// the specified portals.
template <typename DecoratorImplT, typename PortalList>
struct GetFunctorTypeImpl;
template <typename DecoratorImplT, template <typename...> class List, typename... PortalTs>
struct GetFunctorTypeImpl<DecoratorImplT, List<PortalTs...>>
{
using type = decltype(std::declval<DecoratorImplT>().CreateFunctor(std::declval<PortalTs>()...));
};
// Deduces the type returned by DecoratorImplT::CreateInverseFunctor when given
// the specified portals. If DecoratorImplT doesn't have a CreateInverseFunctor
// method, a NoOp functor will be used instead.
template <typename CanWrite, typename DecoratorImplT, typename PortalList>
struct GetInverseFunctorTypeImpl;
template <typename DecoratorImplT, template <typename...> class List, typename... PortalTs>
struct GetInverseFunctorTypeImpl<std::true_type, DecoratorImplT, List<PortalTs...>>
{
using type =
decltype(std::declval<DecoratorImplT>().CreateInverseFunctor(std::declval<PortalTs>()...));
};
template <typename DecoratorImplT, typename PortalList>
struct GetInverseFunctorTypeImpl<std::false_type, DecoratorImplT, PortalList>
{
using type = NoOpInverseFunctor;
};
// Get appropriate portals from a source array.
// See note below about using non-writable portals in invertible functors.
// We need to sub in const portals when writable ones don't exist.
template <typename ArrayT>
typename std::decay<ArrayT>::type::PortalControl GetPortalControlImpl(std::true_type,
ArrayT&& array)
{
return array.GetPortalControl();
}
template <typename ArrayT>
typename std::decay<ArrayT>::type::PortalConstControl GetPortalControlImpl(std::false_type,
ArrayT&& array)
{
return array.GetPortalConstControl();
}
template <typename ArrayT, typename Device>
typename std::decay<ArrayT>::type::template ExecutionTypes<Device>::Portal
GetPortalInPlaceImpl(std::true_type, ArrayT&& array, Device)
{
return array.PrepareForInPlace(Device{});
}
template <typename ArrayT, typename Device>
typename std::decay<ArrayT>::type::template ExecutionTypes<Device>::PortalConst
GetPortalInPlaceImpl(std::false_type, ArrayT&& array, Device)
{
// ArrayT is read-only -- prepare for input instead.
return array.PrepareForInput(Device{});
}
template <typename ArrayT, typename Device>
typename std::decay<ArrayT>::type::template ExecutionTypes<Device>::Portal
GetPortalOutputImpl(std::true_type, ArrayT&& array, Device)
{
// Prepare these for inplace usage instead -- we'll likely need to read
// from these in addition to writing.
return array.PrepareForInPlace(Device{});
}
template <typename ArrayT, typename Device>
typename std::decay<ArrayT>::type::template ExecutionTypes<Device>::PortalConst
GetPortalOutputImpl(std::false_type, ArrayT&& array, Device)
{
// ArrayT is read-only -- prepare for input instead.
return array.PrepareForInput(Device{});
}
} // namespace detail
// Get portal types:
// We allow writing to an AHDecorator if *any* of the ArrayHandles are writable.
// This means we have to avoid calling PrepareForOutput, etc on non-writable
// array handles, since these may throw. On non-writable handles, use the
// const array handles so we can at least read from them in the inverse
// functors.
template <typename ArrayT,
typename Portal = typename std::decay<ArrayT>::type::PortalControl,
typename PortalConst = typename std::decay<ArrayT>::type::PortalConstControl>
using GetPortalControlType =
typename brigand::if_<vtkm::internal::PortalSupportsSets<Portal>, Portal, PortalConst>::type;
template <typename ArrayT>
using GetPortalConstControlType = typename std::decay<ArrayT>::type::PortalConstControl;
template <typename ArrayT,
typename Device,
typename Portal =
typename std::decay<ArrayT>::type::template ExecutionTypes<Device>::Portal,
typename PortalConst =
typename std::decay<ArrayT>::type::template ExecutionTypes<Device>::PortalConst>
using GetPortalExecutionType =
typename brigand::if_<vtkm::internal::PortalSupportsSets<Portal>, Portal, PortalConst>::type;
template <typename ArrayT, typename Device>
using GetPortalConstExecutionType =
typename std::decay<ArrayT>::type::template ExecutionTypes<Device>::PortalConst;
// Get portal objects:
// See note above -- we swap in const portals sometimes.
template <typename ArrayT>
GetPortalControlType<typename std::decay<ArrayT>::type> GetPortalControl(ArrayT&& array)
{
return detail::GetPortalControlImpl(IsWritableArrayHandle<ArrayT>{}, std::forward<ArrayT>(array));
}
template <typename ArrayT>
GetPortalConstControlType<typename std::decay<ArrayT>::type> GetPortalConstControl(
const ArrayT& array)
{
return array.GetPortalConstControl();
}
template <typename ArrayT, typename Device>
GetPortalConstExecutionType<typename std::decay<ArrayT>::type, Device> GetPortalInput(
const ArrayT& array,
Device)
{
return array.PrepareForInput(Device{});
}
template <typename ArrayT, typename Device>
GetPortalExecutionType<typename std::decay<ArrayT>::type, Device> GetPortalInPlace(ArrayT&& array,
Device)
{
return detail::GetPortalInPlaceImpl(
IsWritableArrayHandle<ArrayT>{}, std::forward<ArrayT>(array), Device{});
}
template <typename ArrayT, typename Device>
GetPortalExecutionType<typename std::decay<ArrayT>::type, Device> GetPortalOutput(ArrayT&& array,
Device)
{
return detail::GetPortalOutputImpl(
IsWritableArrayHandle<ArrayT>{}, std::forward<ArrayT>(array), Device{});
}
// Equivalent to std::true_type if *any* portal in PortalList can be written to.
// If all are read-only, std::false_type is used instead.
template <typename PortalList>
using AnyPortalIsWritable =
typename brigand::any<PortalList,
brigand::bind<vtkm::internal::PortalSupportsSets, brigand::_1>>::type;
// Set to std::true_type if DecoratorImplT::CreateInverseFunctor can be called
// with the supplied portals, or std::false_type otherwise.
template <typename DecoratorImplT, typename PortalList>
using IsFunctorInvertible =
typename detail::IsFunctorInvertibleImpl<DecoratorImplT, PortalList>::type;
// std::true_type/std::false_type depending on whether the decorator impl has a
// CreateInversePortal method AND any of the arrays are writable.
template <typename DecoratorImplT, typename PortalList>
using CanWriteToFunctor = typename brigand::and_<IsFunctorInvertible<DecoratorImplT, PortalList>,
AnyPortalIsWritable<PortalList>>::type;
// The FunctorType for the provided implementation and portal types.
template <typename DecoratorImplT, typename PortalList>
using GetFunctorType = typename detail::GetFunctorTypeImpl<DecoratorImplT, PortalList>::type;
// The InverseFunctorType for the provided implementation and portal types.
// Will detect when inversion is not possible and return a NoOp functor instead.
template <typename DecoratorImplT, typename PortalList>
using GetInverseFunctorType =
typename detail::GetInverseFunctorTypeImpl<CanWriteToFunctor<DecoratorImplT, PortalList>,
DecoratorImplT,
PortalList>::type;
// Convert a sequence of array handle types to a list of portals:
// Some notes on this implementation:
// - MSVC 2015 ICEs when using brigand::transform to convert a brigand::list
// of arrayhandles to portals. So instead we pass the ArrayTs.
// - Just using brigand::list<GetPortalControlType<ArrayTs>...> fails, as
// apparently that is an improper parameter pack expansion
// - So we jump through some decltype/declval hoops here to get this to work:
template <typename... ArrayTs>
using GetPortalConstControlList =
brigand::list<decltype((GetPortalConstControl(std::declval<ArrayTs>())))...>;
template <typename Device, typename... ArrayTs>
using GetPortalConstExecutionList =
brigand::list<decltype((GetPortalInput(std::declval<ArrayTs>(), Device{})))...>;
template <typename... ArrayTs>
using GetPortalControlList =
brigand::list<decltype((GetPortalControl(std::declval<ArrayTs>())))...>;
template <typename Device, typename... ArrayTs>
using GetPortalExecutionList =
brigand::list<decltype((GetPortalInPlace(std::declval<ArrayTs>(), Device{})))...>;
template <typename DecoratorImplT, typename... ArrayTs>
struct DecoratorStorageTraits
{
using ArrayList = brigand::list<ArrayTs...>;
VTKM_STATIC_ASSERT_MSG(sizeof...(ArrayTs) > 0,
"Must specify at least one source array handle for "
"ArrayHandleDecorator. Consider using "
"ArrayHandleImplicit instead.");
// Need to check this here, since this traits struct is used in the
// ArrayHandleDecorator superclass definition before any other
// static_asserts could be used.
VTKM_STATIC_ASSERT_MSG(decor::AllAreArrayHandles<ArrayList>::value,
"Trailing template parameters for "
"ArrayHandleDecorator must be a list of ArrayHandle "
"types.");
using ArrayTupleType = vtkmstd::tuple<ArrayTs...>;
// size_t integral constants that index ArrayTs:
#if defined(VTKM_MSVC) && (_MSC_VER < 1920) //Less than MSCV2019
using IndexList = brigand::make_sequence<brigand::size_t<0>, sizeof...(ArrayTs)>;
#else
using IndexList = tao::seq::make_index_sequence<sizeof...(ArrayTs)>;
#endif
// Portal lists:
// NOTE we have to pass the parameter pack here instead of using ArrayList
// with brigand::transform, since that's causing MSVC 2015 to ice:
using PortalControlList = GetPortalControlList<ArrayTs...>;
using PortalConstControlList = GetPortalConstControlList<ArrayTs...>;
template <typename Device>
using PortalExecutionList = GetPortalExecutionList<Device, ArrayTs...>;
template <typename Device>
using PortalConstExecutionList = GetPortalConstExecutionList<Device, ArrayTs...>;
// Functors:
using FunctorControlType = GetFunctorType<DecoratorImplT, PortalControlList>;
using FunctorConstControlType = GetFunctorType<DecoratorImplT, PortalConstControlList>;
template <typename Device>
using FunctorExecutionType = GetFunctorType<DecoratorImplT, PortalExecutionList<Device>>;
template <typename Device>
using FunctorConstExecutionType =
GetFunctorType<DecoratorImplT, PortalConstExecutionList<Device>>;
// Inverse functors:
using InverseFunctorControlType = GetInverseFunctorType<DecoratorImplT, PortalControlList>;
using InverseFunctorConstControlType = NoOpInverseFunctor;
template <typename Device>
using InverseFunctorExecutionType =
GetInverseFunctorType<DecoratorImplT, PortalExecutionList<Device>>;
template <typename Device>
using InverseFunctorConstExecutionType = NoOpInverseFunctor;
// Misc:
// ValueType is derived from DecoratorImplT::CreateFunctor(...)'s operator().
using ValueType = decltype(std::declval<FunctorControlType>()(0));
// Decorator portals:
using PortalControlType =
ArrayPortalDecorator<ValueType, FunctorControlType, InverseFunctorControlType>;
using PortalConstControlType =
ArrayPortalDecorator<ValueType, FunctorConstControlType, InverseFunctorConstControlType>;
template <typename Device>
using PortalExecutionType = ArrayPortalDecorator<ValueType,
FunctorExecutionType<Device>,
InverseFunctorExecutionType<Device>>;
template <typename Device>
using PortalConstExecutionType = ArrayPortalDecorator<ValueType,
FunctorConstExecutionType<Device>,
InverseFunctorConstExecutionType<Device>>;
// helper for constructing portals with the appropriate functors. This is
// where we decide whether or not to call `CreateInverseFunctor` on the
// implementation class.
// Do not use these directly, they are helpers for the MakePortal[...]
// methods below.
template <typename DecoratorPortalType, typename... PortalTs>
VTKM_CONT static
typename std::enable_if<DecoratorPortalType::ReadOnly::value, DecoratorPortalType>::type
CreatePortalDecorator(vtkm::Id numVals, const DecoratorImplT& impl, PortalTs&&... portals)
{ // Portal is read only:
return { impl.CreateFunctor(std::forward<PortalTs>(portals)...),
typename DecoratorPortalType::InverseFunctorType{},
numVals };
}
template <typename DecoratorPortalType, typename... PortalTs>
VTKM_CONT static
typename std::enable_if<!DecoratorPortalType::ReadOnly::value, DecoratorPortalType>::type
CreatePortalDecorator(vtkm::Id numVals, const DecoratorImplT& impl, PortalTs... portals)
{ // Portal is read/write:
return { impl.CreateFunctor(portals...), impl.CreateInverseFunctor(portals...), numVals };
}
#if defined(VTKM_MSVC) && (_MSC_VER < 1920) //Less than MSCV2019
// Portal construction methods. These actually create portals.
template <template <typename...> class List, typename... Indices>
VTKM_CONT static PortalControlType MakePortalControl(const DecoratorImplT& impl,
ArrayTupleType& arrays,
vtkm::Id numValues,
List<Indices...>)
{
return CreatePortalDecorator<PortalControlType>(
numValues,
impl,
// More MSVC ICE avoidance while expanding the Indices parameter pack,
// which is a list of std::integral_constant<size_t, ...>:
//
// Indices::value : Works everywhere but MSVC2017, which crashes on it.
// Indices{} : Works on MSVC2017, but won't compile on MSVC2015.
// Indices{}.value : Works on both MSVC2015 and MSVC2017.
//
// Don't touch the following line unless you really, really have to.
GetPortalControl(vtkmstd::get<Indices{}.value>(arrays))...);
}
template <template <typename...> class List, typename... Indices>
VTKM_CONT static PortalConstControlType MakePortalConstControl(const DecoratorImplT& impl,
const ArrayTupleType& arrays,
vtkm::Id numValues,
List<Indices...>)
{
return CreatePortalDecorator<PortalConstControlType>(
numValues,
impl,
// Don't touch the following line unless you really, really have to. See
// note in MakePortalControl.
GetPortalConstControl(vtkmstd::get<Indices{}.value>(arrays))...);
}
template <template <typename...> class List, typename... Indices, typename Device>
VTKM_CONT static PortalConstExecutionType<Device> MakePortalInput(const DecoratorImplT& impl,
const ArrayTupleType& arrays,
vtkm::Id numValues,
List<Indices...>,
Device dev)
{
return CreatePortalDecorator<PortalConstExecutionType<Device>>(
numValues,
impl,
// Don't touch the following line unless you really, really have to. See
// note in MakePortalControl.
GetPortalInput(vtkmstd::get<Indices{}.value>(arrays), dev)...);
}
template <template <typename...> class List, typename... Indices, typename Device>
VTKM_CONT static PortalExecutionType<Device> MakePortalInPlace(const DecoratorImplT& impl,
ArrayTupleType& arrays,
vtkm::Id numValues,
List<Indices...>,
Device dev)
{
return CreatePortalDecorator<PortalExecutionType<Device>>(
numValues,
impl,
// Don't touch the following line unless you really, really have to. See
// note in MakePortalControl.
GetPortalInPlace(vtkmstd::get<Indices{}.value>(arrays), dev)...);
}
template <template <typename...> class List, typename... Indices, typename Device>
VTKM_CONT static PortalExecutionType<Device> MakePortalOutput(const DecoratorImplT& impl,
ArrayTupleType& arrays,
vtkm::Id numValues,
List<Indices...>,
Device dev)
{
return CreatePortalDecorator<PortalExecutionType<Device>>(
numValues,
impl,
// Don't touch the following line unless you really, really have to. See
// note in MakePortalControl.
GetPortalOutput(vtkmstd::get<Indices{}.value>(arrays), dev)...);
}
#else
// Portal construction methods. These actually create portals.
template <template <typename, std::size_t...> class List, std::size_t... Indices>
VTKM_CONT static PortalControlType MakePortalControl(const DecoratorImplT& impl,
ArrayTupleType& arrays,
vtkm::Id numValues,
List<std::size_t, Indices...>)
{
return CreatePortalDecorator<PortalControlType>(
numValues, impl, GetPortalControl(vtkmstd::get<Indices>(arrays))...);
}
template <template <typename, std::size_t...> class List, std::size_t... Indices>
VTKM_CONT static PortalConstControlType MakePortalConstControl(const DecoratorImplT& impl,
const ArrayTupleType& arrays,
vtkm::Id numValues,
List<std::size_t, Indices...>)
{
return CreatePortalDecorator<PortalConstControlType>(
numValues, impl, GetPortalConstControl(vtkmstd::get<Indices>(arrays))...);
}
template <template <typename, std::size_t...> class List, std::size_t... Indices, typename Device>
VTKM_CONT static PortalConstExecutionType<Device> MakePortalInput(const DecoratorImplT& impl,
const ArrayTupleType& arrays,
vtkm::Id numValues,
List<std::size_t, Indices...>,
Device dev)
{
return CreatePortalDecorator<PortalConstExecutionType<Device>>(
numValues, impl, GetPortalInput(vtkmstd::get<Indices>(arrays), dev)...);
}
template <template <typename, std::size_t...> class List, std::size_t... Indices, typename Device>
VTKM_CONT static PortalExecutionType<Device> MakePortalInPlace(const DecoratorImplT& impl,
ArrayTupleType& arrays,
vtkm::Id numValues,
List<std::size_t, Indices...>,
Device dev)
{
return CreatePortalDecorator<PortalExecutionType<Device>>(
numValues, impl, GetPortalInPlace(vtkmstd::get<Indices>(arrays), dev)...);
}
template <template <typename, std::size_t...> class List, std::size_t... Indices, typename Device>
VTKM_CONT static PortalExecutionType<Device> MakePortalOutput(const DecoratorImplT& impl,
ArrayTupleType& arrays,
vtkm::Id numValues,
List<std::size_t, Indices...>,
Device dev)
{
return CreatePortalDecorator<PortalExecutionType<Device>>(
numValues, impl, GetPortalOutput(vtkmstd::get<Indices>(arrays), dev)...);
}
#endif
};
} // end namespace decor
template <typename DecoratorImplT, typename... ArrayTs>
struct VTKM_ALWAYS_EXPORT StorageTagDecorator
{
};
template <typename DecoratorImplT, typename... ArrayTs>
class Storage<typename decor::DecoratorStorageTraits<DecoratorImplT, ArrayTs...>::ValueType,
StorageTagDecorator<DecoratorImplT, ArrayTs...>>
{
using Traits = decor::DecoratorStorageTraits<DecoratorImplT, ArrayTs...>;
using IndexList = typename Traits::IndexList;
public:
using ArrayTupleType = typename Traits::ArrayTupleType;
using ValueType = typename Traits::ValueType;
using PortalType = typename Traits::PortalControlType;
using PortalConstType = typename Traits::PortalConstControlType;
VTKM_CONT
Storage()
: Valid{ false }
{
}
VTKM_CONT
Storage(const DecoratorImplT& impl, const ArrayTupleType& arrayTuple, vtkm::Id numValues)
: Implementation(impl)
, ArrayTuple{ arrayTuple }
, NumberOfValues(numValues)
, Valid{ true }
{
}
VTKM_CONT
PortalType GetPortal()
{
VTKM_ASSERT(this->Valid);
return Traits::MakePortalControl(
this->Implementation, this->ArrayTuple, this->NumberOfValues, IndexList{});
}
VTKM_CONT
PortalConstType GetPortalConst() const
{
VTKM_ASSERT(this->Valid);
return Traits::MakePortalConstControl(
this->Implementation, this->ArrayTuple, this->NumberOfValues, IndexList{});
}
VTKM_CONT
vtkm::Id GetNumberOfValues() const
{
VTKM_ASSERT(this->Valid);
return this->NumberOfValues;
}
VTKM_CONT
void Allocate(vtkm::Id)
{
VTKM_ASSERT(this->Valid);
// No-op. I suppose eventually we could pass numValues down to the
// implementation class and let it do something intelligent.
}
VTKM_CONT
void Shrink(vtkm::Id)
{
VTKM_ASSERT(this->Valid);
// No-op. Again, could eventually be passed down to the implementation.
}
VTKM_CONT
void ReleaseResources()
{
VTKM_ASSERT(this->Valid);
// No-op. Again, could eventually be passed down to the implementation.
}
VTKM_CONT
const ArrayTupleType& GetArrayTuple() const
{
VTKM_ASSERT(this->Valid);
return this->ArrayTuple;
}
VTKM_CONT
ArrayTupleType& GetArrayTuple()
{
VTKM_ASSERT(this->Valid);
return this->ArrayTuple;
}
VTKM_CONT
const DecoratorImplT& GetImplementation() const
{
VTKM_ASSERT(this->Valid);
return this->Implementation;
}
VTKM_CONT
DecoratorImplT& GetImplementation()
{
VTKM_ASSERT(this->Valid);
return this->Implementation;
}
private:
DecoratorImplT Implementation;
ArrayTupleType ArrayTuple;
vtkm::Id NumberOfValues;
bool Valid;
};
template <typename DecoratorImplT, typename... ArrayTs>
struct DecoratorHandleTraits
{
using StorageTraits = decor::DecoratorStorageTraits<DecoratorImplT, ArrayTs...>;
using ValueType = typename StorageTraits::ValueType;
using StorageTag = StorageTagDecorator<DecoratorImplT, ArrayTs...>;
using StorageType = vtkm::cont::internal::Storage<ValueType, StorageTag>;
using Superclass = vtkm::cont::ArrayHandle<ValueType, StorageTag>;
};
template <typename DecoratorImplT, typename... ArrayTs, typename Device>
class ArrayTransfer<typename decor::DecoratorStorageTraits<DecoratorImplT, ArrayTs...>::ValueType,
StorageTagDecorator<DecoratorImplT, ArrayTs...>,
Device>
{
VTKM_IS_DEVICE_ADAPTER_TAG(Device);
using HandleTraits = DecoratorHandleTraits<DecoratorImplT, ArrayTs...>;
using Traits = typename HandleTraits::StorageTraits;
using IndexList = typename Traits::IndexList;
using StorageType = typename HandleTraits::StorageType;
public:
using ValueType = typename Traits::ValueType;
using PortalControl = typename Traits::PortalControlType;
using PortalConstControl = typename Traits::PortalConstControlType;
using PortalExecution = typename Traits::template PortalExecutionType<Device>;
using PortalConstExecution = typename Traits::template PortalConstExecutionType<Device>;
VTKM_CONT
ArrayTransfer(StorageType* storage)
: Storage(storage)
{
}
VTKM_CONT
vtkm::Id GetNumberOfValues() const { return this->Storage->GetNumberOfValues(); }
VTKM_CONT
PortalConstExecution PrepareForInput(bool vtkmNotUsed(updateData)) const
{
return Traits::MakePortalInput(this->Storage->GetImplementation(),
this->Storage->GetArrayTuple(),
this->Storage->GetNumberOfValues(),
IndexList{},
Device{});
}
VTKM_CONT
PortalExecution PrepareForInPlace(bool vtkmNotUsed(updateData))
{
return Traits::MakePortalInPlace(this->Storage->GetImplementation(),
this->Storage->GetArrayTuple(),
this->Storage->GetNumberOfValues(),
IndexList{},
Device{});
}
VTKM_CONT
PortalExecution PrepareForOutput(vtkm::Id)
{
return Traits::MakePortalOutput(this->Storage->GetImplementation(),
this->Storage->GetArrayTuple(),
this->Storage->GetNumberOfValues(),
IndexList{},
Device{});
}
VTKM_CONT
void RetrieveOutputData(StorageType* vtkmNotUsed(storage)) const
{
// Implementation of this method should be unnecessary. The internal
// array handles should automatically retrieve the output data as
// necessary.
}
VTKM_CONT
void Shrink(vtkm::Id)
{
// no-op
}
VTKM_CONT
void ReleaseResources()
{
// no-op
}
private:
StorageType* Storage;
};
} // namespace internal
/// \brief A fancy ArrayHandle that can be used to modify the results from one
/// or more source ArrayHandle.
///
/// ArrayHandleDecorator is given a `DecoratorImplT` class and a list of one or
/// more source ArrayHandles. There are no restrictions on the size or type of
/// the source ArrayHandles.
///
/// The decorator implementation class is described below:
///
/// ```
/// struct ExampleDecoratorImplementation
/// {
///
/// // Takes one portal for each source array handle (only two shown).
/// // Returns a functor that defines:
/// //
/// // ValueType operator()(vtkm::Id id) const;
/// //
/// // which takes an index and returns a value which should be produced by
/// // the source arrays somehow. This ValueType will be the ValueType of the
/// // ArrayHandleDecorator.
/// //
/// // Both SomeFunctor::operator() and CreateFunctor must be const.
/// //
/// template <typename Portal1Type, typename Portal2Type>
/// SomeFunctor CreateFunctor(Portal1Type portal1, Portal2Type portal2) const;
///
/// // Takes one portal for each source array handle (only two shown).
/// // Returns a functor that defines:
/// //
/// // void operator()(vtkm::Id id, ValueType val) const;
/// //
/// // which takes an index and a value, which should be used to modify one
/// // or more of the source arrays.
/// //
/// // CreateInverseFunctor is optional; if not provided, the
/// // ArrayHandleDecorator will be read-only. In addition, if all of the
/// // source ArrayHandles are read-only, the inverse functor will not be used
/// // and the ArrayHandleDecorator will be read only.
/// //
/// // Both SomeInverseFunctor::operator() and CreateInverseFunctor must be
/// // const.
/// //
/// template <typename Portal1Type, typename Portal2Type>
/// SomeInverseFunctor CreateInverseFunctor(Portal1Type portal1,
/// Portal2Type portal2) const;
///
/// };
/// ```
///
/// There are several example DecoratorImpl classes provided in the
/// UnitTestArrayHandleDecorator test file.
///
template <typename DecoratorImplT, typename... ArrayTs>
class ArrayHandleDecorator
: public internal::DecoratorHandleTraits<typename std::decay<DecoratorImplT>::type,
typename std::decay<ArrayTs>::type...>::Superclass
{
private:
using Traits = internal::DecoratorHandleTraits<typename std::decay<DecoratorImplT>::type,
typename std::decay<ArrayTs>::type...>;
using StorageType = typename Traits::StorageType;
public:
VTKM_ARRAY_HANDLE_SUBCLASS(ArrayHandleDecorator,
(ArrayHandleDecorator<typename std::decay<DecoratorImplT>::type,
typename std::decay<ArrayTs>::type...>),
(typename Traits::Superclass));
VTKM_CONT
ArrayHandleDecorator(vtkm::Id numValues,
const typename std::decay<DecoratorImplT>::type& impl,
const typename std::decay<ArrayTs>::type&... arrays)
: Superclass{ StorageType{ impl, vtkmstd::make_tuple(arrays...), numValues } }
{
}
};
/// Create an ArrayHandleDecorator with the specified number of values that
/// uses the provided DecoratorImplT and source ArrayHandles.
///
template <typename DecoratorImplT, typename... ArrayTs>
VTKM_CONT ArrayHandleDecorator<typename std::decay<DecoratorImplT>::type,
typename std::decay<ArrayTs>::type...>
make_ArrayHandleDecorator(vtkm::Id numValues, DecoratorImplT&& f, ArrayTs&&... arrays)
{
using AHList = brigand::list<typename std::decay<ArrayTs>::type...>;
VTKM_STATIC_ASSERT_MSG(sizeof...(ArrayTs) > 0,
"Must specify at least one source array handle for "
"ArrayHandleDecorator. Consider using "
"ArrayHandleImplicit instead.");
VTKM_STATIC_ASSERT_MSG(internal::decor::AllAreArrayHandles<AHList>::value,
"Trailing template parameters for "
"ArrayHandleDecorator must be a list of ArrayHandle "
"types.");
return { numValues, std::forward<DecoratorImplT>(f), std::forward<ArrayTs>(arrays)... };
}
}
} // namespace vtkm::cont
#endif //vtk_m_ArrayHandleDecorator_h

@ -23,6 +23,8 @@ namespace internal
template <typename PortalType>
class VTKM_ALWAYS_EXPORT ArrayPortalExtractComponent
{
using Writable = vtkm::internal::PortalSupportsSets<PortalType>;
public:
using VectorType = typename PortalType::ValueType;
using Traits = vtkm::VecTraits<VectorType>;
@ -58,8 +60,9 @@ public:
return Traits::GetComponent(this->Portal.Get(index), this->Component);
}
VTKM_EXEC_CONT
void Set(vtkm::Id index, const ValueType& value) const
template <typename Writable_ = Writable,
typename = typename std::enable_if<Writable_::value>::type>
VTKM_EXEC_CONT void Set(vtkm::Id index, const ValueType& value) const
{
VectorType vec = this->Portal.Get(index);
Traits::SetComponent(vec, this->Component, value);
@ -300,6 +303,7 @@ VTKM_CONT ArrayHandleExtractComponent<ArrayHandleType> make_ArrayHandleExtractCo
//=============================================================================
// Specializations of serialization related classes
/// @cond SERIALIZATION
namespace vtkm
{
namespace cont
@ -362,5 +366,6 @@ struct Serialization<
{
};
} // diy
/// @endcond SERIALIZATION
#endif // vtk_m_cont_ArrayHandleExtractComponent_h

@ -100,6 +100,7 @@ vtkm::cont::ArrayHandleExtrudeCoords<T> make_ArrayHandleExtrudeCoords(
//=============================================================================
// Specializations of serialization related classes
/// @cond SERIALIZATION
namespace vtkm
{
namespace cont
@ -149,5 +150,6 @@ public:
};
} // diy
/// @endcond SERIALIZATION
#endif

@ -92,6 +92,7 @@ vtkm::cont::ArrayHandleExtrudeField<T> make_ArrayHandleExtrudeField(
//=============================================================================
// Specializations of serialization related classes
/// @cond SERIALIZATION
namespace vtkm
{
namespace cont
@ -141,5 +142,6 @@ public:
};
} // diy
/// @endcond SERIALIZATION
#endif

@ -25,6 +25,8 @@ namespace internal
template <typename PortalType, vtkm::IdComponent N_COMPONENTS>
class VTKM_ALWAYS_EXPORT ArrayPortalGroupVec
{
using Writable = vtkm::internal::PortalSupportsSets<PortalType>;
public:
static constexpr vtkm::IdComponent NUM_COMPONENTS = N_COMPONENTS;
using SourcePortalType = PortalType;
@ -79,8 +81,9 @@ public:
}
VTKM_SUPPRESS_EXEC_WARNINGS
VTKM_EXEC_CONT
void Set(vtkm::Id index, const ValueType& value) const
template <typename Writable_ = Writable,
typename = typename std::enable_if<Writable_::value>::type>
VTKM_EXEC_CONT void Set(vtkm::Id index, const ValueType& value) const
{
vtkm::Id sourceIndex = index * NUM_COMPONENTS;
for (vtkm::IdComponent componentIndex = 0; componentIndex < NUM_COMPONENTS; componentIndex++)
@ -358,6 +361,7 @@ VTKM_CONT vtkm::cont::ArrayHandleGroupVec<ArrayHandleType, NUM_COMPONENTS> make_
//=============================================================================
// Specializations of serialization related classes
/// @cond SERIALIZATION
namespace vtkm
{
namespace cont
@ -418,5 +422,6 @@ struct Serialization<
};
} // diy
/// @endcond SERIALIZATION
#endif //vtk_m_cont_ArrayHandleGroupVec_h

@ -499,6 +499,7 @@ VTKM_CONT vtkm::cont::ArrayHandle<vtkm::Id> ConvertNumComponentsToOffsets(
//=============================================================================
// Specializations of serialization related classes
/// @cond SERIALIZATION
namespace vtkm
{
namespace cont
@ -562,5 +563,6 @@ struct Serialization<
{
};
} // diy
/// @endcond SERIALIZATION
#endif //vtk_m_cont_ArrayHandleGroupVecVariable_h

@ -128,6 +128,7 @@ VTKM_CONT vtkm::cont::ArrayHandleImplicit<FunctorType> make_ArrayHandleImplicit(
//=============================================================================
// Specializations of serialization related classes
/// @cond SERIALIZATION
namespace vtkm
{
namespace cont
@ -191,5 +192,6 @@ struct Serialization<vtkm::cont::ArrayHandle<
};
} // diy
/// @endcond SERIALIZATION
#endif //vtk_m_cont_ArrayHandleImplicit_h

@ -51,6 +51,7 @@ public:
//=============================================================================
// Specializations of serialization related classes
/// @cond SERIALIZATION
namespace vtkm
{
@ -89,5 +90,6 @@ struct Serialization<vtkm::cont::ArrayHandleIndex>
};
} // diy
/// @endcond SERIALIZATION
#endif //vtk_m_cont_ArrayHandleIndex_h

@ -24,6 +24,8 @@ namespace internal
template <typename IndexPortalType, typename ValuePortalType>
class VTKM_ALWAYS_EXPORT ArrayPortalPermutation
{
using Writable = vtkm::internal::PortalSupportsSets<ValuePortalType>;
public:
using ValueType = typename ValuePortalType::ValueType;
@ -69,8 +71,9 @@ public:
}
VTKM_SUPPRESS_EXEC_WARNINGS
VTKM_EXEC
void Set(vtkm::Id index, const ValueType& value) const
template <typename Writable_ = Writable,
typename = typename std::enable_if<Writable_::value>::type>
VTKM_EXEC void Set(vtkm::Id index, const ValueType& value) const
{
vtkm::Id permutedIndex = this->IndexPortal.Get(index);
this->ValuePortal.Set(permutedIndex, value);
@ -362,6 +365,7 @@ make_ArrayHandlePermutation(IndexArrayHandleType indexArray, ValueArrayHandleTyp
//=============================================================================
// Specializations of serialization related classes
/// @cond SERIALIZATION
namespace vtkm
{
namespace cont
@ -427,5 +431,6 @@ struct Serialization<
};
} // diy
/// @endcond SERIALIZATION
#endif //vtk_m_cont_ArrayHandlePermutation_h

@ -26,6 +26,8 @@ namespace internal
template <typename PortalType>
class VTKM_ALWAYS_EXPORT ArrayPortalReverse
{
using Writable = vtkm::internal::PortalSupportsSets<PortalType>;
public:
using ValueType = typename PortalType::ValueType;
@ -56,8 +58,9 @@ public:
return this->portal.Get(portal.GetNumberOfValues() - index - 1);
}
VTKM_EXEC_CONT
void Set(vtkm::Id index, const ValueType& value) const
template <typename Writable_ = Writable,
typename = typename std::enable_if<Writable_::value>::type>
VTKM_EXEC_CONT void Set(vtkm::Id index, const ValueType& value) const
{
this->portal.Set(portal.GetNumberOfValues() - index - 1, value);
}
@ -233,6 +236,7 @@ VTKM_CONT ArrayHandleReverse<HandleType> make_ArrayHandleReverse(const HandleTyp
//=============================================================================
// Specializations of serialization related classes
/// @cond SERIALIZATION
namespace vtkm
{
namespace cont
@ -289,5 +293,6 @@ struct Serialization<
};
} // diy
/// @endcond SERIALIZATION
#endif // vtk_m_cont_ArrayHandleReverse_h

@ -614,6 +614,7 @@ VTKM_CONT
//=============================================================================
// Specializations of serialization related classes
/// @cond SERIALIZATION
namespace vtkm
{

@ -23,6 +23,8 @@ namespace internal
template <typename P>
class VTKM_ALWAYS_EXPORT ArrayPortalStreaming
{
using Writable = vtkm::internal::PortalSupportsSets<P>;
public:
using PortalType = P;
using ValueType = typename PortalType::ValueType;
@ -66,8 +68,9 @@ public:
return this->InputPortal.Get(this->BlockIndex * this->BlockSize + index);
}
VTKM_CONT
void Set(vtkm::Id index, const ValueType& value) const
template <typename Writable_ = Writable,
typename = typename std::enable_if<Writable_::value>::type>
VTKM_CONT void Set(vtkm::Id index, const ValueType& value) const
{
this->InputPortal.Set(this->BlockIndex * this->BlockSize + index, value);
}

@ -117,6 +117,7 @@ template <typename PortalType, typename ArrayHandleType, vtkm::IdComponent OutSi
class VTKM_ALWAYS_EXPORT ArrayPortalSwizzle
{
using Traits = internal::ArrayHandleSwizzleTraits<ArrayHandleType, OutSize>;
using Writable = vtkm::internal::PortalSupportsSets<PortalType>;
public:
using MapType = typename Traits::MapType;
@ -154,8 +155,9 @@ public:
return result;
}
VTKM_EXEC_CONT
void Set(vtkm::Id index, const ValueType& value) const
template <typename Writable_ = Writable,
typename = typename std::enable_if<Writable_::value>::type>
VTKM_EXEC_CONT void Set(vtkm::Id index, const ValueType& value) const
{
if (Traits::AllCompsUsed)
{ // No need to prefetch the value, all values overwritten
@ -388,6 +390,7 @@ make_ArrayHandleSwizzle(const ArrayHandleType& array,
//=============================================================================
// Specializations of serialization related classes
/// @cond SERIALIZATION
namespace vtkm
{
namespace cont
@ -451,5 +454,6 @@ struct Serialization<vtkm::cont::ArrayHandle<
};
} // diy
/// @endcond SERIALIZATION
#endif // vtk_m_cont_ArrayHandleSwizzle_h

@ -90,16 +90,6 @@ public:
VTKM_EXEC_CONT
ValueType Get(vtkm::Id index) const { return this->Functor(this->Portal.Get(index)); }
VTKM_SUPPRESS_EXEC_WARNINGS
VTKM_EXEC_CONT
void Set(vtkm::Id vtkmNotUsed(index), const ValueType& vtkmNotUsed(value)) const
{
#if !(defined(VTKM_MSVC) && defined(VTKM_CUDA))
VTKM_ASSERT(false &&
"Cannot write to read-only transform array. (No inverse transform given.)");
#endif
}
VTKM_SUPPRESS_EXEC_WARNINGS
VTKM_EXEC_CONT
const PortalType& GetPortal() const { return this->Portal; }
@ -120,6 +110,8 @@ template <typename ValueType_,
class VTKM_ALWAYS_EXPORT ArrayPortalTransform
: public ArrayPortalTransform<ValueType_, PortalType_, FunctorType_, NullFunctorType>
{
using Writable = vtkm::internal::PortalSupportsSets<PortalType_>;
public:
using Superclass = ArrayPortalTransform<ValueType_, PortalType_, FunctorType_, NullFunctorType>;
using PortalType = PortalType_;
@ -147,11 +139,11 @@ public:
}
VTKM_SUPPRESS_EXEC_WARNINGS
VTKM_EXEC_CONT
void Set(vtkm::Id index, const ValueType& value) const
template <typename Writable_ = Writable,
typename = typename std::enable_if<Writable_::value>::type>
VTKM_EXEC_CONT void Set(vtkm::Id index, const ValueType& value) const
{
using call_supported_t = typename vtkm::internal::PortalSupportsSets<PortalType>::type;
this->Set(call_supported_t(), index, value);
this->Portal.Set(index, this->InverseFunctor(value));
}
VTKM_SUPPRESS_EXEC_WARNINGS
@ -160,14 +152,6 @@ public:
private:
InverseFunctorType InverseFunctor;
VTKM_SUPPRESS_EXEC_WARNINGS
VTKM_EXEC_CONT
inline void Set(std::true_type, vtkm::Id index, const ValueType& value) const
{
this->Portal.Set(index, this->InverseFunctor(value));
}
VTKM_EXEC_CONT inline void Set(std::false_type, vtkm::Id, const ValueType&) const {}
};
}
}
@ -734,6 +718,7 @@ make_ArrayHandleTransform(HandleType handle, FunctorType functor, InverseFunctor
//=============================================================================
// Specializations of serialization related classes
/// @cond SERIALIZATION
namespace vtkm
{
namespace cont
@ -837,5 +822,6 @@ struct Serialization<vtkm::cont::ArrayHandle<
};
} // diy
/// @endcond SERIALIZATION
#endif //vtk_m_cont_ArrayHandleTransform_h

@ -54,6 +54,7 @@ public:
//=============================================================================
// Specializations of serialization related classes
/// @cond SERIALIZATION
namespace vtkm
{
namespace cont
@ -116,5 +117,6 @@ struct Serialization<vtkm::cont::ArrayHandle<
};
} // diy
/// @endcond SERIALIZATION
#endif //vtk_+m_cont_ArrayHandleUniformPointCoordinates_h

@ -26,6 +26,8 @@ namespace internal
template <typename TargetPortalType>
class ArrayPortalView
{
using Writable = vtkm::internal::PortalSupportsSets<TargetPortalType>;
public:
using ValueType = typename TargetPortalType::ValueType;
@ -59,8 +61,9 @@ public:
ValueType Get(vtkm::Id index) const { return this->TargetPortal.Get(index + this->StartIndex); }
VTKM_SUPPRESS_EXEC_WARNINGS
VTKM_EXEC_CONT
void Set(vtkm::Id index, const ValueType& value) const
template <typename Writable_ = Writable,
typename = typename std::enable_if<Writable_::value>::type>
VTKM_EXEC_CONT void Set(vtkm::Id index, const ValueType& value) const
{
this->TargetPortal.Set(index + this->StartIndex, value);
}

@ -223,6 +223,7 @@ VTKM_CONT inline ArrayHandleType Cast(
}
//=============================================================================
// Specializations of serialization related classes
/// @cond SERIALIZATION
template <typename T>
struct SerializableTypeString<vtkm::cont::ArrayHandleVirtual<T>>
{

@ -44,6 +44,7 @@ ArrayHandleType inline ArrayHandleVirtual<T>::CastToType(
//=============================================================================
// Specializations of serialization related classes
/// @cond SERIALIZATION
namespace mangled_diy_namespace
{

@ -71,6 +71,7 @@ struct SerializableTypeString<vtkm::cont::ArrayHandleVirtualCoordinates>
//=============================================================================
// Specializations of serialization related classes
/// @cond SERIALIZATION
namespace mangled_diy_namespace
{
@ -151,5 +152,6 @@ public:
};
} // diy
/// @endcond SERIALIZATION
#endif // vtk_m_cont_ArrayHandleVirtualCoordinates_h

@ -26,6 +26,14 @@ namespace internal
template <typename ValueType_, typename PortalTypeFirst_, typename PortalTypeSecond_>
class ArrayPortalZip
{
using ReadableP1 = vtkm::internal::PortalSupportsGets<PortalTypeFirst_>;
using ReadableP2 = vtkm::internal::PortalSupportsGets<PortalTypeSecond_>;
using WritableP1 = vtkm::internal::PortalSupportsSets<PortalTypeFirst_>;
using WritableP2 = vtkm::internal::PortalSupportsSets<PortalTypeSecond_>;
using Readable = std::integral_constant<bool, ReadableP1::value && ReadableP2::value>;
using Writable = std::integral_constant<bool, WritableP1::value && WritableP2::value>;
public:
using ValueType = ValueType_;
using T = typename ValueType::FirstType;
@ -64,23 +72,19 @@ public:
VTKM_EXEC_CONT
vtkm::Id GetNumberOfValues() const { return this->PortalFirst.GetNumberOfValues(); }
VTKM_EXEC
ValueType Get(vtkm::Id index) const
template <typename Readable_ = Readable,
typename = typename std::enable_if<Readable_::value>::type>
VTKM_EXEC_CONT ValueType Get(vtkm::Id index) const noexcept
{
using call_supported_t1 = typename vtkm::internal::PortalSupportsGets<PortalTypeFirst>::type;
using call_supported_t2 = typename vtkm::internal::PortalSupportsGets<PortalTypeSecond>::type;
return vtkm::make_Pair(this->GetFirst(call_supported_t1(), index),
this->GetSecond(call_supported_t2(), index));
return vtkm::make_Pair(this->PortalFirst.Get(index), this->PortalSecond.Get(index));
}
VTKM_EXEC
void Set(vtkm::Id index, const ValueType& value) const
template <typename Writable_ = Writable,
typename = typename std::enable_if<Writable_::value>::type>
VTKM_EXEC_CONT void Set(vtkm::Id index, const ValueType& value) const noexcept
{
using call_supported_t1 = typename vtkm::internal::PortalSupportsSets<PortalTypeFirst>::type;
using call_supported_t2 = typename vtkm::internal::PortalSupportsSets<PortalTypeSecond>::type;
this->SetFirst(call_supported_t1(), index, value.first);
this->SetSecond(call_supported_t2(), index, value.second);
this->PortalFirst.Set(index, value.first);
this->PortalSecond.Set(index, value.second);
}
VTKM_EXEC_CONT
@ -90,28 +94,6 @@ public:
const PortalTypeSecond& GetSecondPortal() const { return this->PortalSecond; }
private:
VTKM_EXEC inline T GetFirst(std::true_type, vtkm::Id index) const noexcept
{
return this->PortalFirst.Get(index);
}
VTKM_EXEC inline T GetFirst(std::false_type, vtkm::Id) const noexcept { return T{}; }
VTKM_EXEC inline U GetSecond(std::true_type, vtkm::Id index) const noexcept
{
return this->PortalSecond.Get(index);
}
VTKM_EXEC inline U GetSecond(std::false_type, vtkm::Id) const noexcept { return U{}; }
VTKM_EXEC inline void SetFirst(std::true_type, vtkm::Id index, const T& value) const noexcept
{
this->PortalFirst.Set(index, value);
}
VTKM_EXEC inline void SetFirst(std::false_type, vtkm::Id, const T&) const noexcept {}
VTKM_EXEC inline void SetSecond(std::true_type, vtkm::Id index, const U& value) const noexcept
{
this->PortalSecond.Set(index, value);
}
VTKM_EXEC inline void SetSecond(std::false_type, vtkm::Id, const U&) const noexcept {}
PortalTypeFirst PortalFirst;
PortalTypeSecond PortalSecond;
};
@ -376,6 +358,7 @@ VTKM_CONT vtkm::cont::ArrayHandleZip<FirstHandleType, SecondHandleType> make_Arr
//=============================================================================
// Specializations of serialization related classes
/// @cond SERIALIZATION
namespace vtkm
{
namespace cont
@ -441,5 +424,6 @@ struct Serialization<
};
} // diy
/// @endcond SERIALIZATION
#endif //vtk_m_cont_ArrayHandleZip_h

@ -45,6 +45,12 @@ namespace cont
/// Although portals are defined in the execution environment, they are also
/// used in the control environment for accessing data on the host.
///
/// Since utilities like IsWritableArrayHandle checks for the existence of a Set
/// method on a portal, if the portal is backed by a read-only ArrayHandle, the
/// Set method must not be defined. If the portal may or may not be writable
/// (e.g., ArrayHandleCast may be casting a read-only OR read-write array), the
/// Set method may be conditionally removed using SFINAE.
///
template <typename T>
class ArrayPortal
{
@ -65,8 +71,7 @@ public:
ValueType Get(vtkm::Id index) const;
/// Sets a value in the array. If it is not possible to set a value in the
/// array, this method may error out (for example with a VTKM_ASSERT). In
/// this case the behavior is undefined.
/// array, this method must not be defined.
///
VTKM_EXEC_CONT
void Set(vtkm::Id index, const ValueType& value) const;

@ -43,49 +43,49 @@ VTKM_CONT vtkm::cont::ArrayHandle<vtkm::Range> ArrayRangeCompute(
vtkm::cont::DeviceAdapterId device = vtkm::cont::DeviceAdapterTagAny());
// Precompiled versions of ArrayRangeCompute
#define VTKM_ARRAY_RANGE_COMPUTE_EXPORT_T(T, Storage) \
#define VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_T(T, Storage) \
VTKM_CONT_EXPORT \
VTKM_CONT \
vtkm::cont::ArrayHandle<vtkm::Range> ArrayRangeCompute( \
const vtkm::cont::ArrayHandle<T, Storage>& input, \
vtkm::cont::DeviceAdapterId device = vtkm::cont::DeviceAdapterTagAny())
#define VTKM_ARRAY_RANGE_COMPUTE_EXPORT_VEC(T, N, Storage) \
#define VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_VEC(T, N, Storage) \
VTKM_CONT_EXPORT \
VTKM_CONT \
vtkm::cont::ArrayHandle<vtkm::Range> ArrayRangeCompute( \
const vtkm::cont::ArrayHandle<vtkm::Vec<T, N>, Storage>& input, \
vtkm::cont::DeviceAdapterId device = vtkm::cont::DeviceAdapterTagAny())
VTKM_ARRAY_RANGE_COMPUTE_EXPORT_T(char, vtkm::cont::StorageTagBasic);
VTKM_ARRAY_RANGE_COMPUTE_EXPORT_T(vtkm::Int8, vtkm::cont::StorageTagBasic);
VTKM_ARRAY_RANGE_COMPUTE_EXPORT_T(vtkm::UInt8, vtkm::cont::StorageTagBasic);
VTKM_ARRAY_RANGE_COMPUTE_EXPORT_T(vtkm::Int16, vtkm::cont::StorageTagBasic);
VTKM_ARRAY_RANGE_COMPUTE_EXPORT_T(vtkm::UInt16, vtkm::cont::StorageTagBasic);
VTKM_ARRAY_RANGE_COMPUTE_EXPORT_T(vtkm::Int32, vtkm::cont::StorageTagBasic);
VTKM_ARRAY_RANGE_COMPUTE_EXPORT_T(vtkm::UInt32, vtkm::cont::StorageTagBasic);
VTKM_ARRAY_RANGE_COMPUTE_EXPORT_T(vtkm::Int64, vtkm::cont::StorageTagBasic);
VTKM_ARRAY_RANGE_COMPUTE_EXPORT_T(vtkm::UInt64, vtkm::cont::StorageTagBasic);
VTKM_ARRAY_RANGE_COMPUTE_EXPORT_T(vtkm::Float32, vtkm::cont::StorageTagBasic);
VTKM_ARRAY_RANGE_COMPUTE_EXPORT_T(vtkm::Float64, vtkm::cont::StorageTagBasic);
VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_T(char, vtkm::cont::StorageTagBasic);
VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_T(vtkm::Int8, vtkm::cont::StorageTagBasic);
VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_T(vtkm::UInt8, vtkm::cont::StorageTagBasic);
VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_T(vtkm::Int16, vtkm::cont::StorageTagBasic);
VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_T(vtkm::UInt16, vtkm::cont::StorageTagBasic);
VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_T(vtkm::Int32, vtkm::cont::StorageTagBasic);
VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_T(vtkm::UInt32, vtkm::cont::StorageTagBasic);
VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_T(vtkm::Int64, vtkm::cont::StorageTagBasic);
VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_T(vtkm::UInt64, vtkm::cont::StorageTagBasic);
VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_T(vtkm::Float32, vtkm::cont::StorageTagBasic);
VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_T(vtkm::Float64, vtkm::cont::StorageTagBasic);
VTKM_ARRAY_RANGE_COMPUTE_EXPORT_VEC(vtkm::Int32, 2, vtkm::cont::StorageTagBasic);
VTKM_ARRAY_RANGE_COMPUTE_EXPORT_VEC(vtkm::Int64, 2, vtkm::cont::StorageTagBasic);
VTKM_ARRAY_RANGE_COMPUTE_EXPORT_VEC(vtkm::Float32, 2, vtkm::cont::StorageTagBasic);
VTKM_ARRAY_RANGE_COMPUTE_EXPORT_VEC(vtkm::Float64, 2, vtkm::cont::StorageTagBasic);
VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_VEC(vtkm::Int32, 2, vtkm::cont::StorageTagBasic);
VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_VEC(vtkm::Int64, 2, vtkm::cont::StorageTagBasic);
VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_VEC(vtkm::Float32, 2, vtkm::cont::StorageTagBasic);
VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_VEC(vtkm::Float64, 2, vtkm::cont::StorageTagBasic);
VTKM_ARRAY_RANGE_COMPUTE_EXPORT_VEC(vtkm::Int32, 3, vtkm::cont::StorageTagBasic);
VTKM_ARRAY_RANGE_COMPUTE_EXPORT_VEC(vtkm::Int64, 3, vtkm::cont::StorageTagBasic);
VTKM_ARRAY_RANGE_COMPUTE_EXPORT_VEC(vtkm::Float32, 3, vtkm::cont::StorageTagBasic);
VTKM_ARRAY_RANGE_COMPUTE_EXPORT_VEC(vtkm::Float64, 3, vtkm::cont::StorageTagBasic);
VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_VEC(vtkm::Int32, 3, vtkm::cont::StorageTagBasic);
VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_VEC(vtkm::Int64, 3, vtkm::cont::StorageTagBasic);
VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_VEC(vtkm::Float32, 3, vtkm::cont::StorageTagBasic);
VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_VEC(vtkm::Float64, 3, vtkm::cont::StorageTagBasic);
VTKM_ARRAY_RANGE_COMPUTE_EXPORT_VEC(char, 4, vtkm::cont::StorageTagBasic);
VTKM_ARRAY_RANGE_COMPUTE_EXPORT_VEC(vtkm::Int8, 4, vtkm::cont::StorageTagBasic);
VTKM_ARRAY_RANGE_COMPUTE_EXPORT_VEC(vtkm::UInt8, 4, vtkm::cont::StorageTagBasic);
VTKM_ARRAY_RANGE_COMPUTE_EXPORT_VEC(vtkm::Float32, 4, vtkm::cont::StorageTagBasic);
VTKM_ARRAY_RANGE_COMPUTE_EXPORT_VEC(vtkm::Float64, 4, vtkm::cont::StorageTagBasic);
VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_VEC(char, 4, vtkm::cont::StorageTagBasic);
VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_VEC(vtkm::Int8, 4, vtkm::cont::StorageTagBasic);
VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_VEC(vtkm::UInt8, 4, vtkm::cont::StorageTagBasic);
VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_VEC(vtkm::Float32, 4, vtkm::cont::StorageTagBasic);
VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_VEC(vtkm::Float64, 4, vtkm::cont::StorageTagBasic);
#undef VTKM_ARRAY_RANGE_COMPUTE_EXPORT_T
#undef VTKM_ARRAY_RANGE_COMPUTE_EXPORT_VEC
#undef VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_T
#undef VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_VEC
VTKM_CONT
vtkm::cont::ArrayHandle<vtkm::Range> ArrayRangeCompute(

@ -20,6 +20,7 @@ set(headers
ArrayHandleConcatenate.h
ArrayHandleConstant.h
ArrayHandleCounting.h
ArrayHandleDecorator.h
ArrayHandleDiscard.h
ArrayHandleExtractComponent.h
ArrayHandleExtrudeCoords.h

@ -342,6 +342,7 @@ extern template class VTKM_CONT_TEMPLATE_EXPORT CellSetExplicit<
//=============================================================================
// Specializations of serialization related classes
/// @cond SERIALIZATION
namespace vtkm
{
namespace cont
@ -407,6 +408,7 @@ public:
};
} // diy
/// @endcond SERIALIZATION
#include <vtkm/cont/CellSetExplicit.hxx>

@ -158,6 +158,7 @@ CellSetExtrude make_CellSetExtrude(const std::vector<vtkm::Int32>& conn,
//=============================================================================
// Specializations of serialization related classes
/// @cond SERIALIZATION
namespace vtkm
{
namespace cont
@ -213,6 +214,7 @@ public:
};
} // diy
/// @endcond SERIALIZATION
#include <vtkm/cont/CellSetExtrude.hxx>

@ -484,6 +484,7 @@ vtkm::cont::CellSetPermutation<OriginalCellSet, PermutationArrayHandleType> make
//=============================================================================
// Specializations of serialization related classes
/// @cond SERIALIZATION
namespace vtkm
{
namespace cont
@ -530,5 +531,6 @@ public:
};
} // diy
/// @endcond SERIALIZATION
#endif //vtk_m_cont_CellSetPermutation_h

@ -291,6 +291,7 @@ private:
//=============================================================================
// Specializations of serialization related classes
/// @cond SERIALIZATION
namespace vtkm
{
namespace cont
@ -346,5 +347,6 @@ public:
};
} // diy
/// @endcond SERIALIZATION
#endif //vtk_m_cont_CellSetSingleType_h

@ -133,6 +133,7 @@ extern template class VTKM_CONT_TEMPLATE_EXPORT CellSetStructured<3>;
//=============================================================================
// Specializations of serialization related classes
/// @cond SERIALIZATION
namespace vtkm
{
namespace cont
@ -179,6 +180,7 @@ public:
};
} // diy
/// @endcond SERIALIZATION
#include <vtkm/cont/CellSetStructured.hxx>

@ -142,6 +142,7 @@ struct DynamicTransformTraits<vtkm::cont::CoordinateSystem>
//=============================================================================
// Specializations of serialization related classes
/// @cond SERIALIZATION
namespace mangled_diy_namespace
{
@ -165,5 +166,6 @@ struct Serialization<vtkm::cont::CoordinateSystem>
};
} // diy
/// @endcond SERIALIZATION
#endif //vtk_m_cont_CoordinateSystem_h

@ -218,6 +218,7 @@ private:
//=============================================================================
// Specializations of serialization related classes
/// @cond SERIALIZATION
namespace vtkm
{
namespace cont
@ -300,5 +301,6 @@ public:
};
} // diy
/// @endcond SERIALIZATION
#endif //vtk_m_cont_DataSet_h

@ -338,6 +338,7 @@ struct DynamicCellSetCheck<vtkm::cont::DynamicCellSetBase<CellSetList>>
//=============================================================================
// Specializations of serialization related classes
/// @cond SERIALIZATION
namespace mangled_diy_namespace
{
@ -410,5 +411,6 @@ public:
};
} // diy
/// @endcond SERIALIZATION
#endif //vtk_m_cont_DynamicCellSet_h

@ -37,6 +37,7 @@ public:
#ifndef GetMessage
const std::string& GetMessage() const { return this->Message; }
#endif
const std::string& GetStackTrace() const { return this->StackTrace; }
//GetMessage is a macro defined by <windows.h> to redirrect to
//GetMessageA or W depending on if you are using ansi or unicode.
@ -47,7 +48,7 @@ public:
#endif
// For std::exception compatibility:
const char* what() const noexcept override { return this->Message.c_str(); }
const char* what() const noexcept override { return this->What.c_str(); }
/// Returns true if this exception is device independent. For exceptions that
/// are not device independent, `vtkm::TryExecute`, for example, may try
@ -58,17 +59,18 @@ protected:
Error() {}
Error(const std::string& message, bool is_device_independent = false)
: Message(message)
, StackTrace(vtkm::cont::GetStackTrace(1))
, What(Message + "\n" + StackTrace)
, IsDeviceIndependent(is_device_independent)
{
VTKM_LOG_S(vtkm::cont::LogLevel::Warn,
"Exception raised: " << message << "\n"
<< vtkm::cont::GetStackTrace(1)); // 1 = skip this ctor frame.
}
void SetMessage(const std::string& message) { this->Message = message; }
private:
std::string Message;
std::string StackTrace;
std::string What;
bool IsDeviceIndependent;
};

@ -243,6 +243,7 @@ struct DynamicTransformTraits<vtkm::cont::Field>
//=============================================================================
// Specializations of serialization related classes
/// @cond SERIALIZATION
namespace vtkm
{
namespace cont
@ -298,5 +299,6 @@ public:
};
} // diy
/// @endcond SERIALIZATION
#endif //vtk_m_cont_Field_h

@ -123,6 +123,8 @@ void InitLogging(int& argc, char* argv[])
loguru::set_verbosity_to_name_callback(&verbosityToNameCallback);
loguru::set_name_to_verbosity_callback(&nameToVerbosityCallback);
// Set the default log level to warning
SetStderrLogLevel(vtkm::cont::LogLevel::Warn);
loguru::init(argc, argv);
LOG_F(INFO, "Logging initialized.");

@ -50,9 +50,11 @@
/// functions to help format common types of log data such as byte counts and
/// type names.
///
/// Logging is enabled by setting the CMake variable VTKm_ENABLE_LOGGING. When
/// this flag is enabled, any messages logged to the Info, Warn, Error, and
/// Fatal levels are printed to stderr by default.
/// Logging is enabled via the CMake option VTKm_ENABLE_LOGGING by default.
/// The default log level is set to only log Warn and Error messages; Fatal
/// levels are printed to stderr by default. The logging system will need
/// to be initialized through a call to either vtkm::cont::Initialize or
/// vtkm::cont::InitLogging.
///
/// Additional logging features are enabled by calling vtkm::cont::InitLogging
/// (or preferably, vtkm::cont::Initialize) in an executable. This will:
@ -81,7 +83,7 @@
/// vtkm::cont::SetThreadName. This will appear in the log output so that
/// per-thread messages can be easily tracked.
///
/// By default, only Info, Warn, Error, and Fatal messages are printed to
/// By default, only Warn, Error, and Fatal messages are printed to
/// stderr. This can be changed at runtime by passing the '-v' flag to an
/// executable that calls vtkm::cont::InitLogging. Alternatively, the
/// application can explicitly call vtkm::cont::SetStderrLogLevel to change the
@ -351,7 +353,8 @@ enum class LogLevel
*
* Initializes logging. Sets up custom log level and thread names. Parses any
* "-v [LogLevel]" arguments to set the stderr log level. This argument may
* be either numeric, or the 4-character string printed in the output.
* be either numeric, or the 4-character string printed in the output. Note that
* loguru will consume the "-v [LogLevel]" argument and shrink the arg list.
*
* If the parameterless overload is used, the `-v` parsing is not used, but
* other functionality should still work.

@ -51,6 +51,7 @@ std::string GetVariadicSerializableTypeString(const T&)
} // internal
/// @cond SERIALIZATION
template <>
struct SerializableTypeString<vtkm::Int8>
{
@ -174,5 +175,6 @@ struct SerializableTypeString<vtkm::Pair<T1, T2>>
};
}
} // vtkm::cont
/// @endcond SERIALIZATION
#endif // vtk_m_cont_SerializableTypeString_h

@ -557,6 +557,7 @@ struct DynamicTransformTraits<vtkm::cont::VariantArrayHandleBase<TypeList>>
//=============================================================================
// Specializations of serialization related classes
/// @cond SERIALIZATION
namespace mangled_diy_namespace
{
@ -626,6 +627,7 @@ public:
};
} // diy
/// @endcond SERIALIZATION
#endif //vtk_m_virts_VariantArrayHandle_h

@ -29,4 +29,4 @@ set(unit_tests
UnitTestCudaPointLocatorUniformGrid.cu
UnitTestCudaVirtualObjectHandle.cu
)
vtkm_unit_tests(SOURCES ${unit_tests} LIBRARIES vtkm_worklet)
vtkm_unit_tests(SOURCES ${unit_tests} LABEL "CUDA" LIBRARIES vtkm_worklet)

@ -26,7 +26,10 @@ set(unit_tests
UnitTestOpenMPPointLocatorUniformGrid.cxx
UnitTestOpenMPVirtualObjectHandle.cxx
)
vtkm_unit_tests(OpenMP SOURCES ${unit_tests} DEFINES VTKM_NO_ERROR_ON_MIXED_CUDA_CXX_TAG LIBRARIES vtkm_worklet)
vtkm_unit_tests(SOURCES ${unit_tests}
LABEL "OPENMP"
DEFINES VTKM_NO_ERROR_ON_MIXED_CUDA_CXX_TAG
LIBRARIES vtkm_worklet)
if (VTKm_ENABLE_TESTING)
#We need to have all OpenMP tests run serially as they

@ -27,4 +27,7 @@ set(unit_tests
UnitTestSerialPointLocatorUniformGrid.cxx
UnitTestSerialVirtualObjectHandle.cxx
)
vtkm_unit_tests(SOURCES ${unit_tests} DEFINES VTKM_NO_ERROR_ON_MIXED_CUDA_CXX_TAG LIBRARIES vtkm_worklet)
vtkm_unit_tests(SOURCES ${unit_tests}
LABEL "SERIAL"
DEFINES VTKM_NO_ERROR_ON_MIXED_CUDA_CXX_TAG
LIBRARIES vtkm_worklet)

@ -27,4 +27,7 @@ set(unit_tests
UnitTestTBBVirtualObjectHandle.cxx
)
vtkm_unit_tests(SOURCES ${unit_tests} DEFINES VTKM_NO_ERROR_ON_MIXED_CUDA_CXX_TAG LIBRARIES vtkm_worklet)
vtkm_unit_tests(SOURCES ${unit_tests}
LABEL "TBB"
DEFINES VTKM_NO_ERROR_ON_MIXED_CUDA_CXX_TAG
LIBRARIES vtkm_worklet)

@ -39,6 +39,7 @@ set(unit_tests
UnitTestArrayHandleCartesianProduct.cxx
UnitTestArrayHandleCompositeVector.cxx
UnitTestArrayHandleCounting.cxx
UnitTestArrayHandleDecorator.cxx
UnitTestArrayHandleDiscard.cxx
UnitTestArrayHandleExtractComponent.cxx
UnitTestArrayHandleExtrude.cxx
@ -67,6 +68,7 @@ set(unit_tests
UnitTestDeviceAdapterAlgorithmDependency.cxx
UnitTestDeviceAdapterAlgorithmGeneral.cxx
UnitTestDynamicCellSet.cxx
UnitTestError.cxx
UnitTestFieldRangeCompute.cxx
UnitTestInitialize.cxx
UnitTestLogging.cxx

@ -36,7 +36,7 @@ struct Testing
{
public:
template <class Func>
static VTKM_CONT int Run(Func function, int argc, char* argv[])
static VTKM_CONT int Run(Func function, int& argc, char* argv[])
{
vtkm::cont::Initialize(argc, argv);

@ -0,0 +1,402 @@
//============================================================================
// Copyright (c) Kitware, Inc.
// All rights reserved.
// See LICENSE.txt for details.
//
// This software is distributed WITHOUT ANY WARRANTY; without even
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the above copyright notice for more information.
//============================================================================
#include <vtkm/cont/ArrayHandleDecorator.h>
#include <vtkm/cont/Algorithm.h>
#include <vtkm/cont/ArrayCopy.h>
#include <vtkm/cont/ArrayHandle.h>
#include <vtkm/cont/ArrayHandleConstant.h>
#include <vtkm/cont/ArrayHandleCounting.h>
#include <vtkm/BinaryOperators.h>
#include <vtkm/cont/testing/Testing.h>
namespace
{
struct DecoratorTests
{
static constexpr vtkm::Id ARRAY_SIZE = 10;
// Decorator implemenation that demonstrates how to write invertible functors
// that combine three array handles with complex access logic. The resulting
// ArrayHandleDecorator can be both read from and written to.
//
// Constructs functors that take three portals.
//
// The first portal's values are accessed in reverse order.
// The second portal's values are accessed in normal order.
// The third portal's values are accessed via ((idx + 3) % size).
//
// Functor will return the max of the first two added to the third.
//
// InverseFunctor will update the third portal such that the Functor would
// return the indicated value.
struct InvertibleDecorImpl
{
// The functor used for reading data from the three portals.
template <typename Portal1Type, typename Portal2Type, typename Portal3Type>
struct Functor
{
using ValueType = typename Portal1Type::ValueType;
Portal1Type Portal1;
Portal2Type Portal2;
Portal3Type Portal3;
VTKM_EXEC_CONT ValueType operator()(vtkm::Id idx) const
{
const auto idx1 = this->Portal1.GetNumberOfValues() - idx - 1;
const auto idx2 = idx;
const auto idx3 = (idx + 3) % this->Portal3.GetNumberOfValues();
const auto v1 = this->Portal1.Get(idx1);
const auto v2 = this->Portal2.Get(idx2);
const auto v3 = this->Portal3.Get(idx3);
return vtkm::Max(v1, v2) + v3;
}
};
// The functor used for writing. Only Portal3 is written to, the other
// portals may be read-only.
template <typename Portal1Type, typename Portal2Type, typename Portal3Type>
struct InverseFunctor
{
using ValueType = typename Portal1Type::ValueType;
Portal1Type Portal1;
Portal2Type Portal2;
Portal3Type Portal3;
VTKM_EXEC_CONT void operator()(vtkm::Id idx, const ValueType& vIn) const
{
const auto v1 = this->Portal1.Get(this->Portal1.GetNumberOfValues() - idx - 1);
const auto v2 = this->Portal2.Get(idx);
const auto vNew = static_cast<ValueType>(vIn - vtkm::Max(v1, v2));
this->Portal3.Set((idx + 3) % this->Portal3.GetNumberOfValues(), vNew);
}
};
// Factory function that takes 3 portals as input and creates an instance
// of Functor with them. Variadic template parameters are used here, but are
// not necessary.
template <typename... PortalTs>
Functor<typename std::decay<PortalTs>::type...> CreateFunctor(PortalTs&&... portals) const
{
VTKM_STATIC_ASSERT(sizeof...(PortalTs) == 3);
return { std::forward<PortalTs>(portals)... };
}
// Factory function that takes 3 portals as input and creates an instance
// of InverseFunctor with them. Variadic template parameters are used here,
// but are not necessary.
template <typename... PortalTs>
InverseFunctor<typename std::decay<PortalTs>::type...> CreateInverseFunctor(
PortalTs&&... portals) const
{
VTKM_STATIC_ASSERT(sizeof...(PortalTs) == 3);
return { std::forward<PortalTs>(portals)... };
}
};
// Same as above, but cannot be inverted. The resulting ArrayHandleDecorator
// will be read-only.
struct NonInvertibleDecorImpl
{
template <typename Portal1Type, typename Portal2Type, typename Portal3Type>
struct Functor
{
using ValueType = typename Portal1Type::ValueType;
Portal1Type Portal1;
Portal2Type Portal2;
Portal3Type Portal3;
VTKM_EXEC_CONT ValueType operator()(vtkm::Id idx) const
{
const auto v1 = this->Portal1.Get(this->Portal1.GetNumberOfValues() - idx - 1);
const auto v2 = this->Portal2.Get(idx);
const auto v3 = this->Portal3.Get((idx + 3) % this->Portal3.GetNumberOfValues());
return vtkm::Max(v1, v2) + v3;
}
};
template <typename... PortalTs>
Functor<typename std::decay<PortalTs>::type...> CreateFunctor(PortalTs&&... portals) const
{
VTKM_STATIC_ASSERT(sizeof...(PortalTs) == 3);
return { std::forward<PortalTs>(portals)... };
}
};
// Decorator implementation that demonstrates how to create functors that
// hold custom state. Here, the functors have a customizable Operation
// member.
//
// This implementation is used to create a read-only ArrayHandleDecorator
// that combines the values in two other ArrayHandles using an arbitrary
// binary operation (e.g. vtkm::Maximum, vtkm::Add, etc).
template <typename ValueType, typename OperationType>
struct BinaryOperationDecorImpl
{
OperationType Operation;
// The functor use to read values. Note that it holds extra state in
// addition to the portals.
template <typename Portal1Type, typename Portal2Type>
struct Functor
{
Portal1Type Portal1;
Portal2Type Portal2;
OperationType Operation;
VTKM_EXEC_CONT
ValueType operator()(vtkm::Id idx) const
{
return this->Operation(static_cast<ValueType>(this->Portal1.Get(idx)),
static_cast<ValueType>(this->Portal2.Get(idx)));
}
};
// A non-variadic example of a factory function to produce a functor. This
// is where the extra state is passed into the functor.
template <typename P1T, typename P2T>
Functor<P1T, P2T> CreateFunctor(P1T p1, P2T p2) const
{
return { p1, p2, this->Operation };
}
};
// Decorator implementation that reverses the ScanExtended operation.
//
// The resulting ArrayHandleDecorator will take an array produced by the
// ScanExtended algorithm and return the original ScanExtended input.
//
// Some interesting things about this:
// - The ArrayHandleDecorator's ValueType will not be the same as the
// ScanPortal's ValueType. The Decorator ValueType is determined by the
// return type of Functor::operator().
// - The ScanPortal has more values than the ArrayHandleDecorator. The
// number of values the ArrayHandleDecorator should hold is set during
// construction and may differ from the arrays it holds.
template <typename ValueType>
struct ScanExtendedToNumIndicesDecorImpl
{
template <typename ScanPortalType>
struct Functor
{
ScanPortalType ScanPortal;
VTKM_EXEC_CONT
ValueType operator()(vtkm::Id idx) const
{
return static_cast<ValueType>(this->ScanPortal.Get(idx + 1) - this->ScanPortal.Get(idx));
}
};
template <typename ScanPortalType>
Functor<ScanPortalType> CreateFunctor(ScanPortalType portal) const
{
return { portal };
}
};
template <typename ValueType>
void InversionTest() const
{
auto ah1 = vtkm::cont::make_ArrayHandleCounting(ValueType{ 0 }, ValueType{ 2 }, ARRAY_SIZE);
auto ah2 = vtkm::cont::make_ArrayHandleConstant(ValueType{ ARRAY_SIZE }, ARRAY_SIZE);
vtkm::cont::ArrayHandle<ValueType> ah3;
vtkm::cont::Algorithm::Fill(ah3, ValueType{ ARRAY_SIZE / 2 }, ARRAY_SIZE);
auto ah3Const = vtkm::cont::make_ArrayHandleConstant(ValueType{ ARRAY_SIZE / 2 }, ARRAY_SIZE);
{ // Has a writable handle and an invertible functor:
auto ahInv =
vtkm::cont::make_ArrayHandleDecorator(ARRAY_SIZE, InvertibleDecorImpl{}, ah1, ah2, ah3);
VTKM_TEST_ASSERT(vtkm::cont::internal::IsWritableArrayHandle<decltype(ahInv)>::value);
}
{ // Has no writable handles and an invertible functor:
auto ahNInv = vtkm::cont::make_ArrayHandleDecorator(
ARRAY_SIZE, InvertibleDecorImpl{}, ah1, ah2, ah3Const);
VTKM_TEST_ASSERT(!vtkm::cont::internal::IsWritableArrayHandle<decltype(ahNInv)>::value);
}
{ // Has writable handles, but the functor cannot be inverted:
auto ahNInv =
vtkm::cont::make_ArrayHandleDecorator(ARRAY_SIZE, NonInvertibleDecorImpl{}, ah1, ah2, ah3);
VTKM_TEST_ASSERT(!vtkm::cont::internal::IsWritableArrayHandle<decltype(ahNInv)>::value);
}
{ // Has no writable handles and the functor cannot be inverted:
auto ahNInv = vtkm::cont::make_ArrayHandleDecorator(
ARRAY_SIZE, NonInvertibleDecorImpl{}, ah1, ah2, ah3Const);
VTKM_TEST_ASSERT(!vtkm::cont::internal::IsWritableArrayHandle<decltype(ahNInv)>::value);
}
{ // Test reading/writing to an invertible handle:
// Copy ah3 since we'll be modifying it:
vtkm::cont::ArrayHandle<ValueType> ah3Copy;
vtkm::cont::ArrayCopy(ah3, ah3Copy);
auto ahDecor =
vtkm::cont::make_ArrayHandleDecorator(ARRAY_SIZE, InvertibleDecorImpl{}, ah1, ah2, ah3Copy);
{
auto portalDecor = ahDecor.GetPortalConstControl();
VTKM_TEST_ASSERT(ahDecor.GetNumberOfValues() == ARRAY_SIZE);
VTKM_TEST_ASSERT(portalDecor.GetNumberOfValues() == ARRAY_SIZE);
VTKM_TEST_ASSERT(portalDecor.Get(0) == ValueType{ 23 });
VTKM_TEST_ASSERT(portalDecor.Get(1) == ValueType{ 21 });
VTKM_TEST_ASSERT(portalDecor.Get(2) == ValueType{ 19 });
VTKM_TEST_ASSERT(portalDecor.Get(3) == ValueType{ 17 });
VTKM_TEST_ASSERT(portalDecor.Get(4) == ValueType{ 15 });
VTKM_TEST_ASSERT(portalDecor.Get(5) == ValueType{ 15 });
VTKM_TEST_ASSERT(portalDecor.Get(6) == ValueType{ 15 });
VTKM_TEST_ASSERT(portalDecor.Get(7) == ValueType{ 15 });
VTKM_TEST_ASSERT(portalDecor.Get(8) == ValueType{ 15 });
VTKM_TEST_ASSERT(portalDecor.Get(9) == ValueType{ 15 });
}
// Copy a constant array into the decorator. This should modify ah3Copy.
vtkm::cont::ArrayCopy(vtkm::cont::make_ArrayHandleConstant(ValueType{ 25 }, ARRAY_SIZE),
ahDecor);
{ // Accessing portal should give all 25s:
auto portalDecor = ahDecor.GetPortalConstControl();
VTKM_TEST_ASSERT(ahDecor.GetNumberOfValues() == ARRAY_SIZE);
VTKM_TEST_ASSERT(portalDecor.GetNumberOfValues() == ARRAY_SIZE);
VTKM_TEST_ASSERT(portalDecor.Get(0) == ValueType{ 25 });
VTKM_TEST_ASSERT(portalDecor.Get(1) == ValueType{ 25 });
VTKM_TEST_ASSERT(portalDecor.Get(2) == ValueType{ 25 });
VTKM_TEST_ASSERT(portalDecor.Get(3) == ValueType{ 25 });
VTKM_TEST_ASSERT(portalDecor.Get(4) == ValueType{ 25 });
VTKM_TEST_ASSERT(portalDecor.Get(5) == ValueType{ 25 });
VTKM_TEST_ASSERT(portalDecor.Get(6) == ValueType{ 25 });
VTKM_TEST_ASSERT(portalDecor.Get(7) == ValueType{ 25 });
VTKM_TEST_ASSERT(portalDecor.Get(8) == ValueType{ 25 });
VTKM_TEST_ASSERT(portalDecor.Get(9) == ValueType{ 25 });
}
{ // ah3Copy should have updated values:
auto portalAH3Copy = ah3Copy.GetPortalConstControl();
VTKM_TEST_ASSERT(ahDecor.GetNumberOfValues() == ARRAY_SIZE);
VTKM_TEST_ASSERT(portalAH3Copy.GetNumberOfValues() == ARRAY_SIZE);
VTKM_TEST_ASSERT(portalAH3Copy.Get(0) == ValueType{ 15 });
VTKM_TEST_ASSERT(portalAH3Copy.Get(1) == ValueType{ 15 });
VTKM_TEST_ASSERT(portalAH3Copy.Get(2) == ValueType{ 15 });
VTKM_TEST_ASSERT(portalAH3Copy.Get(3) == ValueType{ 7 });
VTKM_TEST_ASSERT(portalAH3Copy.Get(4) == ValueType{ 9 });
VTKM_TEST_ASSERT(portalAH3Copy.Get(5) == ValueType{ 11 });
VTKM_TEST_ASSERT(portalAH3Copy.Get(6) == ValueType{ 13 });
VTKM_TEST_ASSERT(portalAH3Copy.Get(7) == ValueType{ 15 });
VTKM_TEST_ASSERT(portalAH3Copy.Get(8) == ValueType{ 15 });
VTKM_TEST_ASSERT(portalAH3Copy.Get(9) == ValueType{ 15 });
}
}
}
template <typename ValueType, typename OperationType>
void BinaryOperatorTest() const
{
auto ahCount = vtkm::cont::make_ArrayHandleCounting(ValueType{ 0 }, ValueType{ 1 }, ARRAY_SIZE);
auto ahConst = vtkm::cont::make_ArrayHandleConstant(ValueType{ ARRAY_SIZE / 2 }, ARRAY_SIZE);
const OperationType op;
BinaryOperationDecorImpl<ValueType, OperationType> impl{ op };
auto decorArray = vtkm::cont::make_ArrayHandleDecorator(ARRAY_SIZE, impl, ahCount, ahConst);
{
auto decorPortal = decorArray.GetPortalConstControl();
auto countPortal = ahCount.GetPortalConstControl();
auto constPortal = ahConst.GetPortalConstControl();
for (vtkm::Id i = 0; i < ARRAY_SIZE; ++i)
{
VTKM_TEST_ASSERT(decorPortal.Get(i) == op(countPortal.Get(i), constPortal.Get(i)));
}
}
vtkm::cont::ArrayHandle<ValueType> copiedInExec;
vtkm::cont::ArrayCopy(decorArray, copiedInExec);
{
auto copiedPortal = copiedInExec.GetPortalConstControl();
auto countPortal = ahCount.GetPortalConstControl();
auto constPortal = ahConst.GetPortalConstControl();
for (vtkm::Id i = 0; i < ARRAY_SIZE; ++i)
{
VTKM_TEST_ASSERT(copiedPortal.Get(i) == op(countPortal.Get(i), constPortal.Get(i)));
}
}
}
template <typename ValueType>
void ScanExtendedToNumIndicesTest() const
{
auto numIndicesOrig =
vtkm::cont::make_ArrayHandleCounting(ValueType{ 0 }, ValueType{ 1 }, ARRAY_SIZE);
vtkm::cont::ArrayHandle<vtkm::Id> scan;
vtkm::cont::Algorithm::ScanExtended(vtkm::cont::make_ArrayHandleCast<vtkm::Id>(numIndicesOrig),
scan);
// Some interesting things to notice:
// - `numIndicesDecor` will have `ARRAY_SIZE` entries, while `scan` has
// `ARRAY_SIZE + 1`.
// - `numIndicesDecor` uses the current function scope `ValueType`, since
// that is what the functor from the implementation class returns. `scan`
// uses `vtkm::Id`.
auto numIndicesDecor = vtkm::cont::make_ArrayHandleDecorator(
ARRAY_SIZE, ScanExtendedToNumIndicesDecorImpl<ValueType>{}, scan);
{
auto origPortal = numIndicesOrig.GetPortalConstControl();
auto decorPortal = numIndicesDecor.GetPortalConstControl();
VTKM_STATIC_ASSERT(VTKM_PASS_COMMAS(
std::is_same<decltype(origPortal.Get(0)), decltype(decorPortal.Get(0))>::value));
VTKM_TEST_ASSERT(origPortal.GetNumberOfValues() == decorPortal.GetNumberOfValues());
for (vtkm::Id i = 0; i < origPortal.GetNumberOfValues(); ++i)
{
VTKM_TEST_ASSERT(origPortal.Get(i) == decorPortal.Get(i));
}
}
}
template <typename ValueType>
void operator()(const ValueType) const
{
InversionTest<ValueType>();
BinaryOperatorTest<ValueType, vtkm::Maximum>();
BinaryOperatorTest<ValueType, vtkm::Minimum>();
BinaryOperatorTest<ValueType, vtkm::Add>();
BinaryOperatorTest<ValueType, vtkm::Subtract>();
BinaryOperatorTest<ValueType, vtkm::Multiply>();
ScanExtendedToNumIndicesTest<ValueType>();
}
};
void TestArrayHandleDecorator()
{
vtkm::testing::Testing::TryTypes(DecoratorTests{}, vtkm::TypeListTagScalarAll{});
}
} // anonymous namespace
int UnitTestArrayHandleDecorator(int argc, char* argv[])
{
return vtkm::cont::testing::Testing::Run(TestArrayHandleDecorator, argc, argv);
}

@ -13,8 +13,9 @@
#include <vtkm/cont/ArrayHandleExtrudeCoords.h>
#include <vtkm/cont/CellSetExtrude.h>
#include <vtkm/cont/testing/Testing.h>
#include <vtkm/filter/CellAverage.h>
#include <vtkm/filter/PointAverage.h>
#include <vtkm/filter/PointAverage.hxx>
#include <vtkm/filter/PolicyExtrude.h>
namespace
@ -143,7 +144,7 @@ int TestCellSetExtrude()
try
{
avg.SetActiveField("cfield");
auto result = avg.Execute(dataset, PolicyExtrude{});
auto result = avg.Execute(dataset, vtkm::filter::PolicyExtrude{});
VTKM_TEST_ASSERT(result.HasPointField("cfield"), "filter resulting dataset should be valid");
}
catch (const vtkm::cont::Error& err)

@ -0,0 +1,76 @@
//============================================================================
// Copyright (c) Kitware, Inc.
// All rights reserved.
// See LICENSE.txt for details.
//
// This software is distributed WITHOUT ANY WARRANTY; without even
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the above copyright notice for more information.
//============================================================================
#include <vtkm/cont/Error.h>
#include <vtkm/cont/ErrorBadValue.h>
#include <vtkm/cont/Logging.h>
#include <vtkm/cont/testing/Testing.h>
namespace
{
void RecursiveFunction(int recurse)
{
if (recurse < 5)
{
RecursiveFunction(++recurse);
}
else
{
throw vtkm::cont::ErrorBadValue("Too much recursion");
}
}
void ValidateError(const vtkm::cont::Error& error)
{
std::string message = "Too much recursion";
std::string stackTrace = error.GetStackTrace();
std::stringstream stackTraceStream(stackTrace);
std::string tmp;
size_t count = 0;
while (std::getline(stackTraceStream, tmp))
{
count++;
}
// StackTrace may be unavailable on certain Devices
if (stackTrace == "(Stack trace unavailable)")
{
VTKM_TEST_ASSERT(count == 1, "Logging disabled, stack trace shouldn't be available");
}
else
{
std::string assert_msg = "StackTrace did not recurse: (" + std::to_string(count) + " <= 5)";
VTKM_TEST_ASSERT(count > 5, assert_msg);
}
VTKM_TEST_ASSERT(test_equal(message, error.GetMessage()), "Message was incorrect");
VTKM_TEST_ASSERT(test_equal(message + "\n" + stackTrace, std::string(error.what())),
"what() was incorrect");
}
void DoErrorTest()
{
VTKM_LOG_S(vtkm::cont::LogLevel::Info, "Check base error messages");
try
{
RecursiveFunction(0);
}
catch (const vtkm::cont::Error& e)
{
ValidateError(e);
}
}
} // anonymous namespace
int UnitTestError(int argc, char* argv[])
{
return vtkm::cont::testing::Testing::Run(DoErrorTest, argc, argv);
}

@ -21,6 +21,11 @@
set(headers
CellDiagonalRatioMetric.h
CellEdgeRatioMetric.h
CellJacobianMetric.h
TypeOfCellHexahedral.h
TypeOfCellQuadrilateral.h
TypeOfCellTetrahedral.h
TypeOfCellTriangle.h
)

@ -0,0 +1,187 @@
//============================================================================
// Copyright (c) Kitware, Inc.
// All rights reserved.
// See LICENSE.txt for details.
// This software is distributed WITHOUT ANY WARRANTY; without even
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the above copyright notice for more information.
//
// Copyright 2018 National Technology & Engineering Solutions of Sandia, LLC (NTESS).
// Copyright 2018 UT-Battelle, LLC.
// Copyright 2018 Los Alamos National Security.
//
// Under the terms of Contract DE-NA0003525 with NTESS,
// the U.S. Government retains certain rights in this software.
//
// Under the terms of Contract DE-AC52-06NA25396 with Los Alamos National
// Laboratory (LANL), the U.S. Government retains certain rights in
// this software.
//============================================================================
#ifndef vtk_m_exec_cellmetrics_Jacobian_h
#define vtk_m_exec_cellmetrics_Jacobian_h
/*
* Mesh quality metric functions that computes the Jacobian of mesh cells.
*
* These metric computations are adapted from the VTK implementation of the Verdict library,
* which provides a set of mesh/cell metrics for evaluating the geometric qualities of regions
* of mesh spaces.
*
* See: The Verdict Library Reference Manual (for per-cell-type metric formulae)
* See: vtk/ThirdParty/verdict/vtkverdict (for VTK code implementation of this metric)
*/
#include "TypeOfCellHexahedral.h"
#include "TypeOfCellQuadrilateral.h"
#include "TypeOfCellTetrahedral.h"
#include "TypeOfCellTriangle.h"
#include "vtkm/CellShape.h"
#include "vtkm/CellTraits.h"
#include "vtkm/VecTraits.h"
#include "vtkm/VectorAnalysis.h"
#include "vtkm/exec/FunctorBase.h"
#define UNUSED(expr) (void)(expr);
namespace vtkm
{
namespace exec
{
namespace cellmetrics
{
// ========================= Unsupported cells ==================================
// By default, cells return the metric 0.0 unless the shape type template is specialized below.
template <typename OutType, typename PointCoordVecType, typename CellShapeType>
VTKM_EXEC OutType CellJacobianMetric(const vtkm::IdComponent& numPts,
const PointCoordVecType& pts,
CellShapeType shape,
const vtkm::exec::FunctorBase&)
{
UNUSED(numPts);
UNUSED(pts);
UNUSED(shape);
return OutType(0.0);
}
// ========================= 2D cells ==================================
// Compute the Jacobian of a quadrilateral.
// Formula: min{Jacobian at each vertex}
// Equals 1 for a unit square
// Acceptable range: [0,FLOAT_MAX]
// Normal range: [0,FLOAT_MAX]
// Full range: [FLOAT_MIN,FLOAT_MAX]
template <typename OutType, typename PointCoordVecType>
VTKM_EXEC OutType CellJacobianMetric(const vtkm::IdComponent& numPts,
const PointCoordVecType& pts,
vtkm::CellShapeTagQuad,
const vtkm::exec::FunctorBase& worklet)
{
if (numPts != 4)
{
worklet.RaiseError("Jacobian metric(quad) requires 4 points.");
return OutType(0.0);
}
using Scalar = OutType;
using CollectionOfPoints = PointCoordVecType;
using Vector = typename PointCoordVecType::ComponentType;
const Scalar alpha0 = GetQuadAlpha0<Scalar, Vector, CollectionOfPoints>(pts);
const Scalar alpha1 = GetQuadAlpha1<Scalar, Vector, CollectionOfPoints>(pts);
const Scalar alpha2 = GetQuadAlpha2<Scalar, Vector, CollectionOfPoints>(pts);
const Scalar alpha3 = GetQuadAlpha3<Scalar, Vector, CollectionOfPoints>(pts);
const Scalar q = vtkm::Min(alpha0, vtkm::Min(alpha1, vtkm::Min(alpha2, alpha3)));
return q;
}
// ============================= 3D Volume cells ==================================
// Compute the Jacobian of a hexahedron.
// Formula: min{ {Alpha_i for i in 1..7}, Alpha_8/64}
// -Alpha_i -> Jacobian determinant at respective vertex
// -Alpha_8 -> Jacobian at center
// Equals 1 for a unit cube
// Acceptable Range: [0, FLOAT_MAX]
// Normal Range: [0, FLOAT_MAX]
// Full range: [FLOAT_MIN ,FLOAT_MAX]
template <typename OutType, typename PointCoordVecType>
VTKM_EXEC OutType CellJacobianMetric(const vtkm::IdComponent& numPts,
const PointCoordVecType& pts,
vtkm::CellShapeTagHexahedron,
const vtkm::exec::FunctorBase& worklet)
{
if (numPts != 8)
{
worklet.RaiseError("Jacobian metric(hexahedron) requires 8 points.");
return OutType(0.0);
}
using Scalar = OutType;
using CollectionOfPoints = PointCoordVecType;
using Vector = typename PointCoordVecType::ComponentType;
const Scalar alpha0 = GetHexAlphai<Scalar, Vector, CollectionOfPoints>(pts, vtkm::Id(0));
const Scalar alpha1 = GetHexAlphai<Scalar, Vector, CollectionOfPoints>(pts, vtkm::Id(1));
const Scalar alpha2 = GetHexAlphai<Scalar, Vector, CollectionOfPoints>(pts, vtkm::Id(2));
const Scalar alpha3 = GetHexAlphai<Scalar, Vector, CollectionOfPoints>(pts, vtkm::Id(3));
const Scalar alpha4 = GetHexAlphai<Scalar, Vector, CollectionOfPoints>(pts, vtkm::Id(4));
const Scalar alpha5 = GetHexAlphai<Scalar, Vector, CollectionOfPoints>(pts, vtkm::Id(5));
const Scalar alpha6 = GetHexAlphai<Scalar, Vector, CollectionOfPoints>(pts, vtkm::Id(6));
const Scalar alpha7 = GetHexAlphai<Scalar, Vector, CollectionOfPoints>(pts, vtkm::Id(7));
const Scalar alpha8 = GetHexAlphai<Scalar, Vector, CollectionOfPoints>(pts, vtkm::Id(8));
const Scalar alpha8Div64 = alpha8 / Scalar(64.0);
const Scalar q = vtkm::Min(
alpha0,
vtkm::Min(
alpha1,
vtkm::Min(
alpha2,
vtkm::Min(
alpha3,
vtkm::Min(alpha4,
vtkm::Min(alpha5, vtkm::Min(alpha6, vtkm::Min(alpha7, alpha8Div64))))))));
return q;
}
// Compute the Jacobian of a tetrahedron.
// Formula: (L2 x L0) * L3
// Equals Sqrt(2) / 2 for unit equilateral tetrahedron
// Acceptable Range: [0, FLOAT_MAX]
// Normal Range: [0, FLOAT_MAX]
// Full range: [FLOAT_MIN,FLOAT_MAX]
template <typename OutType, typename PointCoordVecType>
VTKM_EXEC OutType CellJacobianMetric(const vtkm::IdComponent& numPts,
const PointCoordVecType& pts,
vtkm::CellShapeTagTetra,
const vtkm::exec::FunctorBase& worklet)
{
if (numPts != 4)
{
worklet.RaiseError("Jacobian metric (tetra) requires 4 points");
return OutType(0.0);
}
using Scalar = OutType;
using CollectionOfPoints = PointCoordVecType;
using Vector = typename PointCoordVecType::ComponentType;
const Vector L0 = GetTetraL0<Scalar, Vector, CollectionOfPoints>(pts);
const Vector L2 = GetTetraL2<Scalar, Vector, CollectionOfPoints>(pts);
const Vector L3 = GetTetraL3<Scalar, Vector, CollectionOfPoints>(pts);
const Scalar q = vtkm::Dot(vtkm::Cross(L2, L0), L3);
return q;
}
} // namespace cellmetrics
} // namespace exec
} // namespace vtkm
#endif // vtk_m_exec_cellmetrics_CellJacobianMetric_h

Some files were not shown because too many files have changed in this diff Show More