Add VTK-m User's Guide to source

This is a start of moving the VTK-m User's Guide into the VTK-m source.
This is only the start of the process. There are several goals of this
work.

1. Integrate the documentation into the source code better to better
   keep the code up to date.
2. Move the documentation over to Sphinx so that it can be posted online
   and be more easily linked.
3. Incoporate Doxygen into the guide to keep the documentation
   consistent.
4. Build the user guide examples as part of the VTK-m CI to catch
   compatibility changes quickly.
This commit is contained in:
Kenneth Moreland 2023-07-12 16:05:47 -06:00
parent feee5a2f9d
commit b80b7e2e71
55 changed files with 3111 additions and 29 deletions

1
.gitattributes vendored

@ -8,6 +8,7 @@
data/** filter=lfs diff=lfs merge=lfs -text
/**/data/** filter=lfs diff=lfs merge=lfs -text
/**/images/** filter=lfs diff=lfs merge=lfs -text
*.cmake whitespace=tab-in-indent
*.md whitespace=tab-in-indent whitespace=-blank-at-eol conflict-marker-size=79 -whitespace

395
CMake/FindSphinx.cmake Normal file

@ -0,0 +1,395 @@
# This find module originally created by Jeroen Koekkoek.
# Copyright (c) 2023, Jeroen Koekkoek
#
# This file is covered by a BSD 3-Clause License.
# See https://github.com/k0ekk0ek/cmake-sphinx/blob/master/LICENSE for details.
include(FindPackageHandleStandardArgs)
macro(_Sphinx_find_executable _exe)
string(TOUPPER "${_exe}" _uc)
# sphinx-(build|quickstart)-3 x.x.x
# FIXME: This works on Fedora (and probably most other UNIX like targets).
# Windows targets and PIP installs might need some work.
find_program(
SPHINX_${_uc}_EXECUTABLE
NAMES "sphinx-${_exe}-3" "sphinx-${_exe}" "sphinx-${_exe}.exe")
mark_as_advanced(SPHINX_${_uc}_EXECUTABLE)
if(SPHINX_${_uc}_EXECUTABLE)
execute_process(
COMMAND "${SPHINX_${_uc}_EXECUTABLE}" --version
RESULT_VARIABLE _result
OUTPUT_VARIABLE _output
OUTPUT_STRIP_TRAILING_WHITESPACE)
if(_result EQUAL 0 AND _output MATCHES " v?([0-9]+\\.[0-9]+\\.[0-9]+)$")
set(SPHINX_${_uc}_VERSION "${CMAKE_MATCH_1}")
endif()
if(NOT TARGET Sphinx::${_exe})
add_executable(Sphinx::${_exe} IMPORTED GLOBAL)
set_target_properties(Sphinx::${_exe} PROPERTIES
IMPORTED_LOCATION "${SPHINX_${_uc}_EXECUTABLE}")
endif()
set(Sphinx_${_exe}_FOUND TRUE)
else()
set(Sphinx_${_exe}_FOUND FALSE)
endif()
unset(_uc)
endmacro()
macro(_Sphinx_find_module _name _module)
string(TOUPPER "${_name}" _Sphinx_uc)
if(SPHINX_PYTHON_EXECUTABLE)
execute_process(
COMMAND ${SPHINX_PYTHON_EXECUTABLE} -m ${_module} --version
RESULT_VARIABLE _result
OUTPUT_VARIABLE _output
OUTPUT_STRIP_TRAILING_WHITESPACE
ERROR_QUIET)
if(_result EQUAL 0)
if(_output MATCHES " v?([0-9]+\\.[0-9]+\\.[0-9]+)$")
set(SPHINX_${_Sphinx_uc}_VERSION "${CMAKE_MATCH_1}")
endif()
if(NOT TARGET Sphinx::${_name})
set(SPHINX_${_Sphinx_uc}_EXECUTABLE "${SPHINX_PYTHON_EXECUTABLE} -m ${_module}")
add_executable(Sphinx::${_name} IMPORTED GLOBAL)
set_target_properties(Sphinx::${_name} PROPERTIES
IMPORTED_LOCATION "${SPHINX_PYTHON_EXECUTABLE}")
endif()
set(Sphinx_${_name}_ARGS -m ${_module})
set(Sphinx_${_name}_FOUND TRUE)
else()
set(Sphinx_${_name}_FOUND FALSE)
endif()
else()
set(Sphinx_${_name}_FOUND FALSE)
endif()
unset(_Sphinx_uc)
endmacro()
macro(_Sphinx_find_extension _ext)
if(SPHINX_PYTHON_EXECUTABLE)
execute_process(
COMMAND ${SPHINX_PYTHON_EXECUTABLE} -c "import ${_ext}"
RESULT_VARIABLE _result)
if(_result EQUAL 0)
set(Sphinx_${_ext}_FOUND TRUE)
else()
set(Sphinx_${_ext}_FOUND FALSE)
endif()
endif()
endmacro()
#
# Find sphinx-build and sphinx-quickstart.
#
# Find sphinx-build shim.
_Sphinx_find_executable(build)
if(SPHINX_BUILD_EXECUTABLE)
# Find sphinx-quickstart shim.
_Sphinx_find_executable(quickstart)
# Locate Python executable
if(CMAKE_HOST_WIN32)
# script-build on Windows located under (when PIP is used):
# C:/Program Files/PythonXX/Scripts
# C:/Users/username/AppData/Roaming/Python/PythonXX/Sripts
#
# Python modules are installed under:
# C:/Program Files/PythonXX/Lib
# C:/Users/username/AppData/Roaming/Python/PythonXX/site-packages
#
# To verify a given module is installed, use the Python base directory
# and test if either Lib/module.py or site-packages/module.py exists.
get_filename_component(_Sphinx_directory "${SPHINX_BUILD_EXECUTABLE}" DIRECTORY)
get_filename_component(_Sphinx_directory "${_Sphinx_directory}" DIRECTORY)
if(EXISTS "${_Sphinx_directory}/python.exe")
set(SPHINX_PYTHON_EXECUTABLE "${_Sphinx_directory}/python.exe")
endif()
unset(_Sphinx_directory)
else()
file(READ "${SPHINX_BUILD_EXECUTABLE}" _Sphinx_script)
if(_Sphinx_script MATCHES "^#!([^\n]+)")
string(STRIP "${CMAKE_MATCH_1}" _Sphinx_shebang)
if(EXISTS "${_Sphinx_shebang}")
set(SPHINX_PYTHON_EXECUTABLE "${_Sphinx_shebang}")
endif()
endif()
unset(_Sphinx_script)
unset(_Sphinx_shebang)
endif()
endif()
if(NOT SPHINX_PYTHON_EXECUTABLE)
# Python executable cannot be extracted from shim shebang or path if e.g.
# virtual environments are used, fallback to find package. Assume the
# correct installation is found, the setup is probably broken in more ways
# than one otherwise.
find_package(Python3 QUIET COMPONENTS Interpreter)
if(TARGET Python3::Interpreter)
set(SPHINX_PYTHON_EXECUTABLE ${Python3_EXECUTABLE})
# Revert to "python -m sphinx" if shim cannot be found.
if(NOT SPHINX_BUILD_EXECUTABLE)
_Sphinx_find_module(build sphinx)
_Sphinx_find_module(quickstart sphinx.cmd.quickstart)
endif()
endif()
endif()
#
# Verify components are available.
#
if(SPHINX_BUILD_VERSION)
# Breathe is required for Exhale
if("exhale" IN_LIST Sphinx_FIND_COMPONENTS AND NOT
"breathe" IN_LIST Sphinx_FIND_COMPONENTS)
list(APPEND Sphinx_FIND_COMPONENTS "breathe")
endif()
foreach(_Sphinx_component IN LISTS Sphinx_FIND_COMPONENTS)
if(_Sphinx_component STREQUAL "build")
# Do nothing, sphinx-build is always required.
continue()
elseif(_Sphinx_component STREQUAL "quickstart")
# Do nothing, sphinx-quickstart is optional, but looked up by default.
continue()
endif()
_Sphinx_find_extension(${_Sphinx_component})
endforeach()
unset(_Sphinx_component)
#
# Verify both executables are part of the Sphinx distribution.
#
if(SPHINX_QUICKSTART_VERSION AND NOT SPHINX_BUILD_VERSION STREQUAL SPHINX_QUICKSTART_VERSION)
message(FATAL_ERROR "Versions for sphinx-build (${SPHINX_BUILD_VERSION}) "
"and sphinx-quickstart (${SPHINX_QUICKSTART_VERSION}) "
"do not match")
endif()
endif()
find_package_handle_standard_args(
Sphinx
VERSION_VAR SPHINX_BUILD_VERSION
REQUIRED_VARS SPHINX_BUILD_EXECUTABLE SPHINX_BUILD_VERSION
HANDLE_COMPONENTS)
# Generate a conf.py template file using sphinx-quickstart.
#
# sphinx-quickstart allows for quiet operation and a lot of settings can be
# specified as command line arguments, therefore its not required to parse the
# generated conf.py.
function(_Sphinx_generate_confpy _target _cachedir)
if(NOT TARGET Sphinx::quickstart)
message(FATAL_ERROR "sphinx-quickstart is not available, needed by"
"sphinx_add_docs for target ${_target}")
endif()
if(NOT DEFINED SPHINX_PROJECT)
set(SPHINX_PROJECT ${PROJECT_NAME})
endif()
if(NOT DEFINED SPHINX_AUTHOR)
set(SPHINX_AUTHOR "${SPHINX_PROJECT} committers")
endif()
if(NOT DEFINED SPHINX_COPYRIGHT)
string(TIMESTAMP "%Y, ${SPHINX_AUTHOR}" SPHINX_COPYRIGHT)
endif()
if(NOT DEFINED SPHINX_VERSION)
set(SPHINX_VERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}")
endif()
if(NOT DEFINED SPHINX_RELEASE)
set(SPHINX_RELEASE "${PROJECT_VERSION}")
endif()
if(NOT DEFINED SPHINX_LANGUAGE)
set(SPHINX_LANGUAGE "en")
endif()
if(NOT DEFINED SPHINX_MASTER)
set(SPHINX_MASTER "index")
endif()
set(_known_exts autodoc doctest intersphinx todo coverage imgmath mathjax
ifconfig viewcode githubpages)
if(DEFINED SPHINX_EXTENSIONS)
foreach(_ext ${SPHINX_EXTENSIONS})
set(_is_known_ext FALSE)
foreach(_known_ext ${_known_exsts})
if(_ext STREQUAL _known_ext)
set(_opts "${opts} --ext-${_ext}")
set(_is_known_ext TRUE)
break()
endif()
endforeach()
if(NOT _is_known_ext)
if(_exts)
set(_exts "${_exts},${_ext}")
else()
set(_exts "${_ext}")
endif()
endif()
endforeach()
endif()
if(_exts)
set(_exts "--extensions=${_exts}")
endif()
set(_templatedir "${CMAKE_CURRENT_BINARY_DIR}/${_target}.template")
file(MAKE_DIRECTORY "${_templatedir}")
string(REPLACE " " ";" _Sphinx_executable ${SPHINX_QUICKSTART_EXECUTABLE})
execute_process(
COMMAND ${_Sphinx_executable}
-q --no-makefile --no-batchfile
-p "${SPHINX_PROJECT}"
-a "${SPHINX_AUTHOR}"
-v "${SPHINX_VERSION}"
-r "${SPHINX_RELEASE}"
-l "${SPHINX_LANGUAGE}"
--master "${SPHINX_MASTER}"
${_opts} ${_exts} "${_templatedir}"
RESULT_VARIABLE _result
OUTPUT_QUIET)
unset(_Sphinx_executable)
if(_result EQUAL 0 AND EXISTS "${_templatedir}/conf.py")
file(COPY "${_templatedir}/conf.py" DESTINATION "${_cachedir}")
endif()
file(REMOVE_RECURSE "${_templatedir}")
if(NOT _result EQUAL 0 OR NOT EXISTS "${_cachedir}/conf.py")
message(FATAL_ERROR "Sphinx configuration file not generated for "
"target ${_target}")
endif()
endfunction()
function(sphinx_add_docs _target)
set(_opts)
set(_single_opts BUILDER OUTPUT_DIRECTORY SOURCE_DIRECTORY)
set(_multi_opts BREATHE_PROJECTS)
cmake_parse_arguments(_args "${_opts}" "${_single_opts}" "${_multi_opts}" ${ARGN})
unset(SPHINX_BREATHE_PROJECTS)
if(NOT _args_BUILDER)
message(FATAL_ERROR "Sphinx builder not specified for target ${_target}")
elseif(NOT _args_SOURCE_DIRECTORY)
message(FATAL_ERROR "Sphinx source directory not specified for target ${_target}")
else()
if(NOT IS_ABSOLUTE "${_args_SOURCE_DIRECTORY}")
get_filename_component(_sourcedir "${_args_SOURCE_DIRECTORY}" ABSOLUTE)
else()
set(_sourcedir "${_args_SOURCE_DIRECTORY}")
endif()
if(NOT IS_DIRECTORY "${_sourcedir}")
message(FATAL_ERROR "Sphinx source directory '${_sourcedir}' for"
"target ${_target} does not exist")
endif()
endif()
set(_builder "${_args_BUILDER}")
if(_args_OUTPUT_DIRECTORY)
set(_outputdir "${_args_OUTPUT_DIRECTORY}")
else()
set(_outputdir "${CMAKE_CURRENT_BINARY_DIR}/${_target}")
endif()
if(_args_BREATHE_PROJECTS)
if(NOT Sphinx_breathe_FOUND)
message(FATAL_ERROR "Sphinx extension 'breathe' is not available. Needed"
"by sphinx_add_docs for target ${_target}")
endif()
list(APPEND SPHINX_EXTENSIONS breathe)
foreach(_doxygen_target ${_args_BREATHE_PROJECTS})
if(TARGET ${_doxygen_target})
list(APPEND _depends ${_doxygen_target})
# Doxygen targets are supported. Verify that a Doxyfile exists.
get_target_property(_dir ${_doxygen_target} BINARY_DIR)
set(_doxyfile "${_dir}/Doxyfile.${_doxygen_target}")
if(NOT EXISTS "${_doxyfile}")
message(FATAL_ERROR "Target ${_doxygen_target} is not a Doxygen"
"target, needed by sphinx_add_docs for target"
"${_target}")
endif()
# Read the Doxyfile, verify XML generation is enabled and retrieve the
# output directory.
file(READ "${_doxyfile}" _contents)
if(NOT _contents MATCHES "GENERATE_XML *= *YES")
message(FATAL_ERROR "Doxygen target ${_doxygen_target} does not"
"generate XML, needed by sphinx_add_docs for"
"target ${_target}")
elseif(_contents MATCHES "OUTPUT_DIRECTORY *= *([^ ][^\n]*)")
string(STRIP "${CMAKE_MATCH_1}" _dir)
set(_name "${_doxygen_target}")
set(_dir "${_dir}/xml")
else()
message(FATAL_ERROR "Cannot parse Doxyfile generated by Doxygen"
"target ${_doxygen_target}, needed by"
"sphinx_add_docs for target ${_target}")
endif()
elseif(_doxygen_target MATCHES "([^: ]+) *: *(.*)")
set(_name "${CMAKE_MATCH_1}")
string(STRIP "${CMAKE_MATCH_2}" _dir)
endif()
if(_name AND _dir)
if(_breathe_projects)
set(_breathe_projects "${_breathe_projects}, \"${_name}\": \"${_dir}\"")
else()
set(_breathe_projects "\"${_name}\": \"${_dir}\"")
endif()
if(NOT _breathe_default_project)
set(_breathe_default_project "${_name}")
endif()
endif()
endforeach()
endif()
set(_cachedir "${CMAKE_CURRENT_BINARY_DIR}/${_target}.cache")
file(MAKE_DIRECTORY "${_cachedir}")
if(EXISTS "${_sourcedir}/_static")
file(COPY "${_sourcedir}/_static" DESTINATION "${_cachedir}")
endif()
if(EXISTS "${_sourcedir}/_templates")
file(COPY "${_sourcedir}/_templates" DESTINATION "${_cachedir}")
endif()
if(EXISTS "${_sourcedir}/conf.py")
configure_file("${_sourcedir}/conf.py" "${_cachedir}/conf.py" @ONLY)
else()
_Sphinx_generate_confpy(${_target} "${_cachedir}")
endif()
if(_breathe_projects)
file(APPEND "${_cachedir}/conf.py"
"\nbreathe_projects = { ${_breathe_projects} }"
"\nbreathe_default_project = '${_breathe_default_project}'")
endif()
string(REPLACE " " ";" _Sphinx_executable ${SPHINX_BUILD_EXECUTABLE})
add_custom_target(
${_target} ALL
COMMAND ${_Sphinx_executable}
-b ${_builder}
-d "${CMAKE_CURRENT_BINARY_DIR}/${_target}.cache/_doctrees"
-c "${CMAKE_CURRENT_BINARY_DIR}/${_target}.cache"
"${_sourcedir}"
"${_outputdir}"
COMMENT "Building ${_target} Sphinx document"
DEPENDS ${_depends})
unset(_Sphinx_executable)
endfunction()

@ -221,7 +221,7 @@ function(_vtkm_module_parse_module_file module_file name_var)
# Parse module file as arguments to a function
set(options NO_TESTING)
set(oneValueArgs NAME)
set(oneValueArgs NAME TESTING_DIR)
set(multiValueArgs
GROUPS DEPENDS PRIVATE_DEPENDS OPTIONAL_DEPENDS TEST_DEPENDS TEST_OPTIONAL_DEPENDS)
cmake_parse_arguments(_vtkm_module
@ -592,10 +592,16 @@ function(_vtkm_modules_try_build_tests target_module)
endif()
endforeach()
vtkm_module_get_property(testing_subdir ${target_module} TESTING_DIR)
if(NOT testing_subdir)
set(testing_subdir "testing")
endif()
vtkm_module_get_property(src_directory ${target_module} DIRECTORY)
file(RELATIVE_PATH rel_directory "${VTKm_SOURCE_DIR}" "${src_directory}")
set(vtkm_module_current_test ${target_module})
add_subdirectory("${src_directory}/testing" "${VTKm_BINARY_DIR}/${rel_directory}/testing")
add_subdirectory("${src_directory}/${testing_subdir}"
"${VTKm_BINARY_DIR}/${rel_directory}/${testing_subdir}")
set(vtkm_module_current_test)
endfunction()

@ -294,7 +294,7 @@ MAN_LINKS = NO
# configuration options related to the XML output
#---------------------------------------------------------------------------
GENERATE_XML = NO
GENERATE_XML = YES
XML_OUTPUT = xml

@ -119,6 +119,14 @@ mark_as_advanced(VTKm_ENABLE_TESTING_LIBRARY)
cmake_dependent_option(VTKm_ENABLE_ANARI "Enable ANARI interop support"
OFF "VTKm_ENABLE_RENDERING" OFF)
# If you are building Doxygen, you also have the option to build the User's Guide with Sphinx
cmake_dependent_option(VTKm_ENABLE_USERS_GUIDE
"Build User's Guide with Sphinx"
ON
"VTKm_ENABLE_DOCUMENTATION"
OFF
)
# We may want to make finer controls on whether libraries/modules get built.
# VTK uses the concept of groups for its modules
vtkm_option(VTKm_BUILD_ALL_LIBRARIES
@ -306,28 +314,6 @@ include(CheckTypeSize)
check_type_size(long VTKm_SIZE_LONG BUILTIN_TYPES_ONLY)
check_type_size("long long" VTKm_SIZE_LONG_LONG BUILTIN_TYPES_ONLY)
#-----------------------------------------------------------------------------
# Add subdirectories
add_subdirectory(vtkmstd)
#-----------------------------------------------------------------------------
# Process modules
vtkm_modules_scan(
SCAN_DIRECTORIES vtkm benchmarking
PROVIDED_MODULES all_modules
)
vtkm_modules_build(
PROVIDED_MODULES ${all_modules}
WANT_BY_DEFAULT ${VTKm_BUILD_ALL_LIBRARIES}
WANT_BY_DEFAULT_REASON "VTKm_BUILD_ALL_LIBRARIES is `${VTKm_BUILD_ALL_LIBRARIES}`"
)
#-----------------------------------------------------------------------------
# Build documentation
if (VTKm_ENABLE_DOCUMENTATION)
include(VTKmBuildDocumentation)
endif()
#-----------------------------------------------------------------------------
# Ready files for find_package
include(CMakePackageConfigHelpers)
@ -349,6 +335,28 @@ write_basic_package_version_file(
VERSION ${VTKm_VERSION}
COMPATIBILITY ExactVersion )
#-----------------------------------------------------------------------------
# Add subdirectories
add_subdirectory(vtkmstd)
#-----------------------------------------------------------------------------
# Process modules
vtkm_modules_scan(
SCAN_DIRECTORIES vtkm benchmarking docs
PROVIDED_MODULES all_modules
)
vtkm_modules_build(
PROVIDED_MODULES ${all_modules}
WANT_BY_DEFAULT ${VTKm_BUILD_ALL_LIBRARIES}
WANT_BY_DEFAULT_REASON "VTKm_BUILD_ALL_LIBRARIES is `${VTKm_BUILD_ALL_LIBRARIES}`"
)
#-----------------------------------------------------------------------------
# Build documentation
if (VTKm_ENABLE_DOCUMENTATION)
include(VTKmBuildDocumentation)
endif()
#-----------------------------------------------------------------------------
# Create makefile/package files for projects not using CMake

@ -32,7 +32,7 @@ met:
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
@ -48,6 +48,7 @@ The following files and directories come from third parties. Check the
contents of these for details on the specifics of their respective
licenses.
- - - - - - - - - - - - - - - - - - - - - - - - do not remove this line
CMake/FindSphinx.cmake
CMake/FindTBB.cmake
Utilities
vtkm/cont/tbb/internal/parallel_sort.h

@ -102,6 +102,8 @@ arguments for that option. The following options can be defined in a
named `testing`, which will build any necessary testing executables and
add ctest tests. If this option is given, no tests are added. (Note,
modules generally should have tests.)
* `TESTING_DIR`: Specify the name of the testing subdirectory. If not
provided, `testing` is used.
A `vtkm.module` file may also have comments. Everything between a `#` and
the end of the line will be ignored.

@ -0,0 +1,15 @@
# Added VTK-m's user guide into the source code
The VTK-m User's Guide is being transitioned into the VTK-m source code.
The implementation of the guide is being converted from LaTeX to
ReStructuredText text to be built by Sphinx. There are several goals of
this change.
1. Integrate the documentation into the source code better to better
keep the code up to date.
2. Move the documentation over to Sphinx so that it can be posted online
and be more easily linked.
3. Incoporate Doxygen into the guide to keep the documentation
consistent.
4. Build the user guide examples as part of the VTK-m CI to catch
compatibility changes quickly.

@ -0,0 +1,46 @@
##============================================================================
## 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.
##============================================================================
# This module is always loaded so that the example code is compiled as part
# of the test build. However, we only really want to build the document if
# VTKm_ENABLE_USERS_GUIDE is set.
if (NOT VTKm_ENABLE_USERS_GUIDE)
return()
endif()
set(sphinx_docs
index.rst
)
find_package(Sphinx)
if (NOT Sphinx_FOUND)
message(FATAL_ERROR
"Could not find Sphinx to build User's Guide. If you want to compile Doxygen without the User's Guide, turn off VTKm_ENABLE_USERS_GUIDE.")
endif()
# Configuration used in conf.py.
set(doxygen_xml_output_dir "${VTKm_BINARY_DIR}/docs/doxygen/xml")
set(example_directory "${CMAKE_CURRENT_SOURCE_DIR}/examples")
sphinx_add_docs(VTKmUsersGuideHTML
BUILDER html
SOURCE_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/html
CONF_FILE conf.py
)
add_dependencies(VTKmUsersGuideHTML VTKmDoxygenDocs)
sphinx_add_docs(VTKmUsersGuideLaTeX
BUILDER latex
SOURCE_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/latex
CONF_FILE conf.py
)
add_dependencies(VTKmUsersGuideLaTeX VTKmDoxygenDocs)

278
docs/users-guide/README.md Normal file

@ -0,0 +1,278 @@
# VTK-m User's Guide Source
This directory contains the source for building the VTK-m User's Guide. The
document is written for the [Sphinx](https://www.sphinx-doc.org/en/master/)
document generator.
## Building the documentation
To build the document, you will need the following installed on your
system.
* [Doxygen] - Processes source code to pull out documentation.
* [Sphinx] - Processes [reStructuredText] to build HTML and LaTeX
formatted documents.
* [RTD Theme] - We use the Sphinx Read the Docs theme for formatting the
generated HTML. The build will fail without this installed.
* [Sphinx CMake Domain] Sphinx does not support documenting CMake
elements out of the box. This extension provides that support.
* [Breathe] - Forms a bridge betweein Doxygen and Sphinx to allow the
Sphinx reStructuredTest to include documentation extracted by Doxygen.
To enable document generation, you first must turn on the CMake option
`VTKm_ENABLE_DOCUMENTATION`, which turns on the Doxygen documentation. With
that on, you can then turn on the `VTKm_ENABLE_USERS_GUIDE` CMake option.
The documentation will be built into HTML format in the
`docs/users-guide/html` directory in the build. It will also build LaTeX
files in `docs/users-guide/latex`. It will come with a `Makefile` that can
be used to generate a pdf form (given the proper LaTeX compiler).
## Features of the documents
The VTK-m User's Guide is built as a standard [Sphinx] project. However,
there are some features that writers should be aware of.
### Writing credit
Kenneth Moreland is the main author of this document. If you have made a
contribution, you can credit yourself in the `Contributors` section of
[acknowledgements.rst].
### Provided substitutions
The Sphinx configuration provides some convenient substitutions that can be
used throughout the document.
* `|VTKm|` This should be used whenever `VTK-m` is referenced. The
substitution contains formatting for the word.
### Expanded directives
This reStructuredText is build with some extended directives.
#### Info boxes
Two new "admonition" boxes are supported: `didyouknow` and `commonerrors`.
It is encouraged to use these boxes to highlight interesting features or
common gotchas. These are use like other tip boxes.
``` restructuredtext
.. didyouknow::
In this guide we periodically use these **Did you know?** boxes to
provide additional information related to the topic at hand.
.. commonerrors::
**Common Errors** blocks are used to highlight some of the common
problems or complications you might encounter when dealing with the
topic of discussion.
```
### Section references
It is desired for the VTK-m User's Guide to be available both online as web
pages and as a self-contained document (e.g. pdf). One issue is that
traditional paper documents work best with numbered references to parts,
chapters, and sections whereas html documents prefer descriptive links.
To service both, this document has extensions to automatically provide
references to document parts. Three roles are created: `:partref:`,
`:chapref:`, and `:secref:` to create cross references to parts, chapters,
and sections, respectively. They each take a label, and Sphinx is
configured with numfig and autosection labels. These labels take the form
<file>:<title> where <file> is the name of the file containing the section
(without the `.rst` extension) and <title> is the full name of the section.
Here are examples of cross references.
``` restructuredtext
:partref:`part-getting-started:Getting Started`
:chapref:`introduction:Introduction`
:secref:`introduction:How to Use This Guide`
```
### Example code
The VTK-m User's Guide has numerous code examples. These code examples are
pulled from source files that are compiled and run as part of VTK-m's
regression tests. Although these "tests" are not meant to be thorough
regression tests like the others, they ensure that the documentation stays
up to date and correct.
Examples are added to the `examples` directory more or less like any other
unit test in VTK-m (except by convention we start the name with
`GuideExample`). Each of these files can then be scanned to find excerpts
to include as an example in the guide.
#### Marking examples in the code
A simple text scanner goes through the example code looking for lines
containing a comment starting with 4 slashes, `////`. Any such line will
not be included in the example.
An example can be started with `//// BEGIN-EXAMPLE` and ended with
`//// END-EXAMPLE`. Each of these must be given the name of the example.
``` cpp
////
//// BEGIN-EXAMPLE EquilateralTriangle
////
vtkm::Vec<vtkm::Vec2f_32, 3> equilateralTriangle = { { 0.0f, 0.0f },
{ 1.0f, 0.0f },
{ 0.5f, 0.8660254f } };
////
//// END-EXAMPLE EquilateralTriangle
////
```
#### Loading examples in the documentation
An example can be loaded into the VTK-m User's Guide using the extended
reStructuredText `load-example` directive. The directive takes the name of
the example as its argument. `load-example` should also be given the
`:file:` and `:caption:` options.
``` restructuredtext
.. load-example:: EquilateralTriangle
:file: GuideExampleCoreDataTypes.cxx
:caption: Defining a triangle in the plane.
```
The following options are supported.
* `:file:` The filename of the file containing the named example. The
filename is relative to the `examples` directory.
* `:caption:` The caption used for the example.
* `:nolinenos:` Turn off line numbering. By default, line numbers are
shown, but they are suppressed with this option.
#### Referencing examples
The example is registered as a `code-block` the named registered as the
example named prepended with `ex:`. This name can then be referenced with
the `:ref:` and `:numref:` roles as with figures, sections, and other cross
references.
The `:numref:` role is particularly useful for referencing each example.
Using `:numref:` with just the name will be replaced with a link titled
"Example #" with "#" being the number of the example.
``` restructuredtext
:numref:`ex:EquilateralTriangle` shows how the :class:`Vec` class can be used to
store several points in the same structure.
```
The `:numref:` role also supports custom text with number substitution as
described in the [Sphinx
documentation](https://www.sphinx-doc.org/en/master/usage/restructuredtext/roles.html#role-numref)
``` restructuredtext
:numref:`Example %s representes an equilateral triangle<ex:EquilateralTriangle>`
using the :class:`Vec` class.
```
#### Pausing and resuming capture
Sometimes it is useful to insert code in the compiled test that is not
included as part of the example. This is useful to, for example, insert a
check for values, which can verify that the code is working correctly but
is not necessary for the example.
When a `//// PAUSE-EXAMPLE` is inserted into the code, the following lines
will not be captured until the line `//// RESUME-EXAMPLE` is encountered.
``` cpp
range.Include(2.0); // range is now [0.5 .. 2]
bool b5 = range.Contains(0.5); // b3 is true
bool b6 = range.Contains(0.6); // b4 is true
range.Include(vtkm::Range(-1, 1)); // range is now [-1 .. 2]
//// PAUSE-EXAMPLE
VTKM_TEST_ASSERT(test_equal(range, vtkm::Range(-1, 2)), "Bad range");
//// RESUME-EXAMPLE
```
#### Referencing a specific line
You apply a label to a specific line in the code by adding a `//// LABEL`
comment right before it. The `LABEL` needs a text string used to reference
the line.
``` cpp
////
//// BEGIN-EXAMPLE VecCExample
////
//// LABEL index-to-ijk
VTKM_EXEC vtkm::VecCConst<vtkm::IdComponent> HexagonIndexToIJK(vtkm::IdComponent index)
{
static const vtkm::IdComponent HexagonIndexToIJKTable[8][3] = {
{ 0, 0, 0 }, { 1, 0, 0 }, { 1, 1, 0 }, { 0, 1, 0 },
{ 0, 0, 1 }, { 1, 0, 1 }, { 1, 1, 1 }, { 0, 1, 1 }
};
return vtkm::make_VecC(HexagonIndexToIJKTable[index], 3);
}
//// LABEL ijk-to-index
VTKM_EXEC vtkm::IdComponent HexagonIJKToIndex(vtkm::VecCConst<vtkm::IdComponent> ijk)
{
static const vtkm::IdComponent HexagonIJKToIndexTable[2][2][2] = {
{
// i=0
{ 0, 4 }, // j=0
{ 3, 7 }, // j=1
},
{
// i=1
{ 1, 5 }, // j=0
{ 2, 6 }, // j=1
}
};
return HexagonIJKToIndexTable[ijk[0]][ijk[1]][ijk[2]];
}
////
//// END-EXAMPLE VecCExample
////
```
This line can be referenced in the text using the extended reStructuredText
`:exlineref:` role. The role takes references of the form
"example-name:line-label". If given just this reference, the link text is
"Example #, line #".
``` restructuredtext
A function to convert a 3D index to a flat index starts on
:exlineref:`VecCExample:ijk-to-index`.
```
`:exlineref:` also accepts a formatting string like the `:numref:` builtin
role. `%s` and `{line}` will be replaced with the line number.
`:exlineref:` also follows the [`:numref:`
convention](https://www.sphinx-doc.org/en/master/usage/restructuredtext/roles.html#role-numref)
of replacing `{number}` and `{name}` with the example number and caption,
respectively.
``` restructuredtext
You can convert a flat index to a 3D index (shown starting on
:exlineref:`line {line} in Example {number}<VecCExample:index-to-ijk>`) and
the inverse function (:exlineref:`line %s<VecCExample:ijk-to-index>`).
```
### Ingesting Doxygen
The VTK-m User's Guide is built with [Breathe], which allows it to pull in
Doxygen documentation. Use [Breathe's
directives](https://breathe.readthedocs.io/en/latest/directives.html#directives)
to include the doxygen documentation.
[Sphinx]: https://www.sphinx-doc.org/en/master/
[Doxygen]: https://www.doxygen.nl/
[RTD Theme]: https://sphinx-themes.org/sample-sites/sphinx-rtd-theme/
[Sphinx CMake Domain]: https://github.com/scikit-build/moderncmakedomain
[Breathe]: https://www.breathe-doc.org/
[reStructuredText]: https://docutils.sourceforge.io/rst.html

@ -0,0 +1,139 @@
##=============================================================================
##
## 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.
##
##=============================================================================
from extract_examples import find_examples
import sphinx_tools
import docutils.nodes
import docutils.parsers.rst.directives
import sphinx.util.docutils
import re
class LoadExampleDirective(sphinx.util.docutils.SphinxDirective):
has_content = False
required_arguments = 1
option_spec = {
'file': docutils.parsers.rst.directives.unchanged,
'nolinenos': docutils.parsers.rst.directives.flag,
'caption': docutils.parsers.rst.directives.unchanged_required,
'language': docutils.parsers.rst.directives.unchanged,
'command-comment': docutils.parsers.rst.directives.unchanged,
}
def run(self):
reparse = sphinx_tools.ReparseNodes()
source_file = self.state.document.current_source
source_line = self.lineno
example_name = self.arguments[0]
filename = None
if 'file' in self.options:
filename = self.options.get('file')
if self.config.example_directory:
filename = self.config.example_directory + '/' + filename
else:
print('WARNING %s:%d: Example `%s` loaded without filename.' %
(source_file, source_line, example_name))
if 'language' in self.options:
language = self.options.get('language')
else:
language = self.config.example_language
reparse.add_line('.. code-block:: %s' % language, source_file, source_line)
reparse.add_line(' :name: ex:%s' % example_name, source_file, source_line)
if 'nolinenos' not in self.options:
reparse.add_line(' :linenos:', source_file, source_line)
if 'caption' in self.options:
reparse.add_line(' :caption: %s' % self.options.get('caption'),
source_file, source_line)
reparse.add_line('', source_file, source_line)
try:
if 'command-comment' in self.options:
command_comment = self.options.get('command-comment')
else:
command_comment = self.config.example_command_comment
example = find_examples.get_example(example_name,
filename=filename,
command_comment=command_comment)
for line in example.lines:
reparse.add_line(' %s' % line.code, example.sourcefile, line.lineno)
except Exception as e:
error = self.state_machine.reporter.error(
str(e),
docutils.nodes.literal_block(self.block_text, self.block_text),
lineno=self.lineno,
)
return [error]
reparse.add_line('', source_file, source_line)
return reparse.get_nodes(self)
def exlineref_role(name, rawtext, text, lineno, inliner, options = {}, content = []):
match = re.fullmatch(r'(.*)<(.*)>', text, re.DOTALL)
if match:
pattern = match.group(1)
ref = match.group(2)
else:
pattern = 'Example {number}, line {line}'
ref = text
match = re.fullmatch(r'(.*):([^:]*)', ref)
if not match:
message = inliner.reporter.error(
'References for :exlineref: must be of the form example-name:label-name.;'
' `%s` is invalid.' % ref, line=lineno)
problematic = inliner.problematic(rawtext, rawtext, message)
return [problematic, message]
examplename = match.group(1)
linelabel = match.group(2)
# Strip optional `ex:` prefix.
match = re.fullmatch(r'ex:(.*)', examplename)
if match:
examplename = group(1)
try:
example = find_examples.get_example(examplename)
if linelabel not in example.labels:
raise Exception(
'Label `%s` not in example `%s`' % (linelabel, examplename))
lineno = example.labels[linelabel]
except Exception as e:
message = inliner.reporter.error(str(e), line=lineno)
problematic = inliner.problematic(rawtext, rawtext, message)
return [problematic, message]
pattern = re.sub(r'%s', str(lineno), pattern, 1, re.DOTALL)
pattern = pattern.format(line=lineno, number='{number}', name='{name}')
if (pattern.find('{number}') >=0) or (pattern.find('{name}') >= 0):
return sphinx_tools.role_reparse(
':numref:`%s <ex:%s>`' % (pattern, examplename), lineno, inliner)
else:
return sphinx_tools.role_reparse(
':ref:`%s <ex:%s>`' % (pattern, examplename), lineno, inliner)
def setup(app):
app.add_config_value('example_directory',
default=None,
rebuild='env',
types=[str])
app.add_config_value('example_command_comment',
default='####',
rebuild='env')
app.add_config_value('example_language',
default='',
rebuild='env')
app.add_directive('load-example', LoadExampleDirective)
app.add_role('exlineref', exlineref_role)

@ -0,0 +1,160 @@
##=============================================================================
##
## 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.
##
##=============================================================================
import re
class SourceLine:
'''Class to hold lines to include as example along with line numbers.'''
def __init__(self, code, lineno):
self.code = code
self.lineno = lineno
class Example:
'''Class to hold an extracted example.
The `name` field contains the name of the example. The `lines` field
contains an array of `SourceLine` objects containing the contents.'''
def __init__(self, name, sourcefile, startline):
self.name = name
self.sourcefile = sourcefile
self.startline = startline
self.lines = []
self.labels = {}
def add_line(self, code, lineno):
self.lines.append(SourceLine(code, lineno))
class ReadError(Exception):
'''This class is thrown as an exception if a read error occurs.'''
def __init__(self, message, filename, lineno, line):
super().__init__('%s:%s: %s\n%s' % (filename, lineno, message, line))
loaded_examples = {}
loaded_files = []
def read_file(filename, command_comment='////', verbose=False):
'''Reads a source file and finds examples declared by special command
comments. This method returns an array of `Example` objects.'''
if verbose:
print('Reading file %s' % filename)
lines = open(filename, 'r').readlines()
examples = []
active_examples = {}
lineno = 0
paused = False
for line in lines:
lineno += 1
index = line.find(command_comment)
if index >= 0:
command = line[(index + len(command_comment)):].split()
if len(command) < 1:
pass
elif command[0] == 'BEGIN-EXAMPLE':
if len(command) != 2:
raise ReadError('BEGIN-EXAMPLE requires exactly one argument.',
filename,
lineno,
line)
example_name = command[1]
if verbose:
print('Extracting example `%s`' % example_name)
if example_name in active_examples:
raise ReadError('Example %s declared within itself.' % example_name,
filename,
lineno,
line)
active_examples[example_name] = Example(example_name, filename, lineno)
elif command[0] == 'END-EXAMPLE':
if len(command) != 2:
raise ReadError('END-EXAMPLE requires exactly one argument.',
filename,
lineno,
line)
example_name = command[1]
if example_name not in active_examples:
raise ReadError('Example %s ended before it began.' % example_name,
filename,
lineno,
line)
examples.append(active_examples[example_name])
del active_examples[example_name]
elif command[0] == 'PAUSE-EXAMPLE':
if paused:
raise ReadError('Example iteratively paused.',
filename, lineno, line)
paused = True
elif command[0] == 'RESUME-EXAMPLE':
if not paused:
raise ReadError('Example resumed without being paused.',
filename, lineno, line)
paused = False
elif command[0] == 'LABEL':
if len(command) != 2:
raise ReadError('LABEL requires exactly one argument.',
filename,
lineno,
line)
label = command[1]
for name in active_examples:
nextline = len(active_examples[name].lines) + 1
active_examples[name].labels[label] = nextline
else:
raise ReadError('Command %s not recognized.' % command[0],
filename,
lineno,
line)
else:
# Line not a command. Add it to any active examples.
if not paused:
for name in active_examples:
active_examples[name].add_line(line.rstrip(), lineno)
if active_examples:
raise ReadError(
'Unterminated example: %s' % next(iter(active_examples.keys())),
filename,
lineno,
line)
return examples
def load_file(filename, command_comment='////', verbose=False):
'''Loads the examples in the given file. The examples a placed in the
`loaded_examples` dictionary, which is indexed by example name. If the
file was previously loaded, nothing happens.'''
if filename not in loaded_files:
examples = read_file(filename, command_comment, verbose)
for example in examples:
name = example.name
if name in loaded_examples:
raise Exception('Example named %s found in both %s:%d and %s:%d.' %
(name, example.sourcefile, example.startline,
loaded_examples[name].sourcefile,
loaded_examples[name].startline))
loaded_examples[name] = example
loaded_files.append(filename)
def get_example(name, filename=None, command_comment='////', verbose=False):
'''Returns an `Example` object containing the named example. If a filename
is provided, that file is first scanned for examples (if it has not already
been scanned for examples).'''
if filename:
load_file(filename, command_comment, verbose)
if name not in loaded_examples:
raise Exception('No example named %s found.' % name)
example = loaded_examples[name]
if filename and filename != example.sourcefile:
print('WARNING: Example %s was expected in file %s but found in %s' %
(name, filename, example.sourcefile))
return example

@ -0,0 +1,37 @@
##=============================================================================
##
## 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.
##
##=============================================================================
import docutils.nodes
import sphinx_tools
def fullref_role(reftype, name, rawtext, text, lineno, inliner, options, content):
return sphinx_tools.role_reparse(
':numref:`%s {number} ({name})<%s>`' % (reftype, text),
lineno, inliner)
def partref_role(name, rawtext, text, lineno, inliner, options = {}, content = []):
return fullref_role(
'Part', name, rawtext, text, lineno, inliner, options, content)
def chapref_role(name, rawtext, text, lineno, inliner, options = {}, content = []):
return fullref_role(
'Chapter', name, rawtext, text, lineno, inliner, options, content)
def secref_role(name, rawtext, text, lineno, inliner, options = {}, content = []):
return fullref_role(
'Section', name, rawtext, text, lineno, inliner, options, content)
def setup(app):
app.add_role('partref', partref_role)
app.add_role('chapref', chapref_role)
app.add_role('secref', secref_role)

@ -0,0 +1,69 @@
##=============================================================================
##
## 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.
##
##=============================================================================
import docutils.nodes
import docutils.parsers.rst
import sphinx.util.docutils
class didyouknownode(docutils.nodes.Admonition, docutils.nodes.Element):
pass
class commonerrorsnode(docutils.nodes.Admonition, docutils.nodes.Element):
pass
def visit_didyouknow_node(self, node):
self.visit_admonition(node)
def visit_commonerrors_node(self, node):
self.visit_admonition(node)
def depart_didyouknow_node(self, node):
self.depart_admonition(node)
def depart_commonerrors_node(self, node):
self.depart_admonition(node)
class didyouknowdirective(sphinx.util.docutils.SphinxDirective):
has_content = True
def run(self):
admonitionnode = didyouknownode('\n'.join(self.content))
admonitionnode += docutils.nodes.title('Did You Know?', 'Did You Know?')
admonitionnode['classes'] += ['tip']
self.state.nested_parse(self.content, self.content_offset, admonitionnode)
return [admonitionnode]
class commonerrorsdirective(sphinx.util.docutils.SphinxDirective):
has_content = True
def run(self):
admonitionnode = commonerrorsnode('\n'.join(self.content))
admonitionnode += docutils.nodes.title('Common Errors', 'Common Errors')
admonitionnode['classes'] += ['error']
self.state.nested_parse(self.content, self.content_offset, admonitionnode)
return [admonitionnode]
def setup(app):
app.add_node(didyouknownode,
html=(visit_didyouknow_node, depart_didyouknow_node),
latex=(visit_didyouknow_node, depart_didyouknow_node),
text=(visit_didyouknow_node, depart_didyouknow_node),
)
app.add_directive('didyouknow', didyouknowdirective)
app.add_node(commonerrorsnode,
html=(visit_commonerrors_node, depart_commonerrors_node),
latex=(visit_commonerrors_node, depart_commonerrors_node),
text=(visit_commonerrors_node, depart_commonerrors_node),
)
app.add_directive('commonerrors', commonerrorsdirective)

@ -0,0 +1,109 @@
##=============================================================================
##
## 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.
##
##=============================================================================
def role_reparse(rawtext, lineno, inliner):
'''Reparses inline code for a role.
It is often the case that a role for reStructuredText can be defined using
other existing functionality. Rather than try to implement the node building
for such extensions from scratch, it is much easier to substitute the text
with something and instruct the parser to parse that.
Unfortunately, Sphinx currently does not provide the ability to do such a
"reparse" while implementing a role. This method is a hacked version of the
`parse` method of `docutils.parsers.rst.states.Inliner`. (This code might
break if the internals of that class change.)
To use this method, create a role implementation function as normal, modify
the text/rawText to the form that implements the functionality, and call
this method with the new text as well as the passed in line number and
inliner object.
Note that if the parsing of the text breaks, the error messages may be
confusing because they could refer to items that are not being directly
used in the reStructuredText document.
'''
remaining = rawtext
processed = []
unprocessed = []
messages = []
while remaining:
match = inliner.patterns.initial.search(remaining)
if match:
groups = match.groupdict()
method = inliner.dispatch[groups['start'] or groups['backquote']
or groups['refend'] or groups['fnend']]
before, inlines, remaining, sysmessages = method(inliner, match, lineno)
unprocessed.append(before)
messages += sysmessages
if inlines:
processed += inliner.implicit_inline(''.join(unprocessed), lineno)
processed += inlines
unprocessed = []
else:
break
remaining = ''.join(unprocessed) + remaining
if remaining:
processed += inliner.implicit_inline(remaining, lineno)
return processed, messages
import docutils.nodes
import docutils.statemachine
import sphinx.util.nodes
class ReparseNodes:
'''This class is used within directive classes to implement a directive by
creating new reStructuredText code. This new code is fed back to the parser
and the resulting nodes can be returned as the implementation of the
directive.
To use this class, construct an object. Then use the ``add_line`` method to
add lines one at a time. When finished, use the ``get_nodes`` function to
get the nodes that should be returned from the directives ``run`` method.
Here is a simple example::
import sphinx.util.docutils
class Foo(sphinx.util.docutils.SphinxDirective):
def run(self):
reparse = ReparseNodes()
reparse.add_line('.. note::', 'fakefile.rst', 1)
reparse.add_line(' This box added in directive.', 'fakefile.rst', 2)
reparse.add_line('', 'fakefile.rst', 3)
reparse.add_line('This text also added in directive.', 'fakefile.rst', 3)
return reparse.get_nodes(self)
def setup(app):
app.add_directive('foo', Foo)
Note that if you want the reparse to base its file location on the location
of your directive (which is a good idea), you can get the name of the file
containing the directive call with ``self.state.document.current_source``
and get the line to directive starts at with ``self.lineno``.
The implementation of this class suggested from
https://stackoverflow.com/questions/34350844/how-to-add-rst-format-in-nodes-for-directive
'''
def __init__(self):
self.source = docutils.statemachine.ViewList()
def add_line(self, sourceline, filename, linenumber):
self.source.append(sourceline, filename, linenumber)
def get_nodes(self, directive):
node = docutils.nodes.section()
node.document = directive.state.document
sphinx.util.nodes.nested_parse_with_titles(directive.state,
self.source,
node)
return node.children

@ -0,0 +1,94 @@
==============================
Acknowledgements
==============================
------------------------------
Contributors
------------------------------
.. todo:: Make sure contribution section cross references are correct.
This book includes contributions from the VTK-m community including the
VTK-m development team and the user community.
We would like to thank the following people for their significant
contributions to this text:
.. NOTE: Also make sure that the contribution list is updated in index.rst
**Vicente Bolea**, **Nickolas Davis**, **Matthew Letter**, and **Nick Thompson** for their help keeping the user's guide up to date with the |VTKm| source code.
**Sujin Philip**, **Robert Maynard**, **James Kress**, **Abhishek Yenpure**, **Mark Kim**, and **Hank Childs** for their descriptions of numerous filters.
.. Sujin Philip: Surface normals, normals in Marching Cubes
.. Robert Maynard: Gradient, warp scalars, warp vectors, histogram, extract structured
.. James Kress: Point transform
.. Abhishek Yenpure: Point merge
.. Mark Kim: ZFP compression
.. Hank Childs: Mesh Quality Metrics
**Allison Vacanti** for her documentation of..
.. several |VTKm| features in the `Extract Component Arrays`_ and `SwizzleArrays`_ sections as well as select filters.
.. Allie Vacanti filters: Surface normals.
**David Pugmire** for his documentation of..
.. partitioned data sets (Section \ref{sec:DataSets:PartitionedDataSet}) and select filters.
.. Dave Pugmire filters: Streamlines, point transform, coordinate system transforms, add ghost cells, remove ghost cells.
**Abhishek Yenpure** and **Li-Ta Lo** for their documentation of locator structures..
.. (Chapter~\ref{chap:Locators}).
.. Abhishek Yenpure: General cell locators and BoundingIntervalHierarchy
.. Li-Ta Lo: General point locators and uniform grid point locator, particle density
**Li-Ta Lo** for his documentation of random array handles and particle
density filters.
.. ArrayHandleRandomUniformBits.
**James Kress** for his documentation on |VTKm|'s testing classes.
**Manish Mathai** for his documentation of rendering features..
.. (Chapter~\ref{chap:Rendering}).
------------------------------
Funding
------------------------------
.. |LogoSpacing| image:: images/LogoSpacing.png
.. |DOELogo| image:: images/DOELogo.png
.. |ORNLLogo| image:: images/ORNLLogo.png
.. |LANLLogo| image:: images/LANLLogo.png
.. |SandiaLogo| image:: images/SandiaLogo.png
.. |KitwareLogo| image:: images/KitwareLogo.png
.. centered:: |DOELogo|
|LogoSpacing|
|ORNLLogo|
|LogoSpacing|
|LANLLogo|
|LogoSpacing|
|SandiaLogo|
|LogoSpacing|
|KitwareLogo|
|LogoSpacing|
This project has been funded in whole or in part with Federal funds from the Department of Energy, including from Oak Ridge National Laboratory, Los Alamos National Laboratory, and Sandia National Laboratories.
This manuscript has been authored in part by UT-Battelle, LLC, under contract DE-AC05-00OR22725 with the US Department of Energy (DOE).
The US government retains and the publisher, by accepting the article for publication, acknowledges that the US government retains a nonexclusive, paid-up, irrevocable, worldwide license to publish or reproduce the published form of this manuscript, or allow others to do so, for US government purposes.
Sandia National Laboratories is a multimission laboratory managed and operated by National Technology and Engineering Solutions of Sandia LLC, a wholly owned subsidiary of Honeywell International Inc. for the U.S. Department of Energy's National Nuclear Security Administration under contract DE-NA0003525.
This research was supported by the Exascale Computing Project (17-SC-20-SC), a joint project of the U.S.
Department of Energy's Office of Science and National Nuclear Security Administration, responsible for delivering a capable exascale ecosystem, including software, applications, and hardware technology, to support the nation's exascale computing imperative.
This material is based upon work supported by the U.S.
Department of Energy, Office of Science, Office of Advanced Scientific Computing Research, Scientific Discovery through Advanced Computing (SciDAC) program.

@ -0,0 +1,227 @@
==============================
Base Types
==============================
It is common for a framework to define its own types.
Even the C++ standard template library defines its own base types like :type:`std::size_t` and :type:`std::pair`.
|VTKm| is no exception.
In fact |VTKm| provides a great many base types.
It is the general coding standard of |VTKm| to not directly use the base C types like ``int`` and ``float`` and instead to use types declared in |VTKm|.
The rational is to precisely declare the representation of each variable to prevent future trouble.
Consider that you are programming something and you need to declare an integer variable.
You would declare this variable as ``int``, right?
Well, maybe.
In C++, the declaration ``int`` does not simply mean "an integer."
``int`` means something much more specific than that.
If you were to look up the C++11 standard, you would find that ``int`` is an integer represented in 32 bits with a two's complement signed representation.
In fact, a C++ compiler has no less than 8 standard integer types.
..
\footnote{%
I intentionally use the phrase ``no less than'' for our pedantic readers.
One could argue that \textcode{char} and \textcode{bool} are treated distinctly by the compiler even if their representations match either \textcode{signed char} or \textcode{unsigned char}.
Furthermore, many modern C++ compilers have extensions for less universally accepted types like 128-bit integers.
}
So, ``int`` is nowhere near as general as the code might make it seem, and treating it as such could lead to trouble.
For example, consider the MPI standard, which, back in the 1990's, implicitly selected ``int`` for its indexing needs.
Fast forward to today where there is a need to reference buffers with more than 2 billion elements, but the standard is stuck with a data type that cannot represent sizes that big.
(To be fair, it is *possible* to represent buffers this large in MPI, but it is extraordinarily awkward to do so.
Consequently, we feel that with |VTKm| it is best to declare the intention of a variable with its declaration, which should help both prevent errors and future proof code.
All the types presented in this chapter are declared in :file:`vtkm/Types.h`, which is typically included either directly or indirectly by all source using |VTKm|.
------------------------------
Floating Point Types
------------------------------
|VTKm| declares 2 types to hold floating point numbers: :type:`vtkm::Float32` and :type:`vtkm::Float64`.
These, of course, represent floating point numbers with 32-bits and 64-bits of precision, respectively.
These should be used when the precision of a floating point number is predetermined.
.. doxygentypedef:: vtkm::Float32
.. doxygentypedef:: vtkm::Float64
When the precision of a floating point number is not predetermined, operations usually have to be overloaded or templated to work with multiple precisions.
In cases where a precision must be set, but no particular precision is specified, :type:`vtkm::FloatDefault` should be used.
.. doxygentypedef:: vtkm::FloatDefault
:type:`vtkm::FloatDefault` will be set to either :type:`vtkm::Float32` or :type:`vtkm::Float64` depending on whether the CMake option :cmake:variable:`VTKm_USE_DOUBLE_PRECISION` was set when |VTKm| was compiled, as discussed in :secref:`building:Configuring |VTKm|`.
Using :type:`vtkm::FloatDefault` makes it easier for users to trade off precision and speed.
------------------------------
Integer Types
------------------------------
The most common use of an integer in |VTKm| is to index arrays.
For this purpose, the :type:`vtkm::Id` type should be used.
(The width of :type:`vtkm::Id` is determined by the :cmake:variable:`VTKm_USE_64BIT_IDS` CMake option.)
.. doxygentypedef:: vtkm::Id
|VTKm| also has a secondary index type named :type:`vtkm::IdComponent`, which is smaller and typically used for indexing groups of components within a thread.
For example, if you had an array of 3D points, you would use :type:`vtkm::Id` to reference each point, and you would use :type:`vtkm::IdComponent` to reference the respective :math:`x`, :math:`y`, and :math:`z` components.
.. doxygentypedef:: vtkm::IdComponent
.. index:: std::size_t, size_t
.. didyouknow::
The |VTKm| index types, :type:`vtkm::Id` and :type:`vtkm::IdComponent` use signed integers.
This breaks with the convention of other common index types like the C++ standard template library :type:`std::size_t`, which use unsigned integers.
Unsigned integers make sense for indices as a valid index is always 0 or greater.
However, doing things like iterating in a for loop backward, representing relative indices, and representing invalid values is much easier with signed integers.
Thus, |VTKm| chooses to use a signed integer for indexing.
|VTKm| also has types to declare an integer of a specific width and sign.
The types :type:`vtkm::Int8`, :type:`vtkm::Int16`, :type:`vtkm::Int32`, and :type:`vtkm::Int64` specify signed integers of 1, 2, 4, and 8 bytes, respectively.
Likewise, the types :type:`vtkm::UInt8`, :type:`vtkm::UInt16`, :type:`vtkm::UInt32`, and :type:`vtkm::UInt64` specify unsigned integers of 1, 2, 4, and 8 bytes, respectively.
.. doxygentypedef:: vtkm::Int8
.. doxygentypedef:: vtkm::UInt8
.. doxygentypedef:: vtkm::Int16
.. doxygentypedef:: vtkm::UInt16
.. doxygentypedef:: vtkm::Int32
.. doxygentypedef:: vtkm::UInt32
.. doxygentypedef:: vtkm::Int64
.. doxygentypedef:: vtkm::UInt64
------------------------------
Vector Types
------------------------------
Visualization algorithms also often require operations on short vectors.
Arrays indexed in up to three dimensions are common.
Data are often defined in 2-space and 3-space, and transformations are typically done in homogeneous coordinates of length 4.
To simplify these types of operations, |VTKm| provides a collection of base types to represent these short vectors, which are collectively referred to as ``Vec`` types.
:type:`vtkm::Vec2f`, :type:`vtkm::Vec3f`, and :type:`vtkm::Vec4f` specify floating point vectors of 2, 3, and 4 components, respectively.
The precision of the floating point numbers follows that of :type:`vtkm::FloatDefault` (which, as documented in :secref:`base-types:Floating Point Types`, is specified by the :cmake:variable:`VTKm_USE_DOUBLE_PRECISION` compile option).
Components of these and other ``Vec`` types can be references through the ``[ ]`` operator, much like a C array.
A ``Vec`` also supports basic arithmetic operators so that it can be used much like its scalar-value counterparts.
.. doxygentypedef:: vtkm::Vec2f
.. doxygentypedef:: vtkm::Vec3f
.. doxygentypedef:: vtkm::Vec4f
.. load-example:: SimpleVectorTypes
:file: GuideExampleCoreDataTypes.cxx
:caption: Simple use of ``Vec`` objects.}
You can also specify the precision for each of these vector types by appending the bit size of each component.
For example, :type:`vtkm::Vec3f_32` and :type:`vtkm::Vec3f_64` represent 3-component floating point vectors with each component being 32 bits and 64 bits respectively.
Note that the precision number refers to the precision of each component, not the vector as a whole.
So :type:`vtkm::Vec3f_32` contains 3 32-bit (4-byte) floating point components, which means the entire :type:`vtkm::Vec3f_32` requires 96 bits (12 bytes).
.. doxygentypedef:: vtkm::Vec2f_32
.. doxygentypedef:: vtkm::Vec2f_64
.. doxygentypedef:: vtkm::Vec3f_32
.. doxygentypedef:: vtkm::Vec3f_64
.. doxygentypedef:: vtkm::Vec4f_32
.. doxygentypedef:: vtkm::Vec4f_64
To help with indexing 2-, 3-, and 4- dimensional arrays, |VTKm| provides the types :type:`vtkm::Id2`, :type:`vtkm::Id3`, and :type:`vtkm::Id4`, which are \textidentifier{Vec}s of type :type:`vtkm::Id`.
Likewise, |VTKm| provides :type:`vtkm::IdComponent2`, :type:`vtkm::IdComponent3`, and :type:`vtkm::IdComponent4`.
.. doxygentypedef:: vtkm::Id2
.. doxygentypedef:: vtkm::Id3
.. doxygentypedef:: vtkm::Id4
.. doxygentypedef:: vtkm::IdComponent2
.. doxygentypedef:: vtkm::IdComponent3
.. doxygentypedef:: vtkm::IdComponent4
|VTKm| also provides types for \textidentifier{Vec}s of integers of all varieties described in Section \ref{sec:IntegerTypes}.
:type:`vtkm::Vec2i`, :type:`vtkm::Vec3i`, and :type:`vtkm::Vec4i` are vectors of signed integers whereas :type:`vtkm::Vec2ui`, :type:`vtkm::Vec3ui`, and :type:`vtkm::Vec4ui` are vectors of unsigned integers.
All of these sport components of a width equal to :type:`vtkm::Id`.
.. doxygentypedef:: vtkm::Vec2i
.. doxygentypedef:: vtkm::Vec3i
.. doxygentypedef:: vtkm::Vec4i
.. doxygentypedef:: vtkm::Vec2ui
.. doxygentypedef:: vtkm::Vec3ui
.. doxygentypedef:: vtkm::Vec4ui
The width can be specified by appending the desired number of bits in the same way as the floating point \textidentifier{Vec}s.
For example, :type:`vtkm::Vec4ui_8` is a \textidentifier{Vec} of 4 unsigned bytes.
.. doxygentypedef:: vtkm::Vec2i_8
.. doxygentypedef:: vtkm::Vec2ui_8
.. doxygentypedef:: vtkm::Vec2i_16
.. doxygentypedef:: vtkm::Vec2ui_16
.. doxygentypedef:: vtkm::Vec2i_32
.. doxygentypedef:: vtkm::Vec2ui_32
.. doxygentypedef:: vtkm::Vec2i_64
.. doxygentypedef:: vtkm::Vec2ui_64
.. doxygentypedef:: vtkm::Vec3i_8
.. doxygentypedef:: vtkm::Vec3ui_8
.. doxygentypedef:: vtkm::Vec3i_16
.. doxygentypedef:: vtkm::Vec3ui_16
.. doxygentypedef:: vtkm::Vec3i_32
.. doxygentypedef:: vtkm::Vec3ui_32
.. doxygentypedef:: vtkm::Vec3i_64
.. doxygentypedef:: vtkm::Vec3ui_64
.. doxygentypedef:: vtkm::Vec4i_8
.. doxygentypedef:: vtkm::Vec4ui_8
.. doxygentypedef:: vtkm::Vec4i_16
.. doxygentypedef:: vtkm::Vec4ui_16
.. doxygentypedef:: vtkm::Vec4i_32
.. doxygentypedef:: vtkm::Vec4ui_32
.. doxygentypedef:: vtkm::Vec4i_64
.. doxygentypedef:: vtkm::Vec4ui_64
These types really just scratch the surface of the ``Vec`` types available in |VTKm| and the things that can be done with them.
See ``:chapref:`advanced-types:Advanced Types` `` for more information on ``Vec`` types and what can be done with them.
.. todo:: Update chapter reference.

@ -0,0 +1,399 @@
==============================
Building and Installing |VTKm|
==============================
Before we begin describing how to develop with |VTKm|, we have a brief overview of how to build |VTKm|, optionally install it on your system, and start your own programs that use |VTKm|.
------------------------------
Getting |VTKm|
------------------------------
|VTKm| is an open source software product where the code is made freely available.
To get the latest released version of |VTKm|, go to the |VTKm| releases page:
https://gitlab.kitware.com/vtk/vtk-m/-/releases
From there with your favorite browser you may download the source code from any of the recent |VTKm| releases in a variety of different archive files such as zip or tar gzip.
For access to the most recent work, the |VTKm| development team provides public anonymous read access to their main source code repository.
The main |VTKm| repository on a GitLab instance hosted at Kitware, Inc.
The repository can be browsed from its project web page:
https://gitlab.kitware.com/vtk/vtk-m
We leave access to the :index:`git` hosted repository as an exercise for the user.
Those interested in :command:`git` access for the purpose of contributing to |VTKm| should consult the `CONTRIBUTING <https://gitlab.kitware.com/vtk/vtk-m/blob/master/CONTRIBUTING.md>`_ guidelines documented in the source code.
.. %% \index{git|(}
.. %% The source code in the |VTKm| repository is access through the \textfilename{git} version control tool.
.. %% If you have not used \textfilename{git} before, there are several resources available to help you get familiar with it.
.. %% Github has a nice setup guide (\url{https://help.github.com/articles/set-up-git}) to help you get up and running quickly.
.. %% For more complete documentation, we recommend the \emph{Pro Git} book (\url{https://git-scm.com/book}).
.. %% To get a copy of the |VTKm| repository, issue a git clone command.
.. %% \begin{blankexample}{Cloning the main |VTKm| git repository.}
.. %% git clone https://gitlab.kitware.com/vtk/vtk-m.git
.. %% \end{blankexample}
.. %% The git clone command will create a copy of all the source code to your local machine.
.. %% As time passes and you want to get an update of changes in the repository, you can do that with the git pull command.
.. %% \begin{blankexample}{Updating a git repository with the pull command.}
.. %% git pull
.. %% \end{blankexample}
.. %% \begin{didyouknow}
.. %% The proceeding examples for using git are based on the \textfilename{git} command line tool, which is particularly prevalent on Unix-based and Mac systems.
.. %% There also exist several GUI tools for accessing git repositories.
.. %% These tools each have their own interface and they can be quite different.
.. %% However, they all should have roughly equivalent commands named ``clone'' to download a repository given a url and ``pull'' to update an existing repository.
.. %% \end{didyouknow}
.. %% \index{git|)}
------------------------------
Configuring |VTKm|
------------------------------
.. index::
single: CMake
pair: CMake; configuration
|VTKm| uses a cross-platform configuration tool named CMake to simplify the configuration and building across many supported platforms.
CMake is available from many package distribution systems and can also be downloaded for many platforms from http://cmake.org.
Most distributions of CMake come with a convenient GUI application (:command:`cmake-gui`) that allows you to browse all of the available configuration variables and run the configuration.
Many distributions also come with an alternative terminal-based version (:command:`ccmake`), which is helpful when accessing remote systems where creating GUI windows is difficult.
One helpful feature of CMake is that it allows you to establish a build directory separate from the source directory, and the |VTKm| project requires that separation.
Thus, when you run CMake for the first time, you want to set the build directory to a new empty directory and the source to the downloaded or cloned files.
The following example shows the steps for the case where the |VTKm| source is cloned from the git repository.
(If you extracted files from an archive downloaded from the |VTKm| web page, the instructions are the same from the second line down.)
.. code-block:: bash
:caption: Running CMake on downloaded |VTKm| source (Unix commands).
:name: ex:RunningCMake
tar xvzf ~/Downloads/vtk-m-v2.1.0.tar.gz
mkdir vtkm-build
cd vtkm-build
cmake-gui ../vtk-m-v2.1.0
.. _fig:CMakeGUI:
.. figure:: images/CMakeGUIBoth.png
:width: 100%
:align: center
The CMake GUI configuring the |VTKm| project.
At left is the initial blank configuration.
At right is the state after a configure pass.
The first time the CMake GUI runs, it initially comes up blank as shown at left in :numref:`fig:CMakeGUI`.
Verify that the source and build directories are correct (located at the top of the GUI) and then click the :guilabel:`Configure` button near the bottom.
The first time you run configure, CMake brings up a dialog box asking what generator you want for the project.
This allows you to select what build system or IDE to use (e.g. make, ninja, Visual Studio).
Once you click :guilabel:`Finish`, CMake will perform its first configuration.
Don't worry if CMake gives an error about an error in this first configuration process.
.. commonerrors::
Most options in CMake can be reconfigured at any time, but not the compiler and build system used.
These must be set the first time configure is run and cannot be subsequently changed.
If you want to change the compiler or the project file types, you will need to delete everything in the build directory and start over.
After the first configuration, the CMake GUI will provide several configuration options as shown in :numref:`fig:CMakeGUI` on the right.
You now have a chance to modify the configuration of |VTKm|, which allows you to modify both the behavior of the compiled |VTKm| code as well as find components on your system.
Using the CMake GUI is usually an iterative process where you set configuration options and re-run :guilabel:`Configure`.
Each time you configure, CMake might find new options, which are shown in red in the GUI.
It is often the case during this iterative configuration process that configuration errors occur.
This can occur after a new option is enabled but CMake does not automatically find the necessary libraries to make that feature possible.
For example, to enable TBB support, you may have to first enable building TBB, configure for TBB support, and then tell CMake where the TBB include directories and libraries are.
Once you have set all desired configuration variables and resolved any CMake errors, click the :guilabel:`Generate` button. This will create the build files (such as makefiles or project files depending on the generator chosen at the beginning). You can then close the CMake GUI.
There are a great number of configuration parameters available when running CMake on |VTKm|.
The following list contains the most common configuration parameters.
.. cmake:variable:: BUILD_SHARED_LIBS
Determines whether static or shared libraries are built.
.. cmake:variable:: CMAKE_BUILD_TYPE
Selects groups of compiler options from categories like :index:`Debug` and :index:`Release`.
Debug builds are, obviously, easier to debug, but they run *much* slower than Release builds.
Use Release builds whenever releasing production software or doing performance tests.
.. cmake:variable:: CMAKE_INSTALL_PREFIX
The root directory to place files when building the install target.
.. cmake:variable:: VTKm_ENABLE_EXAMPLES
The |VTKm| repository comes with an \textfilename{examples} directory.
This macro determines whether they are built.
.. cmake:variable:: VTKm_ENABLE_BENCHMARKS
If on, the |VTKm| build includes several benchmark programs.
The benchmarks are regression tests for performance.
.. cmake:variable:: VTKm_ENABLE_CUDA
Determines whether |VTKm| is built to run on :index:`CUDA` GPU devices.
.. index:: kokkos
.. cmake:variable:: VTKm_ENABLE_KOKKOS
Determines whether |VTKm| is built using the `Kokkos <https://kokkos.github.io/kokkos-core-wiki/>`_ portable library.
Kokkos, can be configured to support several backends that |VTKm| can leverage.
.. cmake:variable:: VTKm_ENABLE_MPI
Determines whether |VTKm| is built with :index:`MPI` suppoert for running on distributed memory clusters.
.. cmake:variable:: VTKm_ENABLE_OPENMP
Determines whether |VTKm| is built to run on multi-core devices using :index:`OpenMP` pragmas provided by the C++ compiler.
.. cmake:variable:: VTKm_ENABLE_RENDERING
Determines whether to build the rendering library.
.. index:: see: Intel Threading Building Blocks; TBB
.. index:: TBB
.. cmake:variable:: VTKm_ENABLE_TBB
Determines whether |VTKm| is built to run on multi-core x86 devices using the Intel Threading Building Blocks library.
.. cmake:variable:: VTKm_ENABLE_TESTING
If on, the |VTKm| build includes building many test programs.
The |VTKm| source includes hundreds of regression tests to ensure quality during development.
.. cmake:variable:: VTKm_ENABLE_TUTORIALS
If on, several small example programes used for the |VTKm| tutorial are built.
.. cmake:variable:: VTKm_USE_64BIT_IDS
If on, then |VTKm| will be compiled to use 64-bit integers to index arrays and other lists.
If off, then |VTKm| will use 32-bit integers.
32-bit integers take less memory but could cause failures on larger data.
.. cmake:variable:: VTKm_USE_DOUBLE_PRECISION
If on, then |VTKm| will use double precision (64-bit) floating point numbers for calculations where the precision type is not otherwise specified.
If off, then single precision (32-bit) floating point numbers are used.
Regardless of this setting, |VTKm|'s templates will accept either type.
------------------------------
Building |VTKm|
------------------------------
Once CMake successfully configures |VTKm| and generates the files for the build system, you are ready to build |VTKm|.
As stated earlier, CMake supports generating configuration files for several different types of build tools.
Make and ninja are common build tools, but CMake also supports building project files for several different types of integrated development environments such as Microsoft Visual Studio and Apple XCode.
The |VTKm| libraries and test files are compiled when the default build is invoked.
For example, if a :file:`Makefile` was generated, the build is invoked by calling \textfilename{make} in the build directory.
Expanding on :numref:`ex:RunningCMake`
.. code-block:: bash
:caption: Using :command:`make` to build |VTKm|.
:name: ex:RunningMake
tar xvzf ~/Downloads/vtk-m-v2.1.0.tar.gz
mkdir vtkm-build
cd vtkm-build
cmake-gui ../vtk-m-v2.1.0
make -j
make install
.. didyouknow::
:file:`Makefile` and other project files generated by CMake support parallel builds, which run multiple compile steps simultaneously.
On computers that have multiple processing cores (as do almost all modern computers), this can significantly speed up the overall compile.
Some build systems require a special flag to engage parallel compiles.
For example, :command:`make` requires the ``-j`` flag to start parallel builds as demonstrated in :numref:`ex:RunningMake`.
.. didyouknow::
:numref:`ex:RunningMake` assumes that a make build system was generated, which is the default on most system.
However, CMake supports many more build systems, which use different commands to run the build.
If you are not sure what the appropriate build command is, you can run ``cmake --build`` to allow CMake to start the build using whatever build system is being used.
.. commonerrors::
CMake allows you to switch between several types of builds including default, Debug, and Release.
Programs and libraries compiled as release builds can run *much* faster than those from other types of builds.
Thus, it is important to perform Release builds of all software released for production or where runtime is a concern.
Some integrated development environments such as Microsoft Visual Studio allow you to specify the different build types within the build system.
But for other build programs, like :command:`make`, you have to specify the build type in the :cmake:variable:`CMAKE_BUILD_TYPE` CMake configuration variable, which is described in :secref:`building:Configuring |VTKm|`.
CMake creates several build "targets" that specify the group of things to build.
The default target builds all of |VTKm|'s libraries as well as tests, examples, and benchmarks if enabled.
The ``test`` target executes each of the |VTKm| regression tests and verifies they complete successfully on the system.
The ``install`` target copies the subset of files required to use |VTKm| to a common installation directory.
The ``install`` target may need to be run as an administrator user if the installation directory is a system directory.
.. didyouknow::
|VTKm| contains a significant amount of regression tests.
If you are not concerned with testing a build on a given system, you can turn off building the testing, benchmarks, and examples using the CMake configuration variables described in :secref:`building:Configuring |VTKm|`.
This can shorten the |VTKm| compile time.
------------------------------
Linking to |VTKm|
------------------------------
Ultimately, the value of |VTKm| is the ability to link it into external projects that you write.
The header files and libraries installed with |VTKm| are typical, and thus you can link |VTKm| into a software project using any type of build system.
However, |VTKm| comes with several CMake configuration files that simplify linking |VTKm| into another project that is also managed by CMake.
Thus, the documentation in this section is specifically for finding and configuring |VTKm| for CMake projects.
.. index::
pair: CMake; VTK-m package
|VTKm| can be configured from an external project using the :cmake:command:`find_package` CMake function.
The behavior and use of this function is well described in the CMake documentation.
The first argument to :cmake:command:`find_package` is the name of the package, which in this case is ``VTKm``.
CMake configures this package by looking for a file named :file:`VTKmConfig.cmake`, which will be located in the :file:`lib/cmake/vtkm-<\VTKm version>` directory of the install or build of |VTKm|.
The configurable CMake variable :cmake:variable:`CMAKE_PREFIX_PATH` can be set to the build or install directory, the :cmake:envvar:`CMAKE_PREFIX_PATH` environment variable can likewise be set, or \cmakevar{VTKm_DIR} can be set to the directory that contains this file.
.. code-block:: cmake
:caption: Loading |VTKm| configuration from an external CMake project.
find_package(VTKm REQUIRED)
.. didyouknow::
The CMake :cmake:command:`find_package` function also supports several features not discussed here including specifying a minimum or exact version of |VTKm| and turning off some of the status messages.
See the CMake documentation for more details.
.. index::
triple: CMake ; VTK-m package ; libraries
When you load the |VTKm| package in CMake, several libraries are defined.
Projects building with |VTKm| components should link against one or more of these libraries as appropriate, typically with the :cmake:command:`target_link_libraries` command.
.. code-block:: cmake
:caption: Linking |VTKm| code into an external program.
find_package(VTKm REQUIRED)
add_executable(myprog myprog.cxx)
target_link_libraries(myprog vtkm::filter)
Several library targets are provided, but most projects will need to link in one or more of the following.
..
Note that I am documenting the VTK-m targets as CMake variables. This is
because the Sphinx extension for the CMake domain that I am using currently
does not support documenting targets.
.. cmake:variable:: vtkm::cont
Contains the base objects used to control |VTKm|.
.. cmake:variable:: vtkm::filter
Contains |VTKm|'s pre-built filters.
Applications that are looking to use VTK-m filters will need to link to this library.
The filters are further broken up into several smaller library packages (such as :cmake:variable:`vtkm::filter_contour`, :cmake:variable`vtkm::filter_flow`, :cmake:variable:`vtkm::filter_field_transform`, and many more.
:cmake:variable:`vtkm::filter` is actually a meta library that links all of these filter libraries to a CMake target.
.. cmake:variable:: vtkm::io
Contains |VTKm|'s facilities for interacting with files.
For example, reading and writing png, NetBPM, and VTK files.
.. cmake:variable:: vtkm::rendering
Contains |VTKm|'s rendering components.
This library is only available if :cmake:variable:`VTKm_ENABLE_RENDERING` is set to true.
.. cmake:variable:: vtkm::source
Contains |VTKm|'s pre-built dataset generators suchas Wavelet, Tangle, and Oscillator.
Most applications will not need to link to this library.
.. didyouknow::
The "libraries" made available in the |VTKm| do more than add a library to the linker line.
These libraries are actually defined as external targets that establish several compiler flags, like include file directories.
Many CMake packages require you to set up other target options to compile correctly, but for |VTKm| it is sufficient to simply link against the library.
.. commonerrors::
Because the |VTKm| CMake libraries do more than set the link line, correcting the link libraries can do more than fix link problems.
For example, if you are getting compile errors about not finding |VTKm| header files, then you probably need to link to one of |VTKm|'s libraries to fix the problem rather than try to add the include directories yourself.
.. index::
triple: CMake; VTK-m package; variables
The following is a list of all the CMake variables defined when the \textcode{find_package} function completes.
.. cmake:variable:: VTKm_FOUND
Set to true if the |VTKm| CMake package is successfully loaded.
If :cmake:command:`find_package` was not called with the ``REQUIRED`` option, then this variable should be checked before attempting to use |VTKm|.
.. cmake:variable:: VTKm_VERSION
The version number of the loaded |VTKm| package.
This is in the form "major.minor".
.. cmake:variable:: VTKm_VERSION_FULL
The extended version number of the |VTKm| package including patch and in-between-release information.
This is in the form "major.minor.patch[.gitsha1]" where "gitsha" is only included if the source code is in between releases.
.. cmake:variable:: VTKm_VERSION_MAJOR
The major |VTKm| version number.
.. cmake:variable:: VTKm_VERSION_MINOR
The minor |VTKm| version number.
.. cmake:variable:: VTKm_VERSION_PATCH
The patch |VTKm| version number.
.. cmake:variable:: VTKm_ENABLE_CUDA
Set to true if |VTKm| was compiled for CUDA.
.. cmake:variable:: VTKm_ENABLE_Kokkos
Set to true if |VTKm| was compiled with Kokkos.
.. cmake:variable:: VTKm_ENABLE_OPENMP
Set to true if |VTKm| was compiled for OpenMP.
.. cmake:variable:: VTKm_ENABLE_TBB
Set to true if |VTKm| was compiled for TBB.
.. cmake:variable:: VTKm_ENABLE_RENDERING
Set to true if the |VTKm| rendering library was compiled.
.. cmake:variable:: VTKm_ENABLE_MPI
Set to true if |VTKm| was compiled with MPI support.
These package variables can be used to query whether optional components are supported before they are used in your CMake configuration.
.. code-block:: cmake
:caption: Using an optional component of |VTKm|.
find_package(VTKm REQUIRED)
if (NOT VTKm::ENABLE::RENDERING)
message(FATAL_ERROR "VTK-m must be built with rendering on.")
endif()
add_executable(myprog myprog.cxx)
target_link_libraries(myprog vtkm::cont vtkm::rendering)

102
docs/users-guide/conf.py Normal file

@ -0,0 +1,102 @@
##============================================================================
## 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.
##============================================================================
# Configuration file for the Sphinx documentation builder.
#
# For the full list of built-in configuration values, see the documentation:
# https://www.sphinx-doc.org/en/master/usage/configuration.html
# -- Project information -----------------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information
project = "The VTK-m User's Guide"
copyright = 'Kitware Inc., National Technology & Engineering Solutions of Sandia LLC, UT-Battelle LLC, Los Alamos National Security LLC'
author = 'Kenneth Moreland'
version = '@VTKm_VERSION_FULL@'
release = '@VTKm_VERSION_FULL@'
# -- General configuration ---------------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration
# We provide some custom extensions in the _ext directory
import sys
sys.path.append('@CMAKE_CURRENT_SOURCE_DIR@/_ext')
extensions = [
'sphinx.ext.autosectionlabel',
'sphinx.ext.mathjax',
'sphinx.ext.todo',
# Extension available from https://breathe.readthedocs.io/en/stable/
'breathe',
# Extension available from https://sphinx-themes.org/sample-sites/sphinx-rtd-theme/
# Can be installed with `pip install sphinx-rtd-theme`
'sphinx_rtd_theme',
# Extension available from https://github.com/scikit-build/moderncmakedomain
# Can be installed with `pip install sphinxcontrib-moderncmakedomain`
'sphinxcontrib.moderncmakedomain',
# Extensions included in the _ext directory.
'extract_examples',
'fullref',
'infoboxes',
]
# Note: there are some custom extensions at the bottom of this file.
todo_include_todos = True
numfig = True
autosectionlabel_prefix_document = True
#templates_path = ['_templates']
exclude_patterns = ['CMakeFiles', '*.cmake', '.DS_Store']
primary_domain = 'cpp'
highlight_language = 'cpp'
numfig = True
numfig_format = {
'figure': 'Figure %s',
'table': 'Table %s',
'code-block': 'Example %s',
'section': '%s',
}
today_fmt = '%B %d, %Y'
rst_prolog = '''
.. |VTKm| replace:: VTKm
.. |report-year| replace:: 2023
.. |report-number| replace:: ORNL/TM-2023/2863
'''
breathe_projects = { 'vtkm': '@doxygen_xml_output_dir@' }
breathe_default_project = 'vtkm'
example_directory = '@example_directory@'
example_command_comment = '////'
example_language = 'cpp'
# -- Options for HTML output -------------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output
#html_theme = 'alabaster'
#html_theme = 'sphinxdoc'
#html_theme = 'bizstyle'
#html_theme = 'classic'
html_theme = 'sphinx_rtd_theme'
#html_static_path = ['_static']
# -- Options for LaTeX output -------------------------------------------------
latex_toplevel_sectioning = 'part'

@ -0,0 +1,17 @@
---
# This configuration requires clang-format 3.8 or higher.
BasedOnStyle: Mozilla
AlignAfterOpenBracket: Align
AlignOperands: false
AlwaysBreakAfterReturnType: None
AlwaysBreakAfterDefinitionReturnType: None
BreakBeforeBraces: Allman
BinPackArguments: false
BinPackParameters: false
ColumnLimit: 89
MaxEmptyLinesToKeep: 4
Standard: Cpp11
# This requires clang-format 4.0 (at least).
#FixNamespaceComments: true
ReflowComments: false
...

@ -0,0 +1,51 @@
##============================================================================
## 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.
##============================================================================
set(examples
GuideExampleCoreDataTypes.cxx
)
vtkm_unit_tests(
SOURCES ${examples}
)
# Special example that is an encapsulated program
# VTKm examples expects vtkm libraries to be namespaced with the prefix vtkm::.
# However as the examples are also built as just another part of the VTK-m code
# those prefix are not added to the targets (This happens during the
# installation). To workaround this issue here, we create IMPORTED libs linking
# to the vtkm libraries used by the examples with expected the vtkm:: prefix.
vtkm_module_get_list(module_list)
foreach(tgt IN LISTS module_list)
if(TARGET ${tgt})
# The reason of creating this phony IMPORTED libraries instead of making
# ALIAS libraries is that ALIAS libraries are GLOBAL whereas IMPORTED are
# local at the directory level where they are created. We do not want these
# phony targets to be visible outside of the example directory.
vtkm_target_mangle(tgt_name_mangled ${tgt})
add_library("vtkm::${tgt_name_mangled}" INTERFACE IMPORTED)
target_link_libraries("vtkm::${tgt_name_mangled}" INTERFACE ${tgt})
endif()
endforeach()
add_library(vtkm::filter INTERFACE IMPORTED)
target_link_libraries(vtkm::filter INTERFACE vtkm_filter)
#add the directory that contains the VTK-m config file to the cmake
#path so that our examples can find VTK-m
set(CMAKE_PREFIX_PATH ${VTKm_BINARY_DIR}/${VTKm_INSTALL_CONFIG_DIR})
include(VTKmQuickStart.cmake)
set_target_properties(VTKmQuickStart
PROPERTIES
RUNTIME_OUTPUT_DIRECTORY ${VTKm_EXECUTABLE_OUTPUT_PATH}
)
add_test(NAME VTKmQuickStart
COMMAND VTKmQuickStart ${VTKm_SOURCE_DIR}/data/data/unstructured/cow.vtk
)

@ -0,0 +1,329 @@
//============================================================================
// 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/Range.h>
#include <vtkm/Types.h>
#include <vtkm/VecVariable.h>
#include <vtkm/testing/Testing.h>
namespace
{
void SimpleVectorTypes()
{
////
//// BEGIN-EXAMPLE SimpleVectorTypes
////
vtkm::Vec2f A(1); // A is (1, 1)
A[1] = 3; // A is (1, 3) now
vtkm::Vec2f B = { 4, 5 }; // B is (4, 5)
vtkm::Vec2f C = A + B; // C is (5, 8)
vtkm::FloatDefault manhattanDistance = C[0] + C[1];
////
//// END-EXAMPLE SimpleVectorTypes
////
VTKM_TEST_ASSERT(test_equal(A, vtkm::make_Vec(1, 3)));
VTKM_TEST_ASSERT(test_equal(B, vtkm::make_Vec(4, 5)));
VTKM_TEST_ASSERT(test_equal(C, vtkm::make_Vec(5, 8)));
VTKM_TEST_ASSERT(test_equal(manhattanDistance, 13));
}
void CreatingVectorTypes()
{
////
//// BEGIN-EXAMPLE CreatingVectorTypes
////
vtkm::Vec3f_32 A{ 1 }; // A is (1, 1, 1)
A[1] = 2; // A is now (1, 2, 1)
vtkm::Vec3f_32 B{ 1, 2, 3 }; // B is (1, 2, 3)
vtkm::Vec3f_32 C = vtkm::make_Vec(3, 4, 5); // C is (3, 4, 5)
// Longer Vecs specified with template.
vtkm::Vec<vtkm::Float32, 5> D{ 1 }; // D is (1, 1, 1, 1, 1)
vtkm::Vec<vtkm::Float32, 5> E{ 1, 2, 3, 4, 5 }; // E is (1, 2, 3, 4, 5)
vtkm::Vec<vtkm::Float32, 5> F = { 6, 7, 8, 9, 10 }; // F is (6, 7, 8, 9, 10)
auto G = vtkm::make_Vec(1, 3, 5, 7, 9); // G is (1, 3, 5, 7, 9)
////
//// END-EXAMPLE CreatingVectorTypes
////
VTKM_TEST_ASSERT((A[0] == 1) && (A[1] == 2) && (A[2] == 1),
"A is different than expected.");
VTKM_TEST_ASSERT((B[0] == 1) && (B[1] == 2) && (B[2] == 3),
"B is different than expected.");
VTKM_TEST_ASSERT((C[0] == 3) && (C[1] == 4) && (C[2] == 5),
"C is different than expected.");
VTKM_TEST_ASSERT((D[0] == 1) && (D[1] == 1) && (D[2] == 1) && (D[3] == 1) &&
(D[4] == 1),
"D is different than expected.");
VTKM_TEST_ASSERT((E[0] == 1) && (E[1] == 2) && (E[2] == 3) && (E[3] == 4) &&
(E[4] == 5),
"E is different than expected.");
VTKM_TEST_ASSERT((F[0] == 6) && (F[1] == 7) && (F[2] == 8) && (F[3] == 9) &&
(F[4] == 10),
"F is different than expected.");
VTKM_TEST_ASSERT((G[0] == 1) && (G[1] == 3) && (G[2] == 5) && (G[3] == 7) &&
(G[4] == 9),
"F is different than expected.");
}
void VectorOperations()
{
////
//// BEGIN-EXAMPLE VectorOperations
////
vtkm::Vec3f_32 A{ 1, 2, 3 };
vtkm::Vec3f_32 B{ 4, 5, 6.5 };
vtkm::Vec3f_32 C = A + B; // C is (5, 7, 9.5)
vtkm::Vec3f_32 D = 2.0f * C; // D is (10, 14, 19)
vtkm::Float32 s = vtkm::Dot(A, B); // s is 33.5
bool b1 = (A == B); // b1 is false
bool b2 = (A == vtkm::make_Vec(1, 2, 3)); // b2 is true
vtkm::Vec<vtkm::Float32, 5> E{ 1, 2.5, 3, 4, 5 }; // E is (1, 2, 3, 4, 5)
vtkm::Vec<vtkm::Float32, 5> F{ 6, 7, 8.5, 9, 10.5 }; // F is (6, 7, 8, 9, 10)
vtkm::Vec<vtkm::Float32, 5> G = E + F; // G is (7, 9.5, 11.5, 13, 15.5)
bool b3 = (E == F); // b3 is false
bool b4 = (G == vtkm::make_Vec(7.f, 9.5f, 11.5f, 13.f, 15.5f)); // b4 is true
////
//// END-EXAMPLE VectorOperations
////
VTKM_TEST_ASSERT(test_equal(C, vtkm::Vec3f_32(5, 7, 9.5)), "C is wrong");
VTKM_TEST_ASSERT(test_equal(D, vtkm::Vec3f_32(10, 14, 19)), "D is wrong");
VTKM_TEST_ASSERT(test_equal(s, 33.5), "s is wrong");
VTKM_TEST_ASSERT(!b1, "b1 is wrong");
VTKM_TEST_ASSERT(b2, "b2 is wrong");
VTKM_TEST_ASSERT(!b3, "b3 is wrong");
VTKM_TEST_ASSERT(b4, "b4 is wrong");
}
void EquilateralTriangle()
{
////
//// BEGIN-EXAMPLE EquilateralTriangle
////
vtkm::Vec<vtkm::Vec2f_32, 3> equilateralTriangle = { { 0.0f, 0.0f },
{ 1.0f, 0.0f },
{ 0.5f, 0.8660254f } };
////
//// END-EXAMPLE EquilateralTriangle
////
vtkm::Float32 edgeLengthSqr = 1.0;
vtkm::Vec<vtkm::Vec2f_32, 3> edges(equilateralTriangle[1] - equilateralTriangle[0],
equilateralTriangle[2] - equilateralTriangle[0],
equilateralTriangle[2] - equilateralTriangle[1]);
VTKM_TEST_ASSERT(test_equal(vtkm::Dot(edges[0], edges[0]), edgeLengthSqr),
"Bad edge length.");
VTKM_TEST_ASSERT(test_equal(vtkm::Dot(edges[1], edges[1]), edgeLengthSqr),
"Bad edge length.");
VTKM_TEST_ASSERT(test_equal(vtkm::Dot(edges[2], edges[2]), edgeLengthSqr),
"Bad edge length.");
}
////
//// BEGIN-EXAMPLE VecCExample
////
VTKM_EXEC vtkm::VecCConst<vtkm::IdComponent> HexagonIndexToIJK(vtkm::IdComponent index)
{
static const vtkm::IdComponent HexagonIndexToIJKTable[8][3] = {
{ 0, 0, 0 }, { 1, 0, 0 }, { 1, 1, 0 }, { 0, 1, 0 },
{ 0, 0, 1 }, { 1, 0, 1 }, { 1, 1, 1 }, { 0, 1, 1 }
};
return vtkm::make_VecC(HexagonIndexToIJKTable[index], 3);
}
VTKM_EXEC vtkm::IdComponent HexagonIJKToIndex(vtkm::VecCConst<vtkm::IdComponent> ijk)
{
static const vtkm::IdComponent HexagonIJKToIndexTable[2][2][2] = { {
// i=0
{ 0, 4 }, // j=0
{ 3, 7 }, // j=1
},
{
// i=1
{ 1, 5 }, // j=0
{ 2, 6 }, // j=1
} };
return HexagonIJKToIndexTable[ijk[0]][ijk[1]][ijk[2]];
}
////
//// END-EXAMPLE VecCExample
////
////
//// BEGIN-EXAMPLE VecVariableExample
////
vtkm::VecVariable<vtkm::IdComponent, 4> HexagonShortestPath(vtkm::IdComponent startPoint,
vtkm::IdComponent endPoint)
{
vtkm::VecCConst<vtkm::IdComponent> startIJK = HexagonIndexToIJK(startPoint);
vtkm::VecCConst<vtkm::IdComponent> endIJK = HexagonIndexToIJK(endPoint);
vtkm::IdComponent3 currentIJK;
startIJK.CopyInto(currentIJK);
vtkm::VecVariable<vtkm::IdComponent, 4> path;
path.Append(startPoint);
for (vtkm::IdComponent dimension = 0; dimension < 3; dimension++)
{
if (currentIJK[dimension] != endIJK[dimension])
{
currentIJK[dimension] = endIJK[dimension];
path.Append(HexagonIJKToIndex(currentIJK));
}
}
return path;
}
////
//// END-EXAMPLE VecVariableExample
////
void UsingVecCAndVecVariable()
{
vtkm::VecVariable<vtkm::IdComponent, 4> path;
path = HexagonShortestPath(2, 2);
VTKM_TEST_ASSERT(test_equal(path, vtkm::Vec<vtkm::IdComponent, 1>(2)), "Bad path");
path = HexagonShortestPath(0, 7);
VTKM_TEST_ASSERT(test_equal(path, vtkm::IdComponent3(0, 3, 7)), "Bad path");
path = HexagonShortestPath(5, 3);
VTKM_TEST_ASSERT(test_equal(path, vtkm::IdComponent4(5, 4, 7, 3)), "Bad path");
}
void UsingRange()
{
////
//// BEGIN-EXAMPLE UsingRange
////
vtkm::Range range; // default constructor is empty range
bool b1 = range.IsNonEmpty(); // b1 is false
range.Include(0.5); // range now is [0.5 .. 0.5]
bool b2 = range.IsNonEmpty(); // b2 is true
bool b3 = range.Contains(0.5); // b3 is true
bool b4 = range.Contains(0.6); // b4 is false
range.Include(2.0); // range is now [0.5 .. 2]
bool b5 = range.Contains(0.5); // b3 is true
bool b6 = range.Contains(0.6); // b4 is true
range.Include(vtkm::Range(-1, 1)); // range is now [-1 .. 2]
//// PAUSE-EXAMPLE
VTKM_TEST_ASSERT(test_equal(range, vtkm::Range(-1, 2)), "Bad range");
//// RESUME-EXAMPLE
range.Include(vtkm::Range(3, 4)); // range is now [-1 .. 4]
//// PAUSE-EXAMPLE
VTKM_TEST_ASSERT(test_equal(range, vtkm::Range(-1, 4)), "Bad range");
//// RESUME-EXAMPLE
vtkm::Float64 lower = range.Min; // lower is -1
vtkm::Float64 upper = range.Max; // upper is 4
vtkm::Float64 length = range.Length(); // length is 5
vtkm::Float64 center = range.Center(); // center is 1.5
////
//// END-EXAMPLE UsingRange
////
VTKM_TEST_ASSERT(!b1, "Bad non empty.");
VTKM_TEST_ASSERT(b2, "Bad non empty.");
VTKM_TEST_ASSERT(b3, "Bad contains.");
VTKM_TEST_ASSERT(!b4, "Bad contains.");
VTKM_TEST_ASSERT(b5, "Bad contains.");
VTKM_TEST_ASSERT(b6, "Bad contains.");
VTKM_TEST_ASSERT(test_equal(lower, -1), "Bad lower");
VTKM_TEST_ASSERT(test_equal(upper, 4), "Bad upper");
VTKM_TEST_ASSERT(test_equal(length, 5), "Bad length");
VTKM_TEST_ASSERT(test_equal(center, 1.5), "Bad center");
}
void UsingBounds()
{
////
//// BEGIN-EXAMPLE UsingBounds
////
vtkm::Bounds bounds; // default constructor makes empty
bool b1 = bounds.IsNonEmpty(); // b1 is false
bounds.Include(vtkm::make_Vec(0.5, 2.0, 0.0)); // bounds contains only
// the point [0.5, 2, 0]
bool b2 = bounds.IsNonEmpty(); // b2 is true
bool b3 = bounds.Contains(vtkm::make_Vec(0.5, 2.0, 0.0)); // b3 is true
bool b4 = bounds.Contains(vtkm::make_Vec(1, 1, 1)); // b4 is false
bool b5 = bounds.Contains(vtkm::make_Vec(0, 0, 0)); // b5 is false
bounds.Include(vtkm::make_Vec(4, -1, 2)); // bounds is region [0.5 .. 4] in X,
// [-1 .. 2] in Y,
// and [0 .. 2] in Z
//// PAUSE-EXAMPLE
VTKM_TEST_ASSERT(test_equal(bounds, vtkm::Bounds(0.5, 4, -1, 2, 0, 2)), "");
//// RESUME-EXAMPLE
bool b6 = bounds.Contains(vtkm::make_Vec(0.5, 2.0, 0.0)); // b6 is true
bool b7 = bounds.Contains(vtkm::make_Vec(1, 1, 1)); // b7 is true
bool b8 = bounds.Contains(vtkm::make_Vec(0, 0, 0)); // b8 is false
vtkm::Bounds otherBounds(vtkm::make_Vec(0, 0, 0), vtkm::make_Vec(3, 3, 3));
// otherBounds is region [0 .. 3] in X, Y, and Z
bounds.Include(otherBounds); // bounds is now region [0 .. 4] in X,
// [-1 .. 3] in Y,
// and [0 .. 3] in Z
//// PAUSE-EXAMPLE
VTKM_TEST_ASSERT(test_equal(bounds, vtkm::Bounds(0, 4, -1, 3, 0, 3)), "");
//// RESUME-EXAMPLE
vtkm::Vec3f_64 lower(bounds.X.Min, bounds.Y.Min, bounds.Z.Min);
// lower is [0, -1, 0]
vtkm::Vec3f_64 upper(bounds.X.Max, bounds.Y.Max, bounds.Z.Max);
// upper is [4, 3, 3]
vtkm::Vec3f_64 center = bounds.Center(); // center is [2, 1, 1.5]
////
//// END-EXAMPLE UsingBounds
////
VTKM_TEST_ASSERT(!b1, "Bad non empty.");
VTKM_TEST_ASSERT(b2, "Bad non empty.");
VTKM_TEST_ASSERT(b3, "Bad contains.");
VTKM_TEST_ASSERT(!b4, "Bad contains.");
VTKM_TEST_ASSERT(!b5, "Bad contains.");
VTKM_TEST_ASSERT(b6, "Bad contains.");
VTKM_TEST_ASSERT(b7, "Bad contains.");
VTKM_TEST_ASSERT(!b8, "Bad contains.");
VTKM_TEST_ASSERT(test_equal(lower, vtkm::make_Vec(0, -1, 0)), "");
VTKM_TEST_ASSERT(test_equal(upper, vtkm::make_Vec(4, 3, 3)), "");
VTKM_TEST_ASSERT(test_equal(center, vtkm::make_Vec(2.0, 1.0, 1.5)), "");
}
void Test()
{
SimpleVectorTypes();
CreatingVectorTypes();
VectorOperations();
EquilateralTriangle();
UsingVecCAndVecVariable();
UsingRange();
UsingBounds();
}
} // anonymous namespace
int GuideExampleCoreDataTypes(int argc, char* argv[])
{
return vtkm::testing::Testing::Run(Test, argc, argv);
}

@ -0,0 +1,25 @@
##=============================================================================
##
## 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.
##
##=============================================================================
####
#### BEGIN-EXAMPLE QuickStartCMakeLists.txt
####
cmake_minimum_required(VERSION 3.13)
project(VTKmQuickStart CXX)
find_package(VTKm REQUIRED)
add_executable(VTKmQuickStart VTKmQuickStart.cxx)
target_link_libraries(VTKmQuickStart vtkm::filter vtkm::rendering)
####
#### END-EXAMPLE QuickStartCMakeLists.txt
####

@ -0,0 +1,100 @@
//=============================================================================
//
// 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.
//
//=============================================================================
////
//// BEGIN-EXAMPLE VTKmQuickStart
////
#include <vtkm/cont/Initialize.h>
#include <vtkm/io/VTKDataSetReader.h>
#include <vtkm/filter/mesh_info/MeshQuality.h>
#include <vtkm/rendering/Actor.h>
#include <vtkm/rendering/CanvasRayTracer.h>
#include <vtkm/rendering/MapperRayTracer.h>
#include <vtkm/rendering/Scene.h>
#include <vtkm/rendering/View3D.h>
////
//// BEGIN-EXAMPLE VTKmQuickStartInitialize
////
int main(int argc, char* argv[])
{
vtkm::cont::Initialize(argc, argv);
////
//// END-EXAMPLE VTKmQuickStartInitialize
////
if (argc != 2)
{
std::cerr << "USAGE: " << argv[0] << " <file.vtk>" << std::endl;
return 1;
}
// Read in a file specified in the first command line argument.
////
//// BEGIN-EXAMPLE VTKmQuickStartReadFile
////
vtkm::io::VTKDataSetReader reader(argv[1]);
vtkm::cont::DataSet inData = reader.ReadDataSet();
////
//// END-EXAMPLE VTKmQuickStartReadFile
////
//// PAUSE-EXAMPLE
inData.PrintSummary(std::cout);
//// RESUME-EXAMPLE
// Run the data through the elevation filter.
////
//// BEGIN-EXAMPLE VTKmQuickStartFilter
////
vtkm::filter::mesh_info::MeshQuality cellArea(
vtkm::filter::mesh_info::CellMetric::Area);
vtkm::cont::DataSet outData = cellArea.Execute(inData);
////
//// END-EXAMPLE VTKmQuickStartFilter
////
// Render an image and write it out to a file.
////
//// BEGIN-EXAMPLE VTKmQuickStartRender
////
//// LABEL scene-start
vtkm::rendering::Actor actor(
outData.GetCellSet(), outData.GetCoordinateSystem(), outData.GetField("area"));
vtkm::rendering::Scene scene;
//// LABEL scene-end
scene.AddActor(actor);
vtkm::rendering::MapperRayTracer mapper;
vtkm::rendering::CanvasRayTracer canvas(1280, 1024);
//// LABEL view
vtkm::rendering::View3D view(scene, mapper, canvas);
//// LABEL paint
view.Paint();
//// LABEL save
view.SaveAs("image.png");
////
//// END-EXAMPLE VTKmQuickStartRender
////
return 0;
}
////
//// END-EXAMPLE VTKmQuickStart
////

@ -0,0 +1,7 @@
==============================
Index
==============================
..
This is placeholder to put the geneated index in the table of context.
https://stackoverflow.com/questions/36235578/how-can-i-include-the-genindex-in-a-sphinx-toc

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:9c8577c28da9c422e9c1b3eb4e2b86502237b4e28de7f89d9fde4daac551e35a
size 45824

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:569d90224e67af812d99bf597cab96b06bd75b0f6e49b31a44db6d0dd2fcf9d8
size 17473

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:09869e65d5b2e9c8e5f4b6ade05a07ccdca2d631afc4dba71182bd488d4af3b1
size 59566

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:94c519604ede743c346bbbe6ad327afd994cfc66dd2a7044fac54a99be72c683
size 765497

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:fe656884ba6a65c9241fe4ac1fdf0342f1ff0616efc14e745d417ccdd151c9fc
size 17966

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:abce0e365bdd079734931ff8cb50dc9e8a0b99fa58e5f7c28b7ccfd1fd36a48d
size 134860

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:7d9933aa10a88c653b9306ef79f9082e7fbb33065668b44aa7b46f677dd93f74
size 18581

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:1ba8be9278d541b02ac603f0b6f68bbc2d1b34f6e9aba82881200d09c919f74c
size 42684

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:89d1e524f9bfcdbb950cfe96c23e13c207dbbde6ee45d2aab773ebf020e99ba8
size 13394

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:b6613cc596bfe2558c7cb491c8c0bd63e5bb4cace59b5c1b90beed43ffb81fe3
size 1397

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:e6919ed64154fb791fa9f7f6a7841314effcea456fed0427946c294416a95abf
size 89920

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:e426c1c2360cd131799eb949a1c4b52752bd5eb64f69b701301b1a3e11711a6c
size 171944

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:5f98d23244b645f4301b6717394cd3a95c3ec60d980081b1519006cdab75cee6
size 54147

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:f2dc062c33b7767c08d45d177a573af1ff13ccd2d41a87ccd2b6538336763781
size 108739

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:cee96e1f16e817b823768d525ff8b9faa388b2054fa0a9f7e2688134cc473fde
size 77653

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:c5af23e99d2f3eadafcd8d7f3f907dfb21c9e6533eff73870c38d561527ff273
size 15328

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:10669565c1f742c0b9e916d6f73d614b721e78752496a88fe5ef9ca579c7f6a9
size 806559

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:2e63593dcf59541ebedacaeb86680bb334e93089ba17dcda80e9602ce4a6fe2b
size 7759

@ -0,0 +1,56 @@
.. title page
==============================
The VTK-m User's Guide
==============================
.. todo:: Hide TODOs for release documentation.
| **The VTK-m User's Guide**
| Version |version|
Kenneth Moreland
with special contributions from
Vicente Bolea,
Hank Childs,
Nickolas Davis,
Mark Kim,
James Kress,
Matthew Letter,
Li-Ta Lo,
Robert Maynard,
Sujin Philip,
David Pugmire,
Nick Thompson,
Allison Vacanti,
Abhishek Yenpure,
and the |VTKm| community
Moreland, K. (|report-year|). *The VTK-m User's Guide*, Tech report |report-number|, Oak Ridge National Laboratory.
.. centered:: Join the VTK-m Community at http://m.vtk.org.
.. todo:: The centered directive is deprecated (https://www.sphinx-doc.org/en/master/usage/restructuredtext/directives.html#directive-centered). Figure out how to add rst-class to center.
.. toctree::
:numbered:
:maxdepth: 2
:caption: VTK-m User's Guide
part-getting-started.rst
part-using.rst
part-developing.rst
part-advanced.rst
part-core.rst
part-appendix.rst
..
Indices and tables
==================
* :ref:`genindex`
* :ref:`modindex`
* :ref:`search`

@ -0,0 +1,86 @@
==============================
Introduction
==============================
High-performance computing relies on ever finer threading.
Advances in processor technology include ever greater numbers of cores, hyperthreading, accelerators with integrated blocks of cores, and special vectorized instructions, all of which require more software parallelism to achieve peak performance.
Traditional visualization solutions cannot support this extreme level of concurrency.
Extreme scale systems require a new programming model and a fundamental change in how we design algorithms.
To address these issues we created |VTKm|: the visualization toolkit for multi-/many-core architectures.
|VTKm| supports a number of algorithms and the ability to design further algorithms through a top-down design with an emphasis on extreme parallelism.
|VTKm| also provides support for finding and building links across topologies, making it possible to perform operations that determine manifold surfaces, interpolate generated values, and find adjacencies.
Although |VTKm| provides a simplified high-level interface for programming, its template-based code removes the overhead of abstraction.
.. |MCCompareCuda| image:: images/MCCompareCuda.png
:width: 75px
.. |MCCompareVTKm| image:: images/MCCompareVTKm.png
:width: 75px
.. table:: Comparison of Marching Cubes implementations.
:name: MCCompare
:widths: auto
:align: center
+-----------------+-----------------+
| CUDA SDK | |VTKm| |
+-----------------+-----------------+
| 431 LOC | 265 LOC |
+-----------------+-----------------+
| |MCCompareCuda| | |MCCompareVTKm| |
+-----------------+-----------------+
|VTKm| simplifies the development of parallel scientific visualization algorithms by providing a framework of supporting functionality that allows developers to focus on visualization operations.
Consider the listings in :numref:`MCCompare` that compares the size of the implementation for the Marching Cubes algorithm in |VTKm| with the equivalent reference implementation in the CUDA software development kit.
Because |VTKm| internally manages the parallel distribution of work and data, the |VTKm| implementation is shorter and easier to maintain.
Additionally, |VTKm| provides data abstractions not provided by other libraries that make code written in |VTKm| more versatile.
------------------------------
How to Use This Guide
------------------------------
This user's guide is organized into 5 parts to help guide novice to advanced users and to provide a convenient reference.
:partref:`part-getting-started:Getting Started` provides a brief overview of using |VTKm|.
This part provides instructions on building |VTKm| and some simple examples of using |VTKm|.
Users new to |VTKm| are well served to read through Part :partref:`part-getting-started:Getting Started` first to become acquainted with the basic concepts.
The remaining parts, which provide detailed documentation of increasing complexity, have chapters that do not need to be read in detail.
Readers will likely find it useful to skip to specific topics of interest.
:partref:`part-using:Using |VTKm|` dives deeper into the |VTKm| library.
It provides much more detail on the concepts introduced in :partref:`part-getting-started:Getting Started` and introduces new topics helpful to people who use |VTKm|'s existing algorithms.
:partref:`part-developing:Developing Algorithms` documents how to use |VTKm|'s framework to develop new or custom visualization algorithms.
In this part we dive into the inner workings of filters and introduce the concept of a *worklet*, which is the base unit used to write a device-portable algorithm in |VTKm|.
:partref:`part-developing:Developing Algorithms` also documents many supporting functions that are helpful in implementing visualization algorithms.
:partref:`part-advanced:Advanced Development` explores in more detail how |VTKm| manages memory and devices.
This information describes how to adapt |VTKm| to custom data structures and new devices.
:partref:`part-core:Core Development` exposes the inner workings of |VTKm|.
These concepts allow you to design new algorithmic structures not already available in |VTKm|.
.. ------------------------------
.. Conventions Used in This Guide
.. ------------------------------
..
.. When documenting the |VTKm| API, the following conventions are used.
.. \begin{itemize}
.. \item Filenames are printed in a \textfilename{sans serif font}.
.. \item C++ code is printed in a \textcode{monospace font}.
.. \item Macros and namespaces from |VTKm| are printed in \textnamespace{red}.
.. \item Identifiers from |VTKm| are printed in \textidentifier{blue}.
.. \item Signatures, described in Chapter \ref{chap:SimpleWorklets}, and the
.. tags used in them are printed in \textsignature{green}.
.. \end{itemize}
..
.. This guide provides actual code samples throughout its discussions to
.. demonstrate their use. These examples are all valid code that can be
.. compiled and used although it is often the case that code snippets are
.. provided. In such cases, the code must be placed in a larger context.
.. didyouknow::
In this guide we periodically use these **Did you know?** boxes to provide additional information related to the topic at hand.
.. commonerrors::
**Common Errors** blocks are used to highlight some of the common problems or complications you might encounter when dealing with the topic of discussion.

@ -0,0 +1,9 @@
==============================
License
==============================
.. include:: ../../LICENSE.txt
:start-line: 3
:end-before: ==============================
All product names mentioned herein are the trademarks of their respective owners.

@ -0,0 +1,3 @@
==============================
Advanced Development
==============================

@ -0,0 +1,12 @@
==============================
Appendix
==============================
.. todolist::
.. toctree::
:maxdepth: 2
acknowledgements.rst
license.rst
genindex.rst

@ -0,0 +1,3 @@
==============================
Core Development
==============================

@ -0,0 +1,3 @@
==============================
Developing Algorithms
==============================

@ -0,0 +1,10 @@
==============================
Getting Started
==============================
.. toctree::
:maxdepth: 2
introduction.rst
building.rst
quick-start.rst

@ -0,0 +1,8 @@
==============================
Using |VTKm|
==============================
.. toctree::
:maxdepth: 2
base-types.rst

@ -0,0 +1,173 @@
==============================
Quick Start
==============================
In this chapter we go through the steps to create a simple program that uses |VTKm|.
This "hello world" example presents only the bare minimum of features available.
The remainder of this book documents dives into much greater detail.
We will call the example program we are building :file:`VTKmQuickStart`.
It will demonstrate reading data from a file, processing the data with a filter, and rendering an image of the data.
Readers who are less interested in an explanation and are more interested in browsing some code can skip to :secref:`quick-start:The Full Example`.
------------------------------
Initialize
------------------------------
.. index:: initialization
The first step to using |VTKm| is to initialize the library.
Although initializing |VTKm| is *optional*, it is recommend to allow |VTKm| to configure devices and logging.
Initialization is done by calling the :func:`vtkm::cont::Initialize` function.
The ``Initialize`` function is defined in the :file:`vtkm/cont/Initialize.h` header file.
``Initialize`` takes the ``argc`` and ``argv`` arguments that are passed to the ``main`` function of your program, find any command line arguments relevant to |VTKm|, and remove them from the list to make further command line argument processing easier.
.. load-example:: VTKmQuickStartInitialize
:file: VTKmQuickStart.cxx
:caption: Initializing |VTKm|.
.. todo:: Uncomment and add cross reference.
..
``Initialize`` has many options to customize command line argument processing.
See Chapter \ref{chap:Initialization} for more details.
.. didyouknow::
Don't have access to ``argc`` and ``argv``?
No problem.
You can call :func:`vtkm::cont::Initialize` with no arguments.
------------------------------
Reading a File
------------------------------
.. index::
single: file I/O ; read
single: read file
|VTKm| comes with a simple I/O library that can read and write files in VTK legacy format.
These files have a :file:`.vtk` extension.
VTK legacy files can be read using the :class:`vtkm::io::VTKDataSetReader` object, which is declared in the :file:`vtkm/io/VTKDataSetReader.h` header file.
The object is constructed with a string specifying the filename (which for this example we will get from the command line).
The data is then read in by calling the :member:`vtkm::io::VTKDataSetReader::ReadDataSet` method.
.. load-example:: VTKmQuickStartReadFile
:file: VTKmQuickStart.cxx
:caption: Reading data from a VTK legacy file.
.. todo:: Uncomment and cross reference.
..
The ``ReadDataSet`` method returns the data in a :class:`vtkm::cont::DataSet` object.
The structure and features of a ``DataSet`` object is described in Chapter \ref{chap:DataSet}.
For the purposes of this quick start, we will treat ``DataSet`` as a mostly opaque object that gets passed to and from operations in |VTKm|.
More information about |VTKm|'s file readers and writers can be found in Chapter \ref{chap:FileIO}.
------------------------------
Running a Filter
------------------------------
.. index:: filter
Algorithms in |VTKm| are encapsulated in units called *filters*.
A filter takes in a ``DataSet``, processes it, and returns a new ``DataSet``.
The returned ``DataSet`` often, but not always, contains data inherited from the source data.
.. todo:: Fix cross reference to Running Filters.
|VTKm| comes with many filters, which are documented in Chapter \ref{chap:RunningFilters}.
For this example, we will demonstrate the use of the :class:`vtkm::filter::MeshQuality` filter, which is defined in the :file:`vtkm/filter/MeshQuality.h` header file.
The ``MeshQuality`` filter will compute for each cell in the input data will compute a quantity representing some metric of the cell's shape.
Several metrics are available, and in this example we will find the area of each cell.
.. todo:: Fix cross reference to MeshQuality.
Like all filters, ``MeshQuality`` contains an ``Execute`` method that takes an input ``DataSet`` and produces an output ``DataSet``.
It also has several methods used to set up the parameters of the execution.
Section \ref{sec:MeshQuality} provides details on all the options of ``MeshQuality``.
Suffice it to say that in this example we instruct the filter to find the area of each cell, which it will output to a field named ``area``.
.. load-example:: VTKmQuickStartFilter
:file: VTKmQuickStart.cxx
:caption: Running a filter.
------------------------------
Rendering an Image
------------------------------
.. index:: rendering
Although it is possible to leverage external rendering systems, |VTKm| comes with its own self-contained image rendering algorithms.
These rendering classes are completely implemented with the parallel features provided by |VTKm|, so using rendering in |VTKm| does not require any complex library dependencies.
.. todo:: Fix cross reference to rendering chapter.
Even a simple rendering scene requires setting up several parameters to establish what is to be featured in the image including what data should be rendered, how that data should be represented, where objects should be placed in space, and the qualities of the image to generate.
Consequently, setting up rendering in |VTKm| involves many steps.
Chapter \ref{chap:Rendering} goes into much detail on the ways in which a rendering scene is specified.
For now, we just briefly present some boilerplate to achieve a simple rendering.
.. load-example:: VTKmQuickStartRender
:file: VTKmQuickStart.cxx
:caption: Rendering data.
.. index::
single: scene
single: actor
The first step in setting up a render is to create a *scene*.
A scene comprises some number of *actors*, which represent some data to be rendered in some location in space.
In our case we only have one ``DataSet`` to render, so we simply create a single actor and add it to a scene as shown in :exlineref:`Example {number} lines {line}<VTKmQuickStartRender:scene-start>` :exlineref:`-- %s<VTKmQuickStartRender:scene-end>`.
.. index::
single: view
single: mapper
single: canvas
The second step in setting up a render is to create a *view*.
The view comprises the aforementioned scene, a *mapper*, which describes how the data are to be rendered, and a *canvas*, which holds the image buffer and other rendering context.
The view is created in :exlineref:`VTKmQuickStartRender:view`.
The image generation is then performed by calling :member:`vtkm::rendering::View::Paint` on the view object (:exlineref:`VTKmQuickStartRender:paint`).
However, the rendering done by |VTKm|'s rendering classes is performed offscreen, which means that the result does not appear on your computer's monitor.
The easiest way to see the image is to save it to an image file using the :member:`vtkm::rendering::View::SaveAs` method (:exlineref:`VTKmQuickStartRender:save`).
------------------------------
The Full Example
------------------------------
Putting together the examples from the previous sections, here is a complete program for reading, processing, and rendering data with |VTKm|.
.. load-example:: VTKmQuickStart
:file: VTKmQuickStart.cxx
:caption: Simple example of using |VTKm|.
------------------------------
Build Configuration
------------------------------
.. index:: CMakeLists.txt
Now that we have the program listed in :numref:`ex:VTKmQuickStart`, we still need to compile it with the appropriate compilers and flags.
By far the easiest way to compile |VTKm| code is to use CMake.
CMake commands that can be used to link code to |VTKm| are discussed in :secref:`building:Linking to |VTKm|`.
The following example provides a minimal :file:`CMakeLists.txt` required to build this program.
.. load-example:: QuickStartCMakeLists.txt
:file: VTKmQuickStart.cmake
:caption: :file:`CMakeLists.txt` to build a program using |VTKm|.
:language: cmake
:command-comment: ####
The first two lines contain boilerplate for any :file:`CMakeLists.txt` file.
They all should declare the minimum CMake version required (for backward compatibility) and have a :cmake:command:`project` command to declare which languages are used.
The remainder of the commands find the |VTKm| library, declare the program begin compiled, and link the program to the |VTKm| library.
These steps are described in detail in :secref:`building:Linking to |VTKm|`.

@ -0,0 +1,10 @@
NAME
UsersGuide
GROUPS
Core
TESTING_DIR
examples
TEST_DEPENDS
vtkm_cont
vtkm_filter_mesh_info
vtkm_rendering

@ -151,16 +151,42 @@ namespace vtkm
//*****************************************************************************
// Typedefs for basic types.
//*****************************************************************************
/// Base type to use for 32-bit floating-point numbers.
///
using Float32 = float;
/// Base type to use for 64-bit floating-point numbers.
///
using Float64 = double;
/// Base type to use for 8-bit signed integer numbers.
///
using Int8 = int8_t;
/// Base type to use for 8-bit unsigned integer numbers.
///
using UInt8 = uint8_t;
/// Base type to use for 16-bit signed integer numbers.
///
using Int16 = int16_t;
/// Base type to use for 16-bit unsigned integer numbers.
///
using UInt16 = uint16_t;
/// Base type to use for 32-bit signed integer numbers.
///
using Int32 = int32_t;
/// Base type to use for 32-bit unsigned integer numbers.
///
using UInt32 = uint32_t;
/// Represents a component ID (index of component in a vector). The number
/// \brief Base type to use to index small lists.
///
/// This type represents a component ID (index of component in a vector). The number
/// of components, being a value fixed at compile time, is generally assumed
/// to be quite small. However, we are currently using a 32-bit width
/// integer because modern processors tend to access them more efficiently
@ -172,19 +198,31 @@ using IdComponent = vtkm::Int32;
using WordTypeDefault = vtkm::UInt32;
//In this order so that we exactly match the logic that exists in VTK
#if VTKM_SIZE_LONG_LONG == 8
#if (VTKM_SIZE_LONG_LONG == 8) || defined(VTKM_DOXYGEN_ONLY)
/// Base type to use for 64-bit signed integer numbers.
///
using Int64 = signed long long;
/// Base type to use for 64-bit signed integer numbers.
///
using UInt64 = unsigned long long;
#define VTKM_UNUSED_INT_TYPE long
#elif VTKM_SIZE_LONG == 8
/// Base type to use for 64-bit signed integer numbers.
///
using Int64 = signed long;
/// Base type to use for 64-bit unsigned integer numbers.
///
using UInt64 = unsigned long;
#define VTKM_UNUSED_INT_TYPE long long
#else
#error Could not find a 64-bit integer.
#endif
/// Represents an ID (index into arrays).
/// \brief Base type to use to index arrays.
///
/// This type represents an ID (index into arrays). It should be used whenever
/// indexing data that could grow arbitrarily large.
///
#ifdef VTKM_USE_64BIT_IDS
using Id = vtkm::Int64;
#else