Merge branch 'master' of https://gitlab.kitware.com/vtk/vtk-m into add-16-cell-metrics
This commit is contained in:
commit
338b87d9f8
@ -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.
|
||||
|
||||
|
244
docs/changelog/array-handle-decorator.md
Normal file
244
docs/changelog/array-handle-decorator.md
Normal file
@ -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);
|
||||
```
|
16
docs/changelog/dataset_sources.md
Normal file
16
docs/changelog/dataset_sources.md
Normal file
@ -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();
|
||||
```
|
80
docs/changelog/provide-cmake-helper-functions.md
Normal file
80
docs/changelog/provide-cmake-helper-functions.md
Normal file
@ -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.
|
||||
|
||||
|
||||
|
73
docs/changelog/provide-prebuilt-filters.md
Normal file
73
docs/changelog/provide-prebuilt-filters.md
Normal file
@ -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
|
||||
|
19
vtkm/Types.h
19
vtkm/Types.h
@ -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
|
||||
|
890
vtkm/cont/ArrayHandleDecorator.h
Normal file
890
vtkm/cont/ArrayHandleDecorator.h
Normal file
@ -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);
|
||||
|
||||
|
402
vtkm/cont/testing/UnitTestArrayHandleDecorator.cxx
Normal file
402
vtkm/cont/testing/UnitTestArrayHandleDecorator.cxx
Normal file
@ -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)
|
||||
|
76
vtkm/cont/testing/UnitTestError.cxx
Normal file
76
vtkm/cont/testing/UnitTestError.cxx
Normal file
@ -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
|
||||
)
|
||||
|
||||
|
||||
|
187
vtkm/exec/cellmetrics/CellJacobianMetric.h
Normal file
187
vtkm/exec/cellmetrics/CellJacobianMetric.h
Normal file
@ -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
Loading…
Reference in New Issue
Block a user