-D CMAKE_CXX_COMPILER=${GITHUB_WORKSPACE}/kokkos/bin/nvcc_wrapper \
-D DEAL_II_CXX_FLAGS='-Werror -Wno-non-template-friend' \
-D DEAL_II_EARLY_DEPRECATIONS=ON \
- -D DEAL_II_WITH_CUDA="ON" \
-D DEAL_II_WITH_KOKKOS="ON" \
-D KOKKOS_DIR=${GITHUB_WORKSPACE}/../kokkos-install \
-D DEAL_II_WITH_MPI="ON" \
- name: build CUDA tests
run: |
cd build
- make -j2 setup_tests_cuda setup_tests_matrix_free_kokkos
- cd tests/cuda
- make -j2 compile_test_executables
- cd ../matrix_free_kokkos
+ make -j2 setup_tests_matrix_free_kokkos
+ cd tests/matrix_free_kokkos
make -j2 compile_test_executables
#############################
-D DEAL_II_FORCE_BUNDLED_BOOST=ON \
-D DEAL_II_CXX_FLAGS="-std=c++17" \
-D DEAL_II_EARLY_DEPRECATIONS=ON \
- -D DEAL_II_WITH_CUDA="ON" \
-D DEAL_II_WITH_KOKKOS="ON" \
-D KOKKOS_DIR=${GITHUB_WORKSPACE}/../kokkos-install \
-D DEAL_II_WITH_MPI="ON" \
- name: build CUDA tests
run: |
cd build
- make -j2 setup_tests_cuda setup_tests_matrix_free_kokkos
- cd tests/cuda
- make -j2 compile_test_executables
- cd ../matrix_free_kokkos
+ make -j2 setup_tests_matrix_free_kokkos
+ cd tests/matrix_free_kokkos
make -j2 compile_test_executables
# Now, set the project and set up the rest:
#
project(deal.II CXX C)
-enable_language_optional(Fortran)
verbose_include(${CMAKE_SOURCE_DIR}/cmake/setup_deal_ii.cmake)
set(DEAL_II_VECTORIZATION_WIDTH_IN_BITS 128)
endif()
-#
-# We need to disable SIMD vectorization for CUDA device code.
-# Otherwise, nvcc compilers from version 9 on will emit an error message like:
-# "[...] contains a vector, which is not supported in device code"
-#
-
-if(DEAL_II_WITH_CUDA)
- set(DEAL_II_VECTORIZATION_WIDTH_IN_BITS 0)
-endif()
-
#
# If we have OpenMP SIMD support (i.e. DEAL_II_HAVE_OPENMP_SIMD is true)
# populate DEAL_II_OPENMP_SIMD_PRAGMA.
# TODO: We might consider refactoring this option into an automatic check
# (in Modules/FindMPI.cmake) at some point. For the time being this is an
# advanced configuration option.
- #
- if(DEAL_II_MPI_WITH_CUDA_SUPPORT)
- option(DEAL_II_MPI_WITH_DEVICE_SUPPORT "Enable MPI Device support" ON)
- else()
- option(DEAL_II_MPI_WITH_DEVICE_SUPPORT "Enable MPI Device support" OFF)
- endif()
+ option(DEAL_II_MPI_WITH_DEVICE_SUPPORT "Enable MPI Device support" OFF)
mark_as_advanced(DEAL_II_MPI_WITH_DEVICE_SUPPORT)
endmacro()
+++ /dev/null
-## ------------------------------------------------------------------------
-##
-## SPDX-License-Identifier: LGPL-2.1-or-later
-## Copyright (C) 2022 - 2023 by the deal.II authors
-##
-## This file is part of the deal.II library.
-##
-## Part of the source code is dual licensed under Apache-2.0 WITH
-## LLVM-exception OR LGPL-2.1-or-later. Detailed license information
-## governing the source code and code contributions can be found in
-## LICENSE.md and CONTRIBUTING.md at the top level directory of deal.II.
-##
-## ------------------------------------------------------------------------
-
-#
-# Configuration for cuda support:
-#
-
-#
-# cuda support is experimental. Therefore, disable the feature per default:
-#
-set(DEAL_II_WITH_CUDA FALSE CACHE BOOL "")
-
-macro(feature_cuda_find_external var)
- if(DEAL_II_FEATURE_KOKKOS_BUNDLED_CONFIGURED)
- set(CUDA_ADDITIONAL_ERROR_STRING
- ${CUDA_ADDITIONAL_ERROR_STRING}
- "deal.II's bundled version of Kokkos only supports the Serial backend and therefore cannot be used with Cuda."
- )
- set(${var} FALSE)
- elseif(NOT Kokkos_ENABLE_CUDA)
- set(CUDA_ADDITIONAL_ERROR_STRING
- ${CUDA_ADDITIONAL_ERROR_STRING}
- "deal.II can only be compiled with Cuda support if Kokkos was built with Cuda support!"
- )
- set(${var} FALSE)
- else()
- # FIXME We need to also find and link with cuSolver and cuSparse even though
- # relying on Kokkos for linking with Cuda. That's why we keep the code below for now.
-
- # We need to set CUDA_USE_STATIC_CUDA_RUNTIME before find_package(CUDA) and to
- # force the value otherwise it is overwritten by find_package(CUDA)
- if(BUILD_SHARED_LIBS)
- set(CUDA_USE_STATIC_CUDA_RUNTIME OFF CACHE BOOL "" FORCE)
- endif()
-
- #
- # TODO: Ultimately, this find_package call is not needed any more. We
- # still use it because it is very convenient to (a) check that CUDA is
- # installed, (b) get compiler path and include directories / libraries.
- #
- find_package(DEAL_II_CUDA)
-
- if(CUDA_FOUND)
- #
- # CUDA was found, check whether we can actually use it:
- #
- set(${var} TRUE)
-
- #
- # disable CUDA support older than 10.2:
- #
- if(CUDA_VERSION VERSION_LESS 10.2)
- message(FATAL_ERROR "\n"
- "deal.II requires CUDA version 10.2 or newer."
- )
- endif()
-
- #
- # We do not support CUDA 12.0 and newer:
- #
- if(CUDA_VERSION VERSION_GREATER_EQUAL 12.0)
- message(FATAL_ERROR "\n"
- "deal.II's own CUDA backend does not support CUDA version 12.0 or newer.\n"
- "Instead, configure Kokkos with CUDA enabled."
- )
- endif()
-
- #
- # CUDA Toolkit 10 is incompatible with C++17.
- # Make sure that deal.II is configured appropriately
- #
- macro(_cuda_ensure_feature_off _version _cpp_version_bad _cpp_version_good)
- if(${CUDA_VERSION_MAJOR} EQUAL ${_version})
- if(${DEAL_II_HAVE_CXX${_cpp_version_bad}})
- set(${var} FALSE)
- message(STATUS "CUDA ${_version} requires ${_feature} to be set to off.")
- set(CUDA_ADDITIONAL_ERROR_STRING
- ${CUDA_ADDITIONAL_ERROR_STRING}
- "CUDA ${_version} is not compatible with the C++${_cpp_version_bad} standard.\n"
- "Please explicitly set the standard version to C++${_cpp_version_good}, e.g. by reconfiguring with\n"
- " cmake -DDEAL_II_CXX_FLAGS=\"-std=c++${_cpp_version_good}\" ."
- )
- endif()
- endif()
- endmacro()
-
- _cuda_ensure_feature_off(10 17 14)
-
- # cuSOLVER requires OpenMP
- find_package(OpenMP REQUIRED)
- set(DEAL_II_LINKER_FLAGS "${DEAL_II_LINKER_FLAGS} ${OpenMP_CXX_FLAGS}")
- endif()
- endif()
-endmacro()
-
-
-macro(feature_cuda_configure_external)
- # We cannot use -pedantic as compiler flags. nvcc generates code that
- # produces a lot of warnings when pedantic is enabled. So filter out the
- # flag:
- #
- string(REPLACE "-pedantic" "" DEAL_II_WARNING_FLAGS "${DEAL_II_WARNING_FLAGS}")
-endmacro()
-
-
-macro(feature_cuda_error_message)
- message(FATAL_ERROR "\n"
- "Could not find any suitable cuda library!\n"
- ${CUDA_ADDITIONAL_ERROR_STRING}
- "\nPlease ensure that a cuda library is installed on your computer and deal.II is configured to use an external Kokkos installation.\n"
- )
-endmacro()
-
-
-configure_feature(CUDA)
-DDEAL_II_WITH_BOOST=ON \
-DDEAL_II_WITH_CGAL=ON \
-DDEAL_II_WITH_COMPLEX_VALUES=ON \
- -DDEAL_II_WITH_CUDA=OFF \
-DDEAL_II_WITH_GINKGO=OFF \
-DDEAL_II_WITH_GMSH=ON \
-DDEAL_II_WITH_GSL=ON \
+++ /dev/null
-// ------------------------------------------------------------------------
-//
-// SPDX-License-Identifier: LGPL-2.1-or-later
-// Copyright (C) 2018 by the deal.II authors
-//
-// This file is part of the deal.II library.
-//
-// Part of the source code is dual licensed under Apache-2.0 WITH
-// LLVM-exception OR LGPL-2.1-or-later. Detailed license information
-// governing the source code and code contributions can be found in
-// LICENSE.md and CONTRIBUTING.md at the top level directory of deal.II.
-//
-// ------------------------------------------------------------------------
-
-
-/**
- * @defgroup CUDAWrappers CUDA Wrappers
- *
- * The classes in this group are concerned with the description of features
- * to be run on GPUs using CUDA.
- */
* <dt class="glossary">@anchor GlossDevice <b>Device</b></dt>
*
* <dd> We commonly refer to GPUs as "devices" in deal.II. The context is
- * always related to Kokkos or CUDA that motivated using this term.
+ * always related to Kokkos that motivated using this term.
* Occasionally, we also call data corresponding to MemorySpace::Default "device data"
* (even though it is allocated in CPU memory if Kokkos was configured without
* a GPU backend) to distinguish between MemorySpace::Default and MemorySpace::Host.
rank="same";
petsc [label="PETSc", URL="\ref PETScWrappers"];
trilinos [label="Trilinos", URL="\ref TrilinosWrappers"];
- cuda [label="CUDA", URL="\ref CUDAWrappers"];
}
umfpack [label="UMFPACK"];
color="gray", fontcolor="gray", fillcolor="white", style="filled"];
fevalues [label="FEEvaluation", fillcolor="deepskyblue"];
mf [label="MatrixFree loops", fillcolor="deepskyblue"];
- cuda [label="CUDA", URL="\ref CUDAWrappers", fontname="FreeSans",fontsize=12,
+ portable [label="Portable", URL="\ref Portable", fontname="FreeSans",fontsize=12,
height=0.2,width=0.4,
color="gray", fontcolor="gray", fillcolor="white", style="filled"];
tbb [label="TBB", fontname="FreeSans",fontsize=12,
{rank=same
simd -> fevalues [dir="none", color="transparent"];
fevalues -> mf [dir="none", color="transparent"];
- mf -> cuda [dir="none", color="transparent"];
- cuda -> tbb [dir="none", color="transparent"];
+ mf -> portable [dir="none", color="transparent"];
+ portable -> tbb [dir="none", color="transparent"];
}
subgraph sol {
rank="same";
DEAL_II_CGAL_VERSION_GTE=1 \
DEAL_II_WITH_TASKFLOW=1 \
DEAL_II_WITH_COMPLEX_VALUES=1 \
- DEAL_II_WITH_CUDA=1 \
DEAL_II_WITH_GINKGO=1 \
DEAL_II_WITH_GMSH=1 \
DEAL_II_GMSH_WITH_API=1 \
<p>
To compile and run CUDA code, you need to use an external Kokkos
installation that has been configured with CUDA support.
-
- To enable deal.II's own CUDA backend, you will need your GPU to have compute
- capability 6.0 or higher. Independently from the GPU itself, you also need a
- version of CUDA between 10.2 and 11.8.
- </p>
-
- <p>
- To configure deal.II's own CUDA backend use the following option:
- <pre>
-
- -DDEAL_II_WITH_CUDA=ON
- </pre>
- CUDA versions prior to 11.0 don't support C++17 or higher. You will have
- to make sure that C++17 is disabled when using earlier versions.
</p>
<p>
--- /dev/null
+Removed: All support for CUDAWrappers and CUDA-related macros have been removed.
+GPU support is provided through Kokkos.
+<br>
+(Daniel Arndt, 2024/08/11)
DEAL_II_WITH_BOOST
DEAL_II_WITH_CGAL
DEAL_II_WITH_COMPLEX_VALUES
-DEAL_II_WITH_CUDA
DEAL_II_WITH_GINKGO
DEAL_II_WITH_GMSH
DEAL_II_WITH_GSL
DEAL_II_WITH_ARPACK
DEAL_II_WITH_ASSIMP
DEAL_II_WITH_COMPLEX_VALUES
-DEAL_II_WITH_CUDA
DEAL_II_WITH_GINKGO
DEAL_II_WITH_GMSH
DEAL_II_WITH_GSL
# set(DEAL_II_WITH_BOOST "ON" CACHE BOOL "")
# set(DEAL_II_WITH_CGAL "ON" CACHE BOOL "")
# set(DEAL_II_WITH_COMPLEX_VALUES "ON" CACHE BOOL "")
-# set(DEAL_II_WITH_CUDA "ON" CACHE BOOL "")
# set(DEAL_II_WITH_GINKGO "ON" CACHE BOOL "")
# set(DEAL_II_WITH_GMSH "ON" CACHE BOOL "")
# set(DEAL_II_WITH_GSL "ON" CACHE BOOL "")
vectors can be seen as buffers on the host that are used to either store data
received from the device or to send data to the device. There are two types of vectors
that can be used on the device:
-- LinearAlgebra::CUDAWrappers::Vector, which is similar to the more common
-Vector<Number>, and
+- LinearAlgebra::TpetraWrappers::Vector<Number, MemorySpace>, that has a host
+and device copy of the data, and
- LinearAlgebra::distributed::Vector<Number,
MemorySpace::Default>, which is a regular
LinearAlgebra::distributed::Vector where we have specified which memory
// Since all the operations in the `solve()` function are executed on the
// graphics card, it is necessary for the vectors used to store their values
// on the GPU as well. LinearAlgebra::distributed::Vector can be told which
- // memory space to use. There is also LinearAlgebra::CUDAWrappers::Vector
- // that always uses GPU memory storage but doesn't work with MPI. It might
+ // memory space to use. It might
// be worth noticing that the communication between different MPI processes
// can be improved if the MPI implementation is GPU-aware and the configure
// flag `DEAL_II_MPI_WITH_DEVICE_SUPPORT` is enabled. (The value of this
#cmakedefine DEAL_II_FEATURE_BOOST_BUNDLED_CONFIGURED
#cmakedefine DEAL_II_WITH_CGAL
#cmakedefine DEAL_II_WITH_COMPLEX_VALUES
-#cmakedefine DEAL_II_WITH_CUDA
#cmakedefine DEAL_II_WITH_GINKGO
#cmakedefine DEAL_II_WITH_GMSH
#cmakedefine DEAL_II_WITH_GSL
#endif
#cmakedefine DEAL_II_MPI_WITH_DEVICE_SUPPORT
-#ifdef DEAL_II_MPI_WITH_DEVICE_SUPPORT
-#cmakedefine DEAL_II_MPI_WITH_CUDA_SUPPORT
-#endif
/***********************************************************************
* Two macro names that we put at the top and bottom of all deal.II files
+++ /dev/null
-// ------------------------------------------------------------------------
-//
-// SPDX-License-Identifier: LGPL-2.1-or-later
-// Copyright (C) 2018 - 2023 by the deal.II authors
-//
-// This file is part of the deal.II library.
-//
-// Part of the source code is dual licensed under Apache-2.0 WITH
-// LLVM-exception OR LGPL-2.1-or-later. Detailed license information
-// governing the source code and code contributions can be found in
-// LICENSE.md and CONTRIBUTING.md at the top level directory of deal.II.
-//
-// ------------------------------------------------------------------------
-
-#ifndef dealii_cuda_h
-#define dealii_cuda_h
-
-#include <deal.II/base/config.h>
-
-#include <deal.II/base/array_view.h>
-#include <deal.II/base/exceptions.h>
-
-#ifdef DEAL_II_WITH_CUDA
-# include <cusolverDn.h>
-# include <cusolverSp.h>
-# include <cusparse.h>
-
-# include <vector>
-
-DEAL_II_NAMESPACE_OPEN
-namespace Utilities
-{
- /**
- * A namespace for utility structures for CUDA.
- */
- namespace CUDA
- {
- /**
- * Various CUDA APIs need an object to store internal data. This structure
- * creates, initializes, stores, and destroys these so-called handles for
- * the respective CUDA libraries used inside deal.II.
- */
- struct Handle
- {
- /**
- * Constructor. Initialize the handles for the different libraries.
- */
- Handle();
-
- /**
- * Copy constructor is deleted.
- */
- Handle(const Handle &) = delete;
-
- /**
- * Destructor. Destroy the handles.
- */
- ~Handle();
-
- /**
- * Pointer to an opaque cuSolverDN context.
- * The handle must be passed to every cuSolverDN library function.
- */
- cusolverDnHandle_t cusolver_dn_handle;
-
- /**
- * Pointer to an opaque cuSolverSP context.
- * The handle must be passed to every cuSolverSP library function.
- */
- cusolverSpHandle_t cusolver_sp_handle;
-
- /**
- * Pointer to an opaque cuSPARSE context.
- * The handle must be passed to every cuSPARSE library function.
- */
- cusparseHandle_t cusparse_handle;
- };
-
- /**
- * Allocate @p n_elements on the @ref GlossDevice "device".
- */
- template <typename T>
- inline void
- malloc(T *&pointer, const unsigned int n_elements)
- {
- cudaError_t cuda_error_code =
- cudaMalloc(&pointer, n_elements * sizeof(T));
- AssertCuda(cuda_error_code);
- }
-
- /**
- * Free memory on the @ref GlossDevice "device".
- */
- template <typename T>
- inline void
- free(T *&pointer)
- {
- cudaError_t cuda_error_code = cudaFree(pointer);
- AssertCuda(cuda_error_code);
- pointer = nullptr;
- }
-
- /**
- * Allocator to be used for `std::unique_ptr` pointing to @ref GlossDevice "device" memory.
- */
- template <typename Number>
- Number *
- allocate_device_data(const std::size_t size)
- {
- Number *device_ptr;
- Utilities::CUDA::malloc(device_ptr, size);
- return device_ptr;
- }
-
- /**
- * Deleter to be used for `std::unique_ptr` pointing to @ref GlossDevice "device" memory.
- */
- template <typename Number>
- void
- delete_device_data(Number *device_ptr) noexcept
- {
- const cudaError_t error_code = cudaFree(device_ptr);
- AssertNothrowCuda(error_code);
- }
-
- /**
- * Copy the @ref GlossDevice "device" ArrayView @p in to the host ArrayView @p out.
- */
- template <typename T>
- inline void
- copy_to_host(const ArrayView<const T, MemorySpace::CUDA> &in,
- ArrayView<T, MemorySpace::Host> &out)
- {
- AssertDimension(in.size(), out.size());
- cudaError_t cuda_error_code = cudaMemcpy(out.data(),
- in.data(),
- in.size() * sizeof(T),
- cudaMemcpyDeviceToHost);
- AssertCuda(cuda_error_code);
- }
-
- /**
- * Copy the host ArrayView @p in to the @ref GlossDevice "device" ArrayView @p out.
- */
- template <typename T>
- inline void
- copy_to_dev(const ArrayView<const T, MemorySpace::Host> &in,
- ArrayView<T, MemorySpace::CUDA> &out)
- {
- AssertDimension(in.size(), out.size());
- cudaError_t cuda_error_code = cudaMemcpy(out.data(),
- in.data(),
- in.size() * sizeof(T),
- cudaMemcpyHostToDevice);
- AssertCuda(cuda_error_code);
- }
-
- /**
- * Copy the elements in @p pointer_dev to the host in @p vector_host.
- */
- template <typename T>
- inline void
- copy_to_host(const T *pointer_dev, std::vector<T> &vector_host)
- {
- ArrayView<const T, MemorySpace::CUDA> in(pointer_dev, vector_host.size());
- auto out = make_array_view(vector_host);
- copy_to_host(in, out);
- }
-
- /**
- * Copy the elements in @p vector_host to the @ref GlossDevice "device" in @p pointer_dev. The
- * memory needs to be allocate on the @ref GlossDevice "device" before this function is called.
- */
- template <typename T>
- inline void
- copy_to_dev(const std::vector<T> &vector_host, T *pointer_dev)
- {
- auto in = make_array_view(vector_host);
- ArrayView<T, MemorySpace::CUDA> out(pointer_dev, vector_host.size());
- copy_to_dev(in, out);
- }
- } // namespace CUDA
-} // namespace Utilities
-
-DEAL_II_NAMESPACE_CLOSE
-#endif
-#endif
+++ /dev/null
-// ------------------------------------------------------------------------
-//
-// SPDX-License-Identifier: LGPL-2.1-or-later
-// Copyright (C) 2018 - 2023 by the deal.II authors
-//
-// This file is part of the deal.II library.
-//
-// Part of the source code is dual licensed under Apache-2.0 WITH
-// LLVM-exception OR LGPL-2.1-or-later. Detailed license information
-// governing the source code and code contributions can be found in
-// LICENSE.md and CONTRIBUTING.md at the top level directory of deal.II.
-//
-// ------------------------------------------------------------------------
-
-#ifndef dealii_cuda_size_h
-#define dealii_cuda_size_h
-
-#include <deal.II/base/config.h>
-
-DEAL_II_NAMESPACE_OPEN
-
-namespace CUDAWrappers
-{
- /**
- * Define the size of a block when launching a CUDA kernel. This number can be
- * changed depending on the architecture the code is running on.
- */
- constexpr int block_size = 512;
-
- /**
- * Define the size of chunk of data worked on by a thread. This number can be
- * changed depending on the architecture the code is running on.
- */
- constexpr int chunk_size = 1;
-
- /**
- * Define the number of threads in a warp.
- */
- constexpr int warp_size = 32;
-} // namespace CUDAWrappers
-
-DEAL_II_NAMESPACE_CLOSE
-
-#endif
#include <string>
#include <type_traits>
-#ifdef DEAL_II_WITH_CUDA
-# include <cusolverSp.h>
-# include <cusparse.h>
-#endif
-
DEAL_II_NAMESPACE_OPEN
"if deal.II was configured to use Assimp, but cmake did not "
"find a valid Assimp library.");
-#ifdef DEAL_II_WITH_CUDA
- /**
- * This exception is raised if an error happened in a CUDA kernel.
- *
- * The constructor takes a single <tt>char*</tt>, the output of
- * cudaGetErrorString.
- */
- DeclException1(ExcCudaError, const char *, << arg1);
- /**
- * This exception is raised if an error happened in a cuSPARSE function.
- */
- DeclException1(ExcCusparseError,
- std::string,
- << "There was an error in a cuSPARSE function: " << arg1);
-#endif
/** @} */
/**
// another function:
do_issue_error_nothrow(e);
}
-#ifdef DEAL_II_WITH_CUDA
- /**
- * Return a string given an error code. This is similar to the
- * cudaGetErrorString function but there is no equivalent function for
- * cuSPARSE.
- */
- std::string
- get_cusparse_error_string(const cusparseStatus_t error_code);
-
- /**
- * Return a string given an error code. This is similar to the
- * cudaGetErrorString function but there is no equivalent function for
- * cuSOLVER.
- */
- std::string
- get_cusolver_error_string(const cusolverStatus_t error_code);
-#endif
} /*namespace internals*/
} /*namespace deal_II_exceptions*/
while (false)
#endif // DEAL_II_WITH_MPI
-#ifdef DEAL_II_WITH_CUDA
-/**
- * An assertion that checks that the error code produced by calling a CUDA
- * routine is equal to cudaSuccess.
- *
- * @note This and similar macro names are examples of preprocessor definitions
- * in the deal.II library that are not prefixed by a string that likely makes
- * them unique to deal.II. As a consequence, it is possible that other
- * libraries your code interfaces with define the same name, and the result
- * will be name collisions (see
- * https://en.wikipedia.org/wiki/Name_collision). One can <code>\#undef</code>
- * this macro, as well as all other macros defined by deal.II that are not
- * prefixed with either <code>DEAL</code> or <code>deal</code>, by including
- * the header <code>deal.II/base/undefine_macros.h</code> after all other
- * deal.II headers have been included.
- *
- * @ingroup Exceptions
- */
-# ifdef DEBUG
-# define AssertCuda(error_code) \
- Assert(error_code == cudaSuccess, \
- dealii::ExcCudaError(cudaGetErrorString(error_code)))
-# else
-# define AssertCuda(error_code) \
- do \
- { \
- (void)(error_code); \
- } \
- while (false)
-# endif
-
-/**
- * The non-throwing equivalent of AssertCuda.
- *
- * @note This and similar macro names are examples of preprocessor definitions
- * in the deal.II library that are not prefixed by a string that likely makes
- * them unique to deal.II. As a consequence, it is possible that other
- * libraries your code interfaces with define the same name, and the result
- * will be name collisions (see
- * https://en.wikipedia.org/wiki/Name_collision). One can <code>\#undef</code>
- * this macro, as well as all other macros defined by deal.II that are not
- * prefixed with either <code>DEAL</code> or <code>deal</code>, by including
- * the header <code>deal.II/base/undefine_macros.h</code> after all other
- * deal.II headers have been included.
- *
- * @ingroup Exceptions
- */
-# ifdef DEBUG
-# define AssertNothrowCuda(error_code) \
- AssertNothrow(error_code == cudaSuccess, \
- dealii::ExcCudaError(cudaGetErrorString(error_code)))
-# else
-# define AssertNothrowCuda(error_code) \
- do \
- { \
- (void)(error_code); \
- } \
- while (false)
-# endif
-
-/**
- * An assertion that checks that the kernel was launched and executed
- * successfully.
- *
- * @note This and similar macro names are examples of preprocessor definitions
- * in the deal.II library that are not prefixed by a string that likely makes
- * them unique to deal.II. As a consequence, it is possible that other
- * libraries your code interfaces with define the same name, and the result
- * will be name collisions (see
- * https://en.wikipedia.org/wiki/Name_collision). One can <code>\#undef</code>
- * this macro, as well as all other macros defined by deal.II that are not
- * prefixed with either <code>DEAL</code> or <code>deal</code>, by including
- * the header <code>deal.II/base/undefine_macros.h</code> after all other
- * deal.II headers have been included.
- *
- * @ingroup Exceptions
- */
-# ifdef DEBUG
-# define AssertCudaKernel() \
- do \
- { \
- cudaError_t local_error_code = cudaPeekAtLastError(); \
- AssertCuda(local_error_code); \
- local_error_code = cudaDeviceSynchronize(); \
- AssertCuda(local_error_code); \
- } \
- while (false)
-# else
-# define AssertCudaKernel() \
- do \
- { \
- } \
- while (false)
-# endif
-
-/**
- * An assertion that checks that the error code produced by calling a cuSPARSE
- * routine is equal to CUSPARSE_STATUS_SUCCESS.
- *
- * @note This and similar macro names are examples of preprocessor definitions
- * in the deal.II library that are not prefixed by a string that likely makes
- * them unique to deal.II. As a consequence, it is possible that other
- * libraries your code interfaces with define the same name, and the result
- * will be name collisions (see
- * https://en.wikipedia.org/wiki/Name_collision). One can <code>\#undef</code>
- * this macro, as well as all other macros defined by deal.II that are not
- * prefixed with either <code>DEAL</code> or <code>deal</code>, by including
- * the header <code>deal.II/base/undefine_macros.h</code> after all other
- * deal.II headers have been included.
- *
- * @ingroup Exceptions
- */
-# ifdef DEBUG
-# define AssertCusparse(error_code) \
- Assert( \
- error_code == CUSPARSE_STATUS_SUCCESS, \
- dealii::ExcCusparseError( \
- dealii::deal_II_exceptions::internals::get_cusparse_error_string( \
- error_code)))
-# else
-# define AssertCusparse(error_code) \
- do \
- { \
- (void)(error_code); \
- } \
- while (false)
-# endif
-
-/**
- * The non-throwing equivalent of AssertCusparse.
- *
- * @note This and similar macro names are examples of preprocessor definitions
- * in the deal.II library that are not prefixed by a string that likely makes
- * them unique to deal.II. As a consequence, it is possible that other
- * libraries your code interfaces with define the same name, and the result
- * will be name collisions (see
- * https://en.wikipedia.org/wiki/Name_collision). One can <code>\#undef</code>
- * this macro, as well as all other macros defined by deal.II that are not
- * prefixed with either <code>DEAL</code> or <code>deal</code>, by including
- * the header <code>deal.II/base/undefine_macros.h</code> after all other
- * deal.II headers have been included.
- *
- * @ingroup Exceptions
- */
-# ifdef DEBUG
-# define AssertNothrowCusparse(error_code) \
- AssertNothrow( \
- error_code == CUSPARSE_STATUS_SUCCESS, \
- dealii::ExcCusparseError( \
- dealii::deal_II_exceptions::internals::get_cusparse_error_string( \
- error_code)))
-# else
-# define AssertNothrowCusparse(error_code) \
- do \
- { \
- (void)(error_code); \
- } \
- while (false)
-# endif
-
-/**
- * An assertion that checks that the error code produced by calling a cuSOLVER
- * routine is equal to CUSOLVER_STATUS_SUCCESS.
- *
- * @note This and similar macro names are examples of preprocessor definitions
- * in the deal.II library that are not prefixed by a string that likely makes
- * them unique to deal.II. As a consequence, it is possible that other
- * libraries your code interfaces with define the same name, and the result
- * will be name collisions (see
- * https://en.wikipedia.org/wiki/Name_collision). One can <code>\#undef</code>
- * this macro, as well as all other macros defined by deal.II that are not
- * prefixed with either <code>DEAL</code> or <code>deal</code>, by including
- * the header <code>deal.II/base/undefine_macros.h</code> after all other
- * deal.II headers have been included.
- *
- * @ingroup Exceptions
- */
-# ifdef DEBUG
-# define AssertCusolver(error_code) \
- Assert( \
- error_code == CUSOLVER_STATUS_SUCCESS, \
- dealii::ExcCusparseError( \
- dealii::deal_II_exceptions::internals::get_cusolver_error_string( \
- error_code)))
-# else
-# define AssertCusolver(error_code) \
- do \
- { \
- (void)(error_code); \
- } \
- while (false)
-# endif
-
-#endif
-
#ifdef DEAL_II_TRILINOS_WITH_SEACAS
/**
* Assertion that checks that the error code produced by calling an ExodusII
{
using kokkos_space = ::Kokkos::DefaultExecutionSpace::memory_space;
};
-
-#ifdef DEAL_II_WITH_CUDA
- /**
- * Structure describing CUDA memory space.
- */
- using CUDA = Default;
-#endif
} // namespace MemorySpace
DEAL_II_NAMESPACE_CLOSE
#include <deal.II/base/config.h>
-#include <deal.II/base/cuda.h>
+#include <deal.II/base/array_view.h>
#include <deal.II/base/exceptions.h>
#include <deal.II/base/kokkos.h>
{
/**
* Structure which stores data on the host or the @ref GlossDevice "device" depending on the
- * template parameter @p MemorySpace. Valid choices are MemorySpace::Host,
- * MemorySpace::Default, and MemorySpace::CUDA (if CUDA was enabled in
- * deal.II). The data is copied into the structure which then owns the data
+ * template parameter @p MemorySpace. Valid choices are MemorySpace::Host and MemorySpace::Default.
+ * The data is copied into the structure which then owns the data
* and will release the memory when the destructor is called.
*/
template <typename T, typename MemorySpace>
#include <deal.II/base/types.h>
-#ifdef DEAL_II_WITH_CUDA
-# include <cuComplex.h>
-#endif
-
#include <Kokkos_Macros.hpp>
#include <cmath>
#include <type_traits>
#define DEAL_II_HOST_DEVICE KOKKOS_FUNCTION
-#define DEAL_II_CUDA_HOST_DEV DEAL_II_HOST_DEVICE
#define DEAL_II_HOST_DEVICE_ALWAYS_INLINE KOKKOS_FORCEINLINE_FUNCTION
// clang++ assumes that all constexpr functions are __host__ __device__ when
}
};
-#ifdef DEAL_II_WITH_CUDA
- template <>
- struct NumberType<cuComplex>
- {
- static cuComplex
- value(const float t)
- {
- return make_cuComplex(t, 0.f);
- }
- };
-
- template <>
- struct NumberType<cuDoubleComplex>
- {
- static cuDoubleComplex
- value(const double t)
- {
- return make_cuDoubleComplex(t, 0.);
- }
- };
-#endif
} // namespace internal
namespace numbers
# undef AssertARKode
#endif // #ifdef AssertARKode
-#ifdef AssertCuda
-# undef AssertCuda
-#endif // #ifdef AssertCuda
-
-#ifdef AssertCudaKernel
-# undef AssertCudaKernel
-#endif // #ifdef AssertCudaKernel
-
#ifdef AssertCusolver
# undef AssertCusolver
#endif // #ifdef AssertCusolver
# undef AssertNothrow
#endif // #ifdef AssertNothrow
-#ifdef AssertNothrowCuda
-# undef AssertNothrowCuda
-#endif // #ifdef AssertNothrowCuda
-
#ifdef AssertNothrowCusparse
# undef AssertNothrowCusparse
#endif // #ifdef AssertNothrowCusparse
+++ /dev/null
-// ------------------------------------------------------------------------
-//
-// SPDX-License-Identifier: LGPL-2.1-or-later
-// Copyright (C) 2016 - 2022 by the deal.II authors
-//
-// This file is part of the deal.II library.
-//
-// Part of the source code is dual licensed under Apache-2.0 WITH
-// LLVM-exception OR LGPL-2.1-or-later. Detailed license information
-// governing the source code and code contributions can be found in
-// LICENSE.md and CONTRIBUTING.md at the top level directory of deal.II.
-//
-// ------------------------------------------------------------------------
-
-#ifndef dealii_cuda_atomic_h
-#define dealii_cuda_atomic_h
-
-#include <deal.II/base/config.h>
-
-#ifdef DEAL_II_WITH_CUDA
-
-DEAL_II_NAMESPACE_OPEN
-
-namespace LinearAlgebra
-{
- namespace CUDAWrappers
- {
- /**
- * Provide atomicMax for floats.
- *
- * @ingroup CUDAWrappers
- */
- inline __device__ float
- atomicMax_wrapper(float *address, float val)
- {
- int *address_as_int = reinterpret_cast<int *>(address);
- int old = *address_as_int, assumed;
- do
- {
- assumed = old;
- old = atomicCAS(address_as_int,
- assumed,
- atomicMax(address_as_int, __float_as_int(val)));
- }
- while (assumed != old);
-
- return __longlong_as_double(old);
- }
-
-
-
- /**
- * Provide atomicMax for doubles.
- *
- * @ingroup CUDAWrappers
- */
- inline __device__ double
- atomicMax_wrapper(double *address, double val)
- {
- unsigned long long int *address_as_ull =
- reinterpret_cast<unsigned long long int *>(address);
- unsigned long long int old = *address_as_ull, assumed;
- do
- {
- assumed = old;
- old = atomicCAS(address_as_ull,
- assumed,
- atomicMax(address_as_ull,
- static_cast<unsigned long long int>(
- __double_as_longlong(val))));
- }
- while (assumed != old);
-
- return __longlong_as_double(old);
- }
- } // namespace CUDAWrappers
-} // namespace LinearAlgebra
-
-DEAL_II_NAMESPACE_CLOSE
-
-#endif
-
-#endif
+++ /dev/null
-// ------------------------------------------------------------------------
-//
-// SPDX-License-Identifier: LGPL-2.1-or-later
-// Copyright (C) 2018 - 2023 by the deal.II authors
-//
-// This file is part of the deal.II library.
-//
-// Part of the source code is dual licensed under Apache-2.0 WITH
-// LLVM-exception OR LGPL-2.1-or-later. Detailed license information
-// governing the source code and code contributions can be found in
-// LICENSE.md and CONTRIBUTING.md at the top level directory of deal.II.
-//
-// ------------------------------------------------------------------------
-
-#ifndef dealii_cuda_kernels_h
-#define dealii_cuda_kernels_h
-
-#include <deal.II/base/config.h>
-
-#ifdef DEAL_II_WITH_CUDA
-
-
-# include <deal.II/base/cuda_size.h>
-# include <deal.II/base/types.h>
-
-# include <deal.II/lac/cuda_atomic.h>
-
-# include <assert.h>
-
-DEAL_II_NAMESPACE_OPEN
-
-namespace LinearAlgebra
-{
- namespace CUDAWrappers
- {
- /**
- * Namespace containing the CUDA kernels.
- */
- namespace kernel
- {
- using ::dealii::CUDAWrappers::block_size;
- using ::dealii::CUDAWrappers::chunk_size;
- using ::dealii::CUDAWrappers::warp_size;
- using size_type = types::global_dof_index;
-
- /**
- * Multiply each entry of @p val of size @p N by @p a.
- *
- * @ingroup CUDAWrappers
- */
- template <typename Number>
- __global__ void
- vec_scale(Number *val, const Number a, const size_type N);
-
-
-
- /**
- * Functor defining the addition of two Numbers.
- *
- * @ingroup CUDAWrappers
- */
- template <typename Number>
- struct Binop_Addition
- {
- __device__ static inline Number
- operation(const Number a, const Number b)
- {
- return a + b;
- }
- };
-
- template <typename Number>
- struct Binop_Addition<std::complex<Number>>
- {
- __device__ static inline std::complex<Number>
- operation(const std::complex<Number> a, const std::complex<Number>)
- {
- printf("This function is not implemented for std::complex<Number>!");
- assert(false);
- return a;
- }
- };
-
-
-
- /**
- * Functor defining the subtraction of two Numbers.
- *
- * @ingroup CUDAWrappers
- */
- template <typename Number>
- struct Binop_Subtraction
- {
- __device__ static inline Number
- operation(const Number a, const Number b)
- {
- return a - b;
- }
- };
-
- template <typename Number>
- struct Binop_Subtraction<std::complex<Number>>
- {
- __device__ static inline std::complex<Number>
- operation(const std::complex<Number> a,
- const std::complex<Number> /*b*/)
- {
- printf("This function is not implemented for std::complex<Number>!");
- assert(false);
- return a;
- }
- };
-
-
-
- /**
- * Functor defining the maximum of two Numbers.
- *
- * @ingroup CUDAWrappers
- */
- template <typename Number>
- struct Binop_Max
- {
- __device__ static inline Number
- operation(const Number a, const Number b)
- {
- return a > b ? a : b;
- }
- };
-
- template <typename Number>
- struct Binop_Max<std::complex<Number>>
- {
- __device__ static inline std::complex<Number>
- operation(const std::complex<Number> a, const std::complex<Number>)
- {
- printf("This function is not implemented for std::complex<Number>!");
- assert(false);
- return a;
- }
- };
-
-
-
- /**
- * Functor defining the maximum of two Numbers.
- *
- * @ingroup CUDAWrappers
- */
- template <typename Number>
- struct Binop_Min
- {
- __device__ static inline Number
- operation(const Number a, const Number b)
- {
- return a > b ? b : a;
- }
- };
-
- template <typename Number>
- struct Binop_Min<std::complex<Number>>
- {
- __device__ static inline std::complex<Number>
- operation(const std::complex<Number> a, const std::complex<Number>)
- {
- printf("This function is not implemented for std::complex<Number>!");
- assert(false);
- return a;
- }
- };
-
-
-
- /**
- * Apply the functor @p Binop to each element of @p v1 and @p v2.
- *
- * @ingroup CUDAWrappers
- */
- template <typename Number, template <typename> class Binop>
- __global__ void
- vector_bin_op(Number *v1, const Number *v2, const size_type N);
-
-
-
- /**
- * Apply the functor @p Binop to the elements of @p v1 that have
- * indices in @p mask and @p v2. The size of @p mask should be greater
- * than the size of @p v1. @p mask and @p v2 should have the same size @p
- * N.
- *
- * @ingroup CUDAWrappers
- */
- template <typename Number, template <typename> class Binop>
- __global__ void
- masked_vector_bin_op(const unsigned int *mask,
- Number *v1,
- const Number *v2,
- const size_type N);
-
-
-
- /**
- * Structure implementing the functions used to add elements when
- * using a reduction.
- *
- * @ingroup CUDAWrappers
- */
- template <typename Number>
- struct ElemSum
- {
- __device__ static Number
- reduction_op(const Number a, const Number b);
-
- __device__ static Number
- atomic_op(Number *dst, const Number a);
-
- __device__ static Number
- element_wise_op(const Number a);
-
- __device__ static Number
- null_value();
- };
-
-
-
- /**
- * Structure implementing the functions used to compute the L1 norm
- * when using a reduction.
- *
- * @ingroup CUDAWrappers
- */
- template <typename Number>
- struct L1Norm
- {
- __device__ static Number
- reduction_op(const Number a, const Number b);
-
- __device__ static Number
- atomic_op(Number *dst, const Number a);
-
- __device__ static Number
- element_wise_op(const Number a);
-
- __device__ static Number
- null_value();
- };
-
-
-
- /**
- * Structure implementing the functions used to compute the L-infinity
- * norm when using a reduction.
- *
- * @ingroup CUDAWrappers
- */
- template <typename Number>
- struct LInfty
- {
- __device__ static Number
- reduction_op(const Number a, const Number b);
-
- __device__ static Number
- atomic_op(Number *dst, const Number a);
-
- __device__ static Number
- element_wise_op(const Number a);
-
- __device__ static Number
- null_value();
- };
-
-
-
- /**
- * Perform a reduction on @p v using @p Operation.
- *
- * @ingroup CUDAWrappers
- */
- template <typename Number, typename Operation>
- __global__ void
- reduction(Number *result, const Number *v, const size_type N);
-
-
-
- /**
- * Structure implementing the functions used to compute the dot
- * product norm when using a double vector reduction.
- *
- * @ingroup CUDAWrappers
- */
- template <typename Number>
- struct DotProduct
- {
- __device__ static Number
- binary_op(const Number a, const Number b);
-
- __device__ static Number
- reduction_op(const Number a, const Number b);
-
- __device__ static Number
- atomic_op(Number *dst, const Number a);
-
- __device__ static Number
- null_value();
- };
-
-
-
- /**
- * Perform a binary operation on each element of @p v1 and @p v2 followed
- * by reduction on the resulting array.
- *
- * @ingroup CUDAWrappers
- */
- template <typename Number, typename Operation>
- __global__ void
- double_vector_reduction(Number *result,
- const Number *v1,
- const Number *v2,
- const size_type N);
-
-
-
- /**
- * Add @p a to each element of @p val.
- *
- * @ingroup CUDAWrappers
- */
- template <typename Number>
- __global__ void
- vec_add(Number *val, const Number a, const size_type N);
-
-
-
- /**
- * Addition of a multiple of a vector, i.e., <tt>val += a*V_val</tt>.
- *
- * @ingroup CUDAWrappers
- */
- template <typename Number>
- __global__ void
- add_aV(Number *val,
- const Number a,
- const Number *V_val,
- const size_type N);
-
-
-
- /**
- * Addition of multiple scaled vector, i.e., <tt>val += a*V_val +
- * b*W_val</tt>.
- *
- * @ingroup CUDAWrappers
- */
- template <typename Number>
- __global__ void
- add_aVbW(Number *val,
- const Number a,
- const Number *V_val,
- const Number b,
- const Number *W_val,
- const size_type N);
-
-
-
- /**
- * Scaling and simple addition of a multiple of a vector, i.e. <tt>val
- * = = s*val + a*V_val</tt>
- *
- * @ingroup CUDAWrappers
- */
- template <typename Number>
- __global__ void
- sadd(const Number s,
- Number *val,
- const Number a,
- const Number *V_val,
- const size_type N);
-
-
-
- /**
- * Scaling and multiple additions of scaled vectors, i.e. <tt>val =
- * = s*val + a*V_val + b*W_val</tt>
- *
- * @ingroup CUDAWrappers
- */
- template <typename Number>
- __global__ void
- sadd(const Number s,
- Number *val,
- const Number a,
- const Number *V_val,
- const Number b,
- const Number *W_val,
- const size_type N);
-
-
-
- /**
- * Scale each element of this vector by the corresponding element in
- * the argument.
- *
- * @ingroup CUDAWrappers
- */
- template <typename Number>
- __global__ void
- scale(Number *val, const Number *V_val, const size_type N);
-
-
-
- /**
- * Assignment <tt>val = a*V_val</tt>.
- *
- * @ingroup CUDAWrappers
- */
- template <typename Number>
- __global__ void
- equ(Number *val, const Number a, const Number *V_val, const size_type N);
-
-
-
- /**
- * Assignment <tt>val = a*V_val + b*W_val</tt>.
- *
- * @ingroup CUDAWrappers
- */
- template <typename Number>
- __global__ void
- equ(Number *val,
- const Number a,
- const Number *V_val,
- const Number b,
- const Number *W_val,
- const size_type N);
-
-
-
- /**
- * Perform a combined operation of a vector addition and a subsequent
- * inner product, returning the value of the inner product.
- *
- * @ingroup CUDAWrappers
- */
- template <typename Number>
- __global__ void
- add_and_dot(Number *res,
- Number *v1,
- const Number *v2,
- const Number *v3,
- const Number a,
- const size_type N);
-
-
-
- /**
- * Set each element of @p val to @p s.
- *
- * @ingroup CUDAWrappers
- */
- template <typename Number>
- __global__ void
- set(Number *val, const Number s, const size_type N);
-
-
- /**
- * Set each element in @p val to @p v using @p indices as permutation, i.e.,
- * <tt>val[indices[i]] = v[i]</tt>.
- *
- * @ingroup CUDAWrappers
- */
- template <typename Number, typename IndexType>
- __global__ void
- set_permutated(const IndexType *indices,
- Number *val,
- const Number *v,
- const IndexType N);
-
-
-
- /**
- * Set each element in @p val to @p v using @p indices as permutation, i.e.,
- * <tt>val[i] = v[indices[i]]</tt>.
- *
- * @ingroup CUDAWrappers
- */
- template <typename Number, typename IndexType>
- __global__ void
- gather(Number *val,
- const IndexType *indices,
- const Number *v,
- const IndexType N);
-
-
-
- /**
- * Add each element in @p val to @p v using @p indices as permutation, i.e.,
- * <tt>val[indices[i]] += v[i]</tt>.
- *
- * @ingroup CUDAWrappers
- */
- template <typename Number>
- __global__ void
- add_permutated(const size_type *indices,
- Number *val,
- const Number *v,
- const size_type N);
- } // namespace kernel
- } // namespace CUDAWrappers
-} // namespace LinearAlgebra
-
-DEAL_II_NAMESPACE_CLOSE
-
-#endif
-
-#endif
+++ /dev/null
-// ------------------------------------------------------------------------
-//
-// SPDX-License-Identifier: LGPL-2.1-or-later
-// Copyright (C) 2018 - 2023 by the deal.II authors
-//
-// This file is part of the deal.II library.
-//
-// Part of the source code is dual licensed under Apache-2.0 WITH
-// LLVM-exception OR LGPL-2.1-or-later. Detailed license information
-// governing the source code and code contributions can be found in
-// LICENSE.md and CONTRIBUTING.md at the top level directory of deal.II.
-//
-// ------------------------------------------------------------------------
-
-#ifndef dealii_cuda_kernels_templates_h
-#define dealii_cuda_kernels_templates_h
-
-#include <deal.II/base/config.h>
-
-#include <deal.II/lac/cuda_kernels.h>
-
-#ifdef DEAL_II_WITH_CUDA
-
-DEAL_II_NAMESPACE_OPEN
-
-namespace LinearAlgebra
-{
- namespace CUDAWrappers
- {
- namespace kernel
- {
- template <typename Number>
- __global__ void
- vec_scale(Number *val, const Number a, const size_type N)
- {
- const size_type idx_base =
- threadIdx.x + blockIdx.x * (blockDim.x * chunk_size);
- for (unsigned int i = 0; i < chunk_size; ++i)
- {
- const size_type idx = idx_base + i * block_size;
- if (idx < N)
- val[idx] *= a;
- }
- }
-
-
-
- template <typename Number, template <typename> class Binop>
- __global__ void
- vector_bin_op(Number *v1, const Number *v2, const size_type N)
- {
- const size_type idx_base =
- threadIdx.x + blockIdx.x * (blockDim.x * chunk_size);
- for (unsigned int i = 0; i < chunk_size; ++i)
- {
- const size_type idx = idx_base + i * block_size;
- if (idx < N)
- v1[idx] = Binop<Number>::operation(v1[idx], v2[idx]);
- }
- }
-
-
-
- template <typename Number, template <typename> class Binop>
- __global__ void
- masked_vector_bin_op(const unsigned int *mask,
- Number *v1,
- const Number *v2,
- const size_type N)
- {
- const size_type idx_base =
- threadIdx.x + blockIdx.x * (blockDim.x * chunk_size);
- for (unsigned int i = 0; i < chunk_size; ++i)
- {
- const size_type idx = idx_base + i * block_size;
- if (idx < N)
- v1[mask[idx]] = Binop<Number>::operation(v1[mask[idx]], v2[idx]);
- }
- }
-
-
- template <typename Number>
- __device__ Number
- ElemSum<Number>::reduction_op(const Number a, const Number b)
- {
- return (a + b);
- }
-
-
-
- template <typename Number>
- __device__ Number
- ElemSum<Number>::atomic_op(Number *dst, const Number a)
- {
- return atomicAdd(dst, a);
- }
-
-
-
- template <typename Number>
- __device__ Number
- ElemSum<Number>::element_wise_op(const Number a)
- {
- return a;
- }
-
-
-
- template <typename Number>
- __device__ Number
- ElemSum<Number>::null_value()
- {
- return Number();
- }
-
-
-
- template <typename Number>
- __device__ Number
- L1Norm<Number>::reduction_op(const Number a, const Number b)
- {
- return (a + b);
- }
-
-
-
- template <typename Number>
- __device__ Number
- L1Norm<Number>::atomic_op(Number *dst, const Number a)
- {
- return atomicAdd(dst, a);
- }
-
-
-
- template <typename Number>
- __device__ Number
- L1Norm<Number>::element_wise_op(const Number a)
- {
- return std::fabs(a);
- }
-
-
-
- template <typename Number>
- __device__ Number
- L1Norm<Number>::null_value()
- {
- return Number();
- }
-
-
-
- template <typename Number>
- __device__ Number
- LInfty<Number>::reduction_op(const Number a, const Number b)
- {
- if (a > b)
- return a;
- else
- return b;
- }
-
-
-
- template <typename Number>
- __device__ Number
- LInfty<Number>::atomic_op(Number *dst, const Number a)
- {
- return atomicMax_wrapper(dst, a);
- }
-
-
-
- template <typename Number>
- __device__ Number
- LInfty<Number>::element_wise_op(const Number a)
- {
- return std::fabs(a);
- }
-
-
-
- template <typename Number>
- __device__ Number
- LInfty<Number>::null_value()
- {
- return Number();
- }
-
-
-
- template <typename Number, typename Operation>
- __device__ void
- reduce(Number *result,
- volatile Number *result_buffer,
- const size_type local_idx,
- const size_type /*global_idx*/,
- const size_type /*N*/)
- {
- for (size_type s = block_size / 2; s > warp_size; s = s >> 1)
- {
- if (local_idx < s)
- result_buffer[local_idx] =
- Operation::reduction_op(result_buffer[local_idx],
- result_buffer[local_idx + s]);
- __syncthreads();
- }
-
- if (local_idx < warp_size)
- {
- for (size_type s = warp_size; s > 0; s = s >> 1)
- {
- result_buffer[local_idx] =
- Operation::reduction_op(result_buffer[local_idx],
- result_buffer[local_idx + s]);
- }
- }
-
- if (local_idx == 0)
- Operation::atomic_op(result, result_buffer[0]);
- }
-
-
-
- template <typename Number, typename Operation>
- __global__ void
- reduction(Number *result, const Number *v, const size_type N)
- {
- __shared__ Number result_buffer[block_size];
-
- const size_type global_idx =
- threadIdx.x + blockIdx.x * (blockDim.x * chunk_size);
- const size_type local_idx = threadIdx.x;
-
- if (global_idx < N)
- result_buffer[local_idx] = Operation::element_wise_op(v[global_idx]);
- else
- result_buffer[local_idx] = Operation::null_value();
-
- __syncthreads();
-
- reduce<Number, Operation>(
- result, result_buffer, local_idx, global_idx, N);
- }
-
-
-
- template <typename Number>
- __device__ Number
- DotProduct<Number>::binary_op(const Number a, const Number b)
- {
- return a * b;
- }
-
-
-
- template <typename Number>
- __device__ Number
- DotProduct<Number>::reduction_op(const Number a, const Number b)
- {
- return a + b;
- }
-
-
-
- template <typename Number>
- __device__ Number
- DotProduct<Number>::atomic_op(Number *dst, const Number a)
- {
- return atomicAdd(dst, a);
- }
-
-
-
- template <typename Number>
- __device__ Number
- DotProduct<Number>::null_value()
- {
- return Number();
- }
-
-
-
- template <typename Number, typename Operation>
- __global__ void
- double_vector_reduction(Number *result,
- const Number *v1,
- const Number *v2,
- const size_type N)
- {
- __shared__ Number result_buffer[block_size];
-
- const size_type global_idx =
- threadIdx.x + blockIdx.x * (blockDim.x * chunk_size);
- const size_type local_idx = threadIdx.x;
-
- if (global_idx < N)
- result_buffer[local_idx] =
- Operation::binary_op(v1[global_idx], v2[global_idx]);
- else
- result_buffer[local_idx] = Operation::null_value();
-
- for (unsigned int i = 1; i < chunk_size; ++i)
- {
- const size_type idx = global_idx + i * block_size;
- if (idx < N)
- result_buffer[local_idx] =
- Operation::reduction_op(result_buffer[local_idx],
- Operation::binary_op(v1[idx], v2[idx]));
- }
-
- __syncthreads();
-
- reduce<Number, Operation>(
- result, result_buffer, local_idx, global_idx, N);
- }
-
-
-
- template <typename Number>
- __global__ void
- vec_add(Number *val, const Number a, const size_type N)
- {
- const size_type idx_base =
- threadIdx.x + blockIdx.x * (blockDim.x * chunk_size);
- for (unsigned int i = 0; i < chunk_size; ++i)
- {
- const size_type idx = idx_base + i * block_size;
- if (idx < N)
- val[idx] += a;
- }
- }
-
-
-
- template <typename Number>
- __global__ void
- add_aV(Number *val,
- const Number a,
- const Number *V_val,
- const size_type N)
- {
- const size_type idx_base =
- threadIdx.x + blockIdx.x * (blockDim.x * chunk_size);
- for (unsigned int i = 0; i < chunk_size; ++i)
- {
- const size_type idx = idx_base + i * block_size;
- if (idx < N)
- val[idx] += a * V_val[idx];
- }
- }
-
-
-
- template <typename Number>
- __global__ void
- add_aVbW(Number *val,
- const Number a,
- const Number *V_val,
- const Number b,
- const Number *W_val,
- const size_type N)
- {
- const size_type idx_base =
- threadIdx.x + blockIdx.x * (blockDim.x * chunk_size);
- for (unsigned int i = 0; i < chunk_size; ++i)
- {
- const size_type idx = idx_base + i * block_size;
- if (idx < N)
- val[idx] += a * V_val[idx] + b * W_val[idx];
- }
- }
-
-
-
- template <typename Number>
- __global__ void
- sadd(const Number s,
- Number *val,
- const Number a,
- const Number *V_val,
- const size_type N)
- {
- const size_type idx_base =
- threadIdx.x + blockIdx.x * (blockDim.x * chunk_size);
- for (unsigned int i = 0; i < chunk_size; ++i)
- {
- const size_type idx = idx_base + i * block_size;
- if (idx < N)
- val[idx] = s * val[idx] + a * V_val[idx];
- }
- }
-
-
-
- template <typename Number>
- __global__ void
- sadd(const Number s,
- Number *val,
- const Number a,
- const Number *V_val,
- const Number b,
- const Number *W_val,
- const size_type N)
- {
- const size_type idx_base =
- threadIdx.x + blockIdx.x * (blockDim.x * chunk_size);
- for (unsigned int i = 0; i < chunk_size; ++i)
- {
- const size_type idx = idx_base + i * block_size;
- if (idx < N)
- val[idx] = s * val[idx] + a * V_val[idx] + b * W_val[idx];
- }
- }
-
-
-
- template <typename Number>
- __global__ void
- scale(Number *val, const Number *V_val, const size_type N)
- {
- const size_type idx_base =
- threadIdx.x + blockIdx.x * (blockDim.x * chunk_size);
- for (unsigned int i = 0; i < chunk_size; ++i)
- {
- const size_type idx = idx_base + i * block_size;
- if (idx < N)
- val[idx] *= V_val[idx];
- }
- }
-
-
-
- template <typename Number>
- __global__ void
- equ(Number *val, const Number a, const Number *V_val, const size_type N)
- {
- const size_type idx_base =
- threadIdx.x + blockIdx.x * (blockDim.x * chunk_size);
- for (unsigned int i = 0; i < chunk_size; ++i)
- {
- const size_type idx = idx_base + i * block_size;
- if (idx < N)
- val[idx] = a * V_val[idx];
- }
- }
-
-
-
- template <typename Number>
- __global__ void
- equ(Number *val,
- const Number a,
- const Number *V_val,
- const Number b,
- const Number *W_val,
- const size_type N)
- {
- const size_type idx_base =
- threadIdx.x + blockIdx.x * (blockDim.x * chunk_size);
- for (unsigned int i = 0; i < chunk_size; ++i)
- {
- const size_type idx = idx_base + i * block_size;
- if (idx < N)
- val[idx] = a * V_val[idx] + b * W_val[idx];
- }
- }
-
-
-
- template <typename Number>
- __global__ void
- add_and_dot(Number *res,
- Number *v1,
- const Number *v2,
- const Number *v3,
- const Number a,
- const size_type N)
- {
- __shared__ Number res_buf[block_size];
-
- const unsigned int global_idx =
- threadIdx.x + blockIdx.x * (blockDim.x * chunk_size);
- const unsigned int local_idx = threadIdx.x;
- if (global_idx < N)
- {
- v1[global_idx] += a * v2[global_idx];
- res_buf[local_idx] =
- v1[global_idx] *
- Number(numbers::NumberTraits<Number>::conjugate(v3[global_idx]));
- }
- else
- res_buf[local_idx] = 0.;
-
- for (unsigned int i = 1; i < chunk_size; ++i)
- {
- const unsigned int idx = global_idx + i * block_size;
- if (idx < N)
- {
- v1[idx] += a * v2[idx];
- res_buf[local_idx] += v1[idx] * v3[idx];
- }
- }
-
- __syncthreads();
-
- reduce<Number, DotProduct<Number>>(
- res, res_buf, local_idx, global_idx, N);
- }
-
-
-
- template <typename Number>
- __global__ void
- set(Number *val, const Number s, const size_type N)
- {
- const size_type idx_base =
- threadIdx.x + blockIdx.x * (blockDim.x * chunk_size);
- for (unsigned int i = 0; i < chunk_size; ++i)
- {
- const size_type idx = idx_base + i * block_size;
- if (idx < N)
- val[idx] = s;
- }
- }
-
-
-
- template <typename Number, typename IndexType>
- __global__ void
- set_permutated(const IndexType *indices,
- Number *val,
- const Number *v,
- const IndexType N)
- {
- const size_type idx_base =
- threadIdx.x + blockIdx.x * (blockDim.x * chunk_size);
- for (unsigned int i = 0; i < chunk_size; ++i)
- {
- const size_type idx = idx_base + i * block_size;
- if (idx < N)
- val[indices[idx]] = v[idx];
- }
- }
-
-
-
- template <typename Number, typename IndexType>
- __global__ void
- gather(Number *val,
- const IndexType *indices,
- const Number *v,
- const IndexType N)
- {
- const IndexType idx_base =
- threadIdx.x + blockIdx.x * (blockDim.x * chunk_size);
- for (unsigned int i = 0; i < chunk_size; ++i)
- {
- const IndexType idx = idx_base + i * block_size;
- if (idx < N)
- val[idx] = v[indices[idx]];
- }
- }
-
-
-
- template <typename Number>
- __global__ void
- add_permutated(const size_type *indices,
- Number *val,
- const Number *v,
- const size_type N)
- {
- const size_type idx_base =
- threadIdx.x + blockIdx.x * (blockDim.x * chunk_size);
- for (unsigned int i = 0; i < chunk_size; ++i)
- {
- const size_type idx = idx_base + i * block_size;
- if (idx < N)
- val[indices[idx]] += v[idx];
- }
- }
- } // namespace kernel
- } // namespace CUDAWrappers
-} // namespace LinearAlgebra
-
-DEAL_II_NAMESPACE_CLOSE
-
-#endif
-
-#endif
+++ /dev/null
-// ------------------------------------------------------------------------
-//
-// SPDX-License-Identifier: LGPL-2.1-or-later
-// Copyright (C) 2018 - 2023 by the deal.II authors
-//
-// This file is part of the deal.II library.
-//
-// Part of the source code is dual licensed under Apache-2.0 WITH
-// LLVM-exception OR LGPL-2.1-or-later. Detailed license information
-// governing the source code and code contributions can be found in
-// LICENSE.md and CONTRIBUTING.md at the top level directory of deal.II.
-//
-// ------------------------------------------------------------------------
-
-#ifndef dealii_cuda_precondition_h
-#define dealii_cuda_precondition_h
-
-#include <deal.II/base/config.h>
-
-#include <deal.II/base/cuda.h>
-#include <deal.II/base/smartpointer.h>
-
-#include <memory>
-
-#ifdef DEAL_II_WITH_CUDA
-
-DEAL_II_NAMESPACE_OPEN
-
-// forward-definition
-# ifndef DOXYGEN
-namespace LinearAlgebra
-{
- namespace CUDAWrappers
- {
- template <typename Number>
- class Vector;
- }
-} // namespace LinearAlgebra
-# endif
-
-namespace CUDAWrappers
-{
- // forward definition
- template <typename Number>
- class SparseMatrix;
-
- /**
- * This class implements an incomplete Cholesky factorization (IC)
- * preconditioner for @em symmetric CUDAWrappers::SparseMatrix matrices.
- *
- * The implementation closely follows the one documented in the cuSPARSE
- * documentation
- * (https://docs.nvidia.com/cuda/cusparse/index.html#cusparse-lt-t-gt-csric02).
- *
- * @note Instantiations for this template are provided for <tt>@<float@> and
- * @<double@></tt>.
- *
- * @ingroup Preconditioners CUDAWrappers
- */
- template <typename Number>
- class PreconditionIC
- {
- public:
- /**
- * Declare the type for container size.
- */
- using size_type = int;
-
- /**
- * Standardized data struct to pipe additional flags to the
- * preconditioner.
- */
- struct AdditionalData
- {
- /**
- * Constructor. cuSPARSE allows to compute and use level information.
- * According to the documentation this might improve performance.
- * It is suggested to try both options.
- */
- AdditionalData(bool use_level_analysis = true);
-
- /**
- * Flag that determines if level information is used when creating and
- * applying the preconditioner. See the documentation for
- * cusparseSolvePolicy_t at
- * https://docs.nvidia.com/cuda/cusparse/index.html#cusparsesolvepolicy_t
- * for more information.
- */
- bool use_level_analysis;
- };
-
- /**
- * Constructor.
- */
- PreconditionIC(const Utilities::CUDA::Handle &handle);
-
- /**
- * The copy constructor is deleted.
- */
- PreconditionIC(const PreconditionIC<Number> &) = delete;
-
- /**
- * The copy assignment operator is deleted.
- */
- PreconditionIC &
- operator=(const PreconditionIC<Number> &) = delete;
-
- /**
- * Destructor. Free all resources that were initialized in this class.
- */
- ~PreconditionIC();
-
- /**
- * Initialize this object. In particular, the given matrix is copied to be
- * modified in-place. For the underlying sparsity pattern pointers are
- * stored. Specifically, this means
- * that the current object can only be used reliably as long as @p matrix is valid
- * and has not been changed since calling this function.
- *
- * The @p additional_data determines if level information are used.
- */
- void
- initialize(const SparseMatrix<Number> &matrix,
- const AdditionalData &additional_data = AdditionalData());
-
- /**
- * Apply the preconditioner.
- */
- void
- vmult(LinearAlgebra::CUDAWrappers::Vector<Number> &dst,
- const LinearAlgebra::CUDAWrappers::Vector<Number> &src) const;
-
- /**
- * Apply the preconditioner. Since the preconditioner is symmetric, this
- * is the same as vmult().
- */
- void
- Tvmult(LinearAlgebra::CUDAWrappers::Vector<Number> &dst,
- const LinearAlgebra::CUDAWrappers::Vector<Number> &src) const;
-
- /**
- * Return the dimension of the codomain (or range) space. Note that the
- * matrix is square and has dimension $m \times m$.
- *
- * @note This function should only be called if the preconditioner has been
- * initialized.
- */
- size_type
- m() const;
-
- /**
- * Return the dimension of the codomain (or range) space. Note that the
- * matrix is square and has dimension $n \times n$.
- *
- * @note This function should only be called if the preconditioner has been
- * initialized.
- */
- size_type
- n() const;
-
- private:
- /**
- * cuSPARSE handle used to call cuSPARSE functions.
- */
- cusparseHandle_t cusparse_handle;
-
- /**
- * cuSPARSE description of the sparse matrix $M=LL^T$.
- */
- cusparseMatDescr_t descr_M;
-
- /**
- * cuSPARSE description of the lower triangular matrix $L$.
- */
- cusparseMatDescr_t descr_L;
-
- /**
- * Solve and analysis structure for $M=LL^T$.
- */
- csric02Info_t info_M;
-
- /**
- * Solve and analysis structure for the lower triangular matrix $L$.
- */
- csrsv2Info_t info_L;
-
- /**
- * Solve and analysis structure for the upper triangular matrix $L^T$.
- */
- csrsv2Info_t info_Lt;
-
- /**
- * Pointer to the matrix this object was initialized with.
- */
- SmartPointer<const SparseMatrix<Number>> matrix_pointer;
-
- /**
- * Pointer to the values (on the @ref GlossDevice "device") of the computed preconditioning
- * matrix.
- */
- std::unique_ptr<Number[], void (*)(Number *)> P_val_dev;
-
- /**
- * Pointer to the row pointer (on the @ref GlossDevice "device") of the sparse matrix this
- * object was initialized with. Guarded by matrix_pointer.
- */
- const int *P_row_ptr_dev;
-
- /**
- * Pointer to the column indices (on the @ref GlossDevice "device") of the sparse matrix this
- * object was initialized with. Guarded by matrix_pointer.
- */
- const int *P_column_index_dev;
-
- /**
- * Pointer to the value (on the @ref GlossDevice "device") for a temporary (helper) vector
- * used in vmult().
- */
- std::unique_ptr<Number[], void (*)(Number *)> tmp_dev;
-
- /**
- * Pointer to an internal buffer (on the @ref GlossDevice "device") that is used for
- * computing the decomposition.
- */
- std::unique_ptr<void, void (*)(void *)> buffer_dev;
-
- /**
- * Determine if level information should be generated for the lower
- * triangular matrix $L$. This value can be modified through an
- * AdditionalData object.
- */
- cusparseSolvePolicy_t policy_L;
-
- /**
- * Determine if level information should be generated for the upper
- * triangular matrix $L^T$. This value can be modified through an
- * AdditionalData object.
- */
- cusparseSolvePolicy_t policy_Lt;
-
- /**
- * Determine if level information should be generated for $M=LL^T$. This
- * value can be modified through an AdditionalData object.
- */
- cusparseSolvePolicy_t policy_M;
-
- /**
- * The number of rows is the same as for the matrix this object has been
- * initialized with.
- */
- int n_rows;
-
- /**
- * The number of non-zero elements is the same as for the matrix this
- * object has been initialized with.
- */
- int n_nonzero_elements;
- };
-
- /**
- * This class implements an incomplete LU factorization preconditioner for
- * CUDAWrappers::SparseMatrix matrices.
- *
- * The implementation closely follows the one documented in the cuSPARSE
- * documentation
- * (https://docs.nvidia.com/cuda/cusparse/index.html#cusparse-lt-t-gt-csrilu02).
- *
- * @note Instantiations for this template are provided for <tt>@<float@> and
- * @<double@></tt>.
- *
- * @ingroup Preconditioners CUDAWrappers
- */
- template <typename Number>
- class PreconditionILU
- {
- public:
- /**
- * Declare the type for container size.
- */
- using size_type = int;
-
- /**
- * Standardized data struct to pipe additional flags to the
- * preconditioner.
- */
- struct AdditionalData
- {
- /**
- * Constructor. cuSPARSE allows to compute and use level information.
- * to the documentation this might improve performance.
- * It is suggested to try both options.
- */
- AdditionalData(bool use_level_analysis = true);
-
- /**
- * Flag that determines if level information is used when creating and
- * applying the preconditioner. See the documentation for
- * cusparseSolvePolicy_t at
- * https://docs.nvidia.com/cuda/cusparse/index.html#cusparsesolvepolicy_t
- * for more information.
- */
- bool use_level_analysis;
- };
-
- /**
- * Constructor.
- */
- PreconditionILU(const Utilities::CUDA::Handle &handle);
-
- /**
- * The copy constructor is deleted.
- */
- PreconditionILU(const PreconditionILU<Number> &) = delete;
-
- /**
- * The copy assignment operator is deleted.
- */
- PreconditionILU &
- operator=(const PreconditionILU<Number> &) = delete;
-
- /**
- * Destructor. Free all resources that were initialized in this class.
- */
- ~PreconditionILU();
-
- /**
- * Initialize this object. In particular, the given matrix is copied to be
- * modified in-place. For the underlying sparsity pattern pointers are
- * stored. Specifically, this means
- * that the current object can only be used reliably as long as @p matrix is valid
- * and has not been changed since calling this function.
- *
- * The @p additional_data determines if level information are used.
- */
- void
- initialize(const SparseMatrix<Number> &matrix,
- const AdditionalData &additional_data = AdditionalData());
-
- /**
- * Apply the preconditioner.
- */
- void
- vmult(LinearAlgebra::CUDAWrappers::Vector<Number> &dst,
- const LinearAlgebra::CUDAWrappers::Vector<Number> &src) const;
-
- /**
- * Apply the transposed preconditioner. Not yet implemented.
- */
- void
- Tvmult(LinearAlgebra::CUDAWrappers::Vector<Number> &dst,
- const LinearAlgebra::CUDAWrappers::Vector<Number> &src) const;
-
- /**
- * Return the dimension of the codomain (or range) space. Note that the
- * matrix is square and has dimension $m \times m$.
- *
- * @note This function should only be called if the preconditioner has been
- * initialized.
- */
- size_type
- m() const;
-
- /**
- * Return the dimension of the codomain (or range) space. Note that the
- * matrix is square and has dimension $n \times n$.
- *
- * @note This function should only be called if the preconditioner has been
- * initialized.
- */
- size_type
- n() const;
-
- private:
- /**
- * cuSPARSE handle used to call cuSPARSE functions.
- */
- cusparseHandle_t cusparse_handle;
-
- /**
- * cuSPARSE description of the sparse matrix $M=LU$.
- */
- cusparseMatDescr_t descr_M;
-
- /**
- * cuSPARSE description of the lower triangular matrix $L$.
- */
- cusparseMatDescr_t descr_L;
-
- /**
- * cuSPARSE description of the upper triangular matrix $U$.
- */
- cusparseMatDescr_t descr_U;
-
- /**
- * Solve and analysis structure for $M=LU$.
- */
- csrilu02Info_t info_M;
-
- /**
- * Solve and analysis structure for the lower triangular matrix $L$.
- */
- csrsv2Info_t info_L;
-
- /**
- * Solve and analysis structure for the upper triangular matrix $U$.
- */
- csrsv2Info_t info_U;
-
- /**
- * Pointer to the matrix this object was initialized with.
- */
- SmartPointer<const SparseMatrix<Number>> matrix_pointer;
-
- /**
- * Pointer to the values (on the @ref GlossDevice "device") of the computed preconditioning
- * matrix.
- */
- std::unique_ptr<Number[], void (*)(Number *)> P_val_dev;
-
- /**
- * Pointer to the row pointer (on the @ref GlossDevice "device") of the sparse matrix this
- * object was initialized with. Guarded by matrix_pointer.
- */
- const int *P_row_ptr_dev;
-
- /**
- * Pointer to the column indices (on the @ref GlossDevice "device") of the sparse matrix this
- * object was initialized with. Guarded by matrix_pointer.
- */
- const int *P_column_index_dev;
-
- /**
- * Pointer to the value (on the @ref GlossDevice "device") for a temporary (helper) vector
- * used in vmult().
- */
- std::unique_ptr<Number[], void (*)(Number *)> tmp_dev;
-
- /**
- * Pointer to an internal buffer (on the @ref GlossDevice "device") that is used for
- * computing the decomposition.
- */
- std::unique_ptr<void, void (*)(void *)> buffer_dev;
-
- /**
- * Determine if level information should be generated for the lower
- * triangular matrix $L$. This value can be modified through an
- * AdditionalData object.
- */
- cusparseSolvePolicy_t policy_L;
-
- /**
- * Determine if level information should be generated for the upper
- * triangular matrix $U$. This value can be modified through an
- * AdditionalData object.
- */
- cusparseSolvePolicy_t policy_U;
-
- /**
- * Determine if level information should be generated for $M=LU$. This
- * value can be modified through an AdditionalData object.
- */
- cusparseSolvePolicy_t policy_M;
-
- /**
- * The number of rows is the same as for the matrix this object has been
- * initialized with.
- */
- int n_rows;
-
- /**
- * The number of non-zero elements is the same as for the matrix this
- * object has been initialized with.
- */
- int n_nonzero_elements;
- };
-
- /*--------------------------- inline functions ----------------------------*/
-
-# ifndef DOXYGEN
- template <typename Number>
- inline typename PreconditionIC<Number>::size_type
- PreconditionIC<Number>::m() const
- {
- return n_rows;
- }
-
-
-
- template <typename Number>
- inline typename PreconditionIC<Number>::size_type
- PreconditionIC<Number>::n() const
- {
- return n_rows;
- }
-
-
-
- template <typename Number>
- inline typename PreconditionILU<Number>::size_type
- PreconditionILU<Number>::m() const
- {
- return n_rows;
- }
-
-
-
- template <typename Number>
- inline typename PreconditionILU<Number>::size_type
- PreconditionILU<Number>::n() const
- {
- return n_rows;
- }
-# endif // DOXYGEN
-
-} // namespace CUDAWrappers
-
-DEAL_II_NAMESPACE_CLOSE
-
-#endif // DEAL_II_WITH_CUDA
-
-#endif // dealii_cuda_precondition_h
+++ /dev/null
-// ------------------------------------------------------------------------
-//
-// SPDX-License-Identifier: LGPL-2.1-or-later
-// Copyright (C) 2018 - 2024 by the deal.II authors
-//
-// This file is part of the deal.II library.
-//
-// Part of the source code is dual licensed under Apache-2.0 WITH
-// LLVM-exception OR LGPL-2.1-or-later. Detailed license information
-// governing the source code and code contributions can be found in
-// LICENSE.md and CONTRIBUTING.md at the top level directory of deal.II.
-//
-// ------------------------------------------------------------------------
-
-#ifndef dealii_cuda_solver_direct_h
-#define dealii_cuda_solver_direct_h
-
-#include <deal.II/base/config.h>
-
-#ifdef DEAL_II_WITH_CUDA
-# include <deal.II/base/cuda.h>
-
-# include <deal.II/lac/cuda_sparse_matrix.h>
-# include <deal.II/lac/cuda_vector.h>
-# include <deal.II/lac/solver_control.h>
-
-DEAL_II_NAMESPACE_OPEN
-
-namespace CUDAWrappers
-{
- /**
- * Direct solvers. These solvers call cuSOLVER underneath.
- *
- * @note Instantiations for this template are provided for <tt>@<float@></tt>
- * and <tt>@<double@></tt>.
- *
- * @ingroup CUDAWrappers
- */
- template <typename Number>
- class SolverDirect
- {
- public:
- /**
- * Struct for additional settings for SolverDirect.
- */
- struct AdditionalData
- {
- /**
- * Set the additional data field to the desired solver.
- */
- explicit AdditionalData(const std::string &solver_type = "LU_dense");
-
- /**
- * Set the solver type. Possibilities are:
- * <ul>
- * <li> "Cholesky" which performs a Cholesky decomposition on the
- * @ref GlossDevice "device"
- * </li>
- * <li> "LU_dense" which converts the sparse matrix to a dense
- * matrix and uses LU factorization </li>
- * <li> "LU_host" which uses LU factorization on the host </li>
- * </ul>
- */
- std::string solver_type;
- };
-
- /**
- * Constructor. Takes the solver control object and creates the solver.
- */
- SolverDirect(const Utilities::CUDA::Handle &handle,
- SolverControl &cn,
- const AdditionalData &data = AdditionalData());
-
- /**
- * Destructor.
- */
- virtual ~SolverDirect() = default;
-
- /**
- * Solve the linear system <tt>Ax=b</tt>.
- */
- void
- solve(const SparseMatrix<Number> &A,
- LinearAlgebra::CUDAWrappers::Vector<Number> &x,
- const LinearAlgebra::CUDAWrappers::Vector<Number> &b);
-
- /**
- * Access to object that controls convergence.
- */
- SolverControl &
- control() const;
-
- private:
- /**
- * Handle
- */
- const Utilities::CUDA::Handle &cuda_handle;
-
- /**
- * Reference to the object that controls convergence of the iterative
- * solver. In fact, for these CUDA wrappers, cuSOLVER and cuSPARSE do so
- * themselves, but we copy the data from this object before starting the
- * solution process, and copy the data back into it afterwards.
- */
- SolverControl &solver_control;
-
- /**
- * Store a copy of the flags for this particular solver.
- */
- const AdditionalData additional_data;
- };
-} // namespace CUDAWrappers
-
-DEAL_II_NAMESPACE_CLOSE
-
-#endif
-
-#endif
+++ /dev/null
-// ------------------------------------------------------------------------
-//
-// SPDX-License-Identifier: LGPL-2.1-or-later
-// Copyright (C) 2018 - 2023 by the deal.II authors
-//
-// This file is part of the deal.II library.
-//
-// Part of the source code is dual licensed under Apache-2.0 WITH
-// LLVM-exception OR LGPL-2.1-or-later. Detailed license information
-// governing the source code and code contributions can be found in
-// LICENSE.md and CONTRIBUTING.md at the top level directory of deal.II.
-//
-// ------------------------------------------------------------------------
-
-#ifndef dealii_cuda_sparse_matrix_h
-#define dealii_cuda_sparse_matrix_h
-
-#include <deal.II/base/config.h>
-
-#include <deal.II/base/subscriptor.h>
-
-#include <iomanip>
-
-#ifdef DEAL_II_WITH_CUDA
-# include <deal.II/base/cuda.h>
-
-# include <deal.II/lac/cuda_vector.h>
-# include <deal.II/lac/sparse_matrix.h>
-
-# include <cusparse.h>
-
-DEAL_II_NAMESPACE_OPEN
-
-namespace CUDAWrappers
-{
- /**
- * This class is a wrapper around cuSPARSE csr sparse matrix. Unlike deal.II's
- * own SparseMatrix all elements within each row are stored in increasing
- * column index order.
- *
- * @note Instantiations for this template are provided for <tt>@<float@> and
- * @<double@></tt>.
- *
- * @ingroup Matrix1
- */
- template <typename Number>
- class SparseMatrix : public virtual Subscriptor
- {
- public:
- /**
- * Declare type for container size.
- */
- using size_type = int;
-
- /**
- * Type of the matrix entries.
- */
- using value_type = Number;
-
- /**
- * Declare a type that holds real-valued numbers with the same precision
- * as the template argument to this class.
- */
- using real_type = Number;
-
- /**
- * @name Constructors and initialization
- */
- /** @{ */
- /**
- * Constructor. Initialize the matrix to be empty, without any structure,
- * i.e., the matrix is not usable at all. This constructor is therefore
- * only useful for matrices which are members of a class.
- *
- * You have to initialize the matrix before usage with reinit.
- */
- SparseMatrix();
-
- /**
- * Constructor. Takes a Utilities::CUDA::Handle and a sparse matrix on the
- * host. The sparse matrix on the host is copied on the @ref GlossDevice "device" and the
- * elements are reordered according to the format supported by cuSPARSE.
- */
- SparseMatrix(Utilities::CUDA::Handle &handle,
- const ::dealii::SparseMatrix<Number> &sparse_matrix_host);
-
- /**
- * Move constructor. Create a new SparseMatrix by stealing the internal
- * data.
- */
- SparseMatrix(CUDAWrappers::SparseMatrix<Number> &&);
-
- /**
- * Copy constructor is deleted.
- */
- SparseMatrix(const CUDAWrappers::SparseMatrix<Number> &) = delete;
-
- /**
- * Destructor. Free all memory.
- */
- ~SparseMatrix();
-
- /**
- * Move assignment operator.
- */
- SparseMatrix &
- operator=(CUDAWrappers::SparseMatrix<Number> &&);
-
- /**
- * Copy assignment is deleted.
- */
- SparseMatrix &
- operator=(const CUDAWrappers::SparseMatrix<Number> &) = delete;
-
- /**
- * Reinitialize the sparse matrix. The sparse matrix on the host is copied
- * to the @ref GlossDevice "device" and the elementes are reordered according to the format
- * supported by cuSPARSE.
- */
- void
- reinit(Utilities::CUDA::Handle &handle,
- const ::dealii::SparseMatrix<Number> &sparse_matrix_host);
- /** @} */
-
- /**
- * @name Information on the matrix
- */
- /** @{ */
- /**
- * Return the dimension of the codomain (or range) space. Note that the
- * matrix is of dimension $m \times n$.
- */
- size_type
- m() const;
-
- /**
- * Return the dimension of the domain space. Note that the matrix is of
- * dimension $m \times n$.
- */
- size_type
- n() const;
-
- /**
- * Return the number of nonzero elements of this matrix. Actually, it
- * returns the number of entries in the sparsity pattern; if any of the
- * entries should happen to be zero, it is counted anyway.
- */
- std::size_t
- n_nonzero_elements() const;
-
- /**
- * Print the matrix to the given stream, using the format <tt>(row,column)
- * value</tt>, i.e. one nonzero entry of the matrix per line. If
- * <tt>across</tt> is true, print all entries on a single line, using the
- * format row,column:value.
- *
- * If the argument <tt>diagonal_first</tt> is true, diagonal elements of
- * quadratic matrices are printed first in their row. If it is false,
- * the elements in a row are written in ascending column order.
- */
- template <typename StreamType>
- void
- print(StreamType &out,
- const bool across = false,
- const bool diagonal_first = true) const;
-
- /**
- * Print the matrix in the usual format, i.e., as a matrix and not as a list
- * of nonzero elements. For better readability, elements not in the matrix
- * are displayed as empty space, while matrix elements which are explicitly
- * set to zero are displayed as such.
- *
- * The parameters allow for a flexible setting of the output format:
- * @p precision and @p scientific are used to determine the number format,
- * where <code>scientific = false</code> means fixed point notation. A zero
- * entry for @p width makes the function compute a width, but it may be
- * changed to a positive value, if output is crude.
- *
- * Additionally, a character for an empty value may be specified in
- * @p zero_string, and a character to separate row entries can be set in
- * @p separator.
- *
- * Finally, the whole matrix can be multiplied with a common @p denominator
- * to produce more readable output, even integers.
- *
- * @attention This function may produce @em large amounts of output if
- * applied to a large matrix!
- */
- void
- print_formatted(std::ostream &out,
- const unsigned int precision = 3,
- const bool scientific = true,
- const unsigned int width = 0,
- const char *zero_string = " ",
- const double denominator = 1.,
- const char *separator = " ") const;
- /** @} */
-
- /**
- * @name Modifying entries
- */
- /** @{ */
- /**
- * Multiply the entire matrix by a fixed factor.
- */
- SparseMatrix &
- operator*=(const Number factor);
-
- /**
- * Divide the entire matrix by a fixed factor.
- */
- SparseMatrix &
- operator/=(const Number factor);
- /** @} */
-
- /**
- * @name Multiplications
- */
- /** @{ */
- /**
- * Matrix-vector multiplication: let $dst = M \cdot src$ with $M$
- * being this matrix.
- */
- void
- vmult(LinearAlgebra::CUDAWrappers::Vector<Number> &dst,
- const LinearAlgebra::CUDAWrappers::Vector<Number> &src) const;
-
- /**
- * Matrix-vector multiplication: let $dst = M^T \cdot src$ with
- * $M$ being this matrix. This function does the same as vmult() but
- * takes this transposed matrix.
- */
- void
- Tvmult(LinearAlgebra::CUDAWrappers::Vector<Number> &dst,
- const LinearAlgebra::CUDAWrappers::Vector<Number> &src) const;
-
- /**
- * Adding matrix-vector multiplication. Add $M \cdot src$ on $dst$
- * with $M$ being this matrix.
- */
- void
- vmult_add(LinearAlgebra::CUDAWrappers::Vector<Number> &dst,
- const LinearAlgebra::CUDAWrappers::Vector<Number> &src) const;
-
- /**
- * Adding matrix-vector multiplication. Add $M^T \cdot src$ to
- * $dst$ with $M$ being this matrix. This function foes the same
- * as vmult_add() but takes the transposed matrix.
- */
- void
- Tvmult_add(LinearAlgebra::CUDAWrappers::Vector<Number> &dst,
- const LinearAlgebra::CUDAWrappers::Vector<Number> &src) const;
-
- /**
- * Return the square of the norm of the vector $v$ with respect to the
- * norm induced by this matrix, i.e., $\left(v,Mv\right)$. This is useful,
- * e.g., in the finite context, where the $L_2$ norm of a function equals
- * the matrix norm with respect to the @ref GlossMassMatrix "mass matrix" of the vector
- * representing the nodal values of the finite element function.
- *
- * Obviously, the matrix needs to be quadratic for this operation.
- */
- Number
- matrix_norm_square(
- const LinearAlgebra::CUDAWrappers::Vector<Number> &v) const;
-
- /**
- * Compute the matrix scalar product $\left(u,Mv\right)$.
- */
- Number
- matrix_scalar_product(
- const LinearAlgebra::CUDAWrappers::Vector<Number> &u,
- const LinearAlgebra::CUDAWrappers::Vector<Number> &v) const;
-
- /**
- * Compute the residual of an equation $M \cdot x=b$, where the residual is
- * defined to be $r=b-M \cdot x$. Write the residual into $dst$. The
- * $l_2$ norm of the residual vector is returned.
- *
- * Source $x$ and destination $dst$ must not be the same vector.
- */
- Number
- residual(LinearAlgebra::CUDAWrappers::Vector<Number> &dst,
- const LinearAlgebra::CUDAWrappers::Vector<Number> &x,
- const LinearAlgebra::CUDAWrappers::Vector<Number> &b) const;
- /** @} */
-
- /**
- * @name Matrix norms
- */
- /** @{ */
- /**
- * Return the $l_1$-norm of the matrix, that is $|M|_1=\max_{\mathrm{all\
- * columns\ }j}\sum_{\mathrm{all\ rows\ }i} |M_{ij}|$, (max. sum of
- * columns). This is the natural matrix norm that is compatible to the
- * $l_1$-norm for vectors, i.e., $|Mv|_1\leq |M|_1 |v|_1$.
- */
- Number
- l1_norm() const;
-
- /**
- * Return the $l_\infty$-norm of the matrix, that is
- * $|M|_\infty=\max_{\mathrm{all\ rows\ }i}\sum_{\mathrm{all\ columns\ }j}
- * |M_{ij}|$, (max. sum of rows). This is the natural norm that is
- * compatible to the $l_\infty$-norm of vectors, i.e., $|Mv|_\infty \leq
- * |M|_\infty |v|_\infty$.
- */
- Number
- linfty_norm() const;
-
- /**
- * Return the frobenius norm of the matrix, i.e., the square root of the
- * sum of squares of all entries in the matrix.
- */
- Number
- frobenius_norm() const;
- /** @} */
-
- /**
- * @name Access to underlying CUDA data
- */
- /** @{ */
- /**
- * Return a tuple containing the pointer to the values of matrix, the
- * pointer to the columns indices, the pointer to the rows pointer,
- * the cuSPARSE matrix description, and the cuSPARSE SP matrix description.
- */
- std::tuple<Number *, int *, int *, cusparseMatDescr_t, cusparseSpMatDescr_t>
- get_cusparse_matrix() const;
- /** @} */
-
- private:
- /**
- * cuSPARSE handle used to call cuSPARSE functions.
- */
- cusparseHandle_t cusparse_handle;
-
- /**
- * Number of non-zero elements in the sparse matrix.
- */
- int nnz;
-
- /**
- * Number of rows of the sparse matrix.
- */
- int n_rows;
-
- /**
- * Number of columns of the sparse matrix.
- */
- int n_cols;
-
- /**
- * Pointer to the values (on the @ref GlossDevice "device") of the sparse matrix.
- */
- std::unique_ptr<Number[], void (*)(Number *)> val_dev;
-
- /**
- * Pointer to the column indices (on the @ref GlossDevice "device") of the sparse matrix.
- */
- std::unique_ptr<int[], void (*)(int *)> column_index_dev;
-
- /**
- * Pointer to the row pointer (on the @ref GlossDevice "device") of the sparse matrix.
- */
- std::unique_ptr<int[], void (*)(int *)> row_ptr_dev;
-
- /**
- * cuSPARSE description of the matrix.
- */
- cusparseMatDescr_t descr;
-
- /**
- * cuSPARSE description of the sparse matrix.
- */
- cusparseSpMatDescr_t sp_descr;
- };
-
-
-
- template <typename Number>
- inline typename SparseMatrix<Number>::size_type
- SparseMatrix<Number>::m() const
- {
- return n_rows;
- }
-
-
-
- template <typename Number>
- inline typename SparseMatrix<Number>::size_type
- SparseMatrix<Number>::n() const
- {
- return n_cols;
- }
-
-
-
- template <typename Number>
- inline std::size_t
- SparseMatrix<Number>::n_nonzero_elements() const
- {
- return nnz;
- }
-
-
-
- template <typename Number>
- template <typename StreamType>
- inline void
- SparseMatrix<Number>::print(StreamType &out,
- const bool across,
- const bool diagonal_first) const
- {
- Assert(column_index_dev != nullptr, ExcNotInitialized());
- Assert(val_dev != nullptr, ExcNotInitialized());
- Assert(row_ptr_dev != nullptr, ExcNotInitialized());
-
- std::vector<int> rows(n_rows + 1);
- std::vector<int> cols(nnz);
- std::vector<double> val(nnz);
- Utilities::CUDA::copy_to_host(row_ptr_dev.get(), rows);
- Utilities::CUDA::copy_to_host(column_index_dev.get(), cols);
- Utilities::CUDA::copy_to_host(val_dev.get(), val);
-
- bool has_diagonal = false;
- Number diagonal = Number();
-
- for (size_type i = 0; i < n_rows; ++i)
- {
- if (diagonal_first)
- {
- // find the diagonal and print if it exists
- for (size_type j = rows[i]; j < rows[i + 1] && cols[j] <= i; ++j)
- {
- if (i == cols[j])
- {
- diagonal = val[j];
- has_diagonal = true;
- if (across)
- out << ' ' << i << ',' << i << ':' << diagonal;
- else
- out << '(' << i << ',' << i << ") " << diagonal
- << std::endl;
- break;
- }
- }
- }
- for (size_type j = rows[i]; j < rows[i + 1]; ++j)
- {
- if (has_diagonal && i == cols[j])
- continue;
- if (across)
- out << ' ' << i << ',' << cols[j] << ':' << val[j];
- else
- out << '(' << i << ',' << cols[j] << ") " << val[j] << std::endl;
- }
- }
- if (across)
- out << std::endl;
- }
-
-
-
- template <typename Number>
- void
- SparseMatrix<Number>::print_formatted(std::ostream &out,
- const unsigned int precision,
- const bool scientific,
- const unsigned int width_,
- const char *zero_string,
- const double denominator,
- const char *separator) const
- {
- Assert(column_index_dev != nullptr, ExcNotInitialized());
- Assert(val_dev != nullptr, ExcNotInitialized());
- Assert(row_ptr_dev != nullptr, ExcNotInitialized());
-
- std::vector<int> rows(n_rows + 1);
- std::vector<int> cols(nnz);
- std::vector<Number> val(nnz);
- Utilities::CUDA::copy_to_host(row_ptr_dev.get(), rows);
- Utilities::CUDA::copy_to_host(column_index_dev.get(), cols);
- Utilities::CUDA::copy_to_host(val_dev.get(), val);
-
- unsigned int width = width_;
-
- std::ios::fmtflags old_flags = out.flags();
- unsigned int old_precision = out.precision(precision);
-
- if (scientific)
- {
- out.setf(std::ios::scientific, std::ios::floatfield);
- if (!width)
- width = precision + 7;
- }
- else
- {
- out.setf(std::ios::fixed, std::ios::floatfield);
- if (!width)
- width = precision + 2;
- }
-
- for (size_type i = 0; i < n_rows; ++i)
- {
- size_type j = rows[i];
- for (size_type k = 0; k < n_cols; ++k)
- {
- if (k == cols[j])
- {
- out << std::setw(width) << val[j] * Number(denominator)
- << separator;
- ++j;
- }
- else
- out << std::setw(width) << zero_string << separator;
- }
- out << std::endl;
- };
- AssertThrow(out.fail() == false, ExcIO());
-
- // reset output format
- out.precision(old_precision);
- out.flags(old_flags);
- }
-} // namespace CUDAWrappers
-
-DEAL_II_NAMESPACE_CLOSE
-
-#endif
-#endif
+++ /dev/null
-// ------------------------------------------------------------------------
-//
-// SPDX-License-Identifier: LGPL-2.1-or-later
-// Copyright (C) 2016 - 2024 by the deal.II authors
-//
-// This file is part of the deal.II library.
-//
-// Part of the source code is dual licensed under Apache-2.0 WITH
-// LLVM-exception OR LGPL-2.1-or-later. Detailed license information
-// governing the source code and code contributions can be found in
-// LICENSE.md and CONTRIBUTING.md at the top level directory of deal.II.
-//
-// ------------------------------------------------------------------------
-
-#ifndef dealii_cuda_vector_h
-#define dealii_cuda_vector_h
-
-#include <deal.II/base/config.h>
-
-#include <deal.II/base/communication_pattern_base.h>
-#include <deal.II/base/exceptions.h>
-#include <deal.II/base/index_set.h>
-
-#include <deal.II/lac/vector_operation.h>
-
-#ifdef DEAL_II_WITH_CUDA
-
-DEAL_II_NAMESPACE_OPEN
-
-// Forward declarations
-# ifndef DOXYGEN
-namespace LinearAlgebra
-{
- template <typename Number>
- class ReadWriteVector;
-}
-# endif
-
-namespace LinearAlgebra
-{
- /**
- * A Namespace for the CUDA vectors.
- */
- namespace CUDAWrappers
- {
- /**
- * This class implements a vector using CUDA for use on Nvidia GPUs.
- *
- * @note Only float and double are supported.
- *
- * <h4>Moving data</h4>
- * You can move data to/from the device as follows:
- * @code
- * unsigned int size = 10;
- * LinearAlgebra::ReadWriteVector<double> rw_vector(size);
- *
- * ...do something with the rw_vector...
- *
- * // Move the data to the device:
- * LinearAlgebra::CUDAWrappers::Vector<double> vector_dev(size);
- * vector_dev.import_elements(rw_vector, VectorOperations::insert);
- *
- * ...do some computations on the device...
- *
- * // Move the data back to the host:
- * rw_vector.import_elements(vector_dev, VectorOperations::insert);
- * @endcode
- *
- * @see CUDAWrappers
- * @ingroup Vectors
- */
- template <typename Number>
- class Vector
- {
- public:
- using value_type = Number;
- using size_type = types::global_dof_index;
- using real_type = typename numbers::NumberTraits<Number>::real_type;
-
- /**
- * Constructor. Create a vector of dimension zero.
- */
- Vector();
-
- /**
- * Copy constructor.
- */
- Vector(const Vector<Number> &V);
-
- /**
- * Move constructor.
- */
- Vector(Vector<Number> &&) noexcept = default;
-
- /**
- * Constructor. Set dimension to @p n and initialize all elements with
- * zero.
- *
- * The constructor is made explicit to avoid accident like this:
- * <tt>v=0;</tt>. Presumably, the user wants to set every elements of
- * the vector to zero, but instead, what happens is this call:
- * <tt>v=Vector@<Number@>(0);</tt>, i.e. the vector is replaced by one
- * of length zero.
- */
- explicit Vector(const size_type n);
-
- /**
- * Copy assignment operator.
- */
- Vector &
- operator=(const Vector<Number> &v);
-
- /**
- * Move assignment operator.
- */
- Vector &
- operator=(Vector<Number> &&v) noexcept = default;
-
- /**
- * Swap the contents of this vector and the other vector @p v. One could do
- * this operation with a temporary variable and copying over the data
- * elements, but this function is significantly more efficient since it
- * only swaps the pointers to the data of the two vectors and therefore
- * does not need to allocate temporary storage and move data around.
- *
- * This function is analogous to the @p swap function of all C++
- * standard containers. Also, there is a global function
- * <tt>swap(u,v)</tt> that simply calls <tt>u.swap(v)</tt>, again in
- * analogy to standard functions.
- */
- void
- swap(Vector<Number> &v);
-
- /**
- * Reinit functionality. The flag <tt>omit_zeroing_entries</tt>
- * determines whether the vector should be filled with zeros (`false`) or
- * left in an undetermined state (`true`).
- */
- void
- reinit(const size_type n, const bool omit_zeroing_entries = false);
-
- /**
- * Change the dimension to that of the vector V. The elements of V are not
- * copied.
- */
- void
- reinit(const Vector<Number> &V, const bool omit_zeroing_entries = false);
-
- /**
- * Import all the element from the input vector @p V.
- * VectorOperation::values @p operation is used to decide if the
- * elements int @p V should be added to the current vector or replace
- * the current elements. The last parameter is not used. It is only used
- * for distributed vectors. This is the function that should be used to
- * copy a vector to the GPU.
- */
- void
- import_elements(
- const ReadWriteVector<Number> &V,
- const VectorOperation::values operation,
- const std::shared_ptr<const Utilities::MPI::CommunicationPatternBase>
- &communication_pattern = {});
-
- /**
- * @deprecated Use import_elements() instead.
- */
- DEAL_II_DEPRECATED void
- import(const ReadWriteVector<Number> &V,
- VectorOperation::values operation,
- std::shared_ptr<const Utilities::MPI::CommunicationPatternBase>
- communication_pattern = {})
- {
- import_elements(V, operation, communication_pattern);
- }
-
- /**
- * Sets all elements of the vector to the scalar @p s. This operation is
- * only allowed if @p s is equal to zero.
- */
- Vector<Number> &
- operator=(const Number s);
-
- /**
- * Multiply the entive vector by a fixed factor.
- */
- Vector<Number> &
- operator*=(const Number factor);
-
- /**
- * Divide the entire vector by a fixed factor.
- */
- Vector<Number> &
- operator/=(const Number factor);
-
- /**
- * Add the vector @p V to the present one.
- */
- Vector<Number> &
- operator+=(const Vector<Number> &V);
-
- /**
- * Subtract the vector @p V from the present one.
- */
- Vector<Number> &
- operator-=(const Vector<Number> &V);
-
- /**
- * Return the scalar product of two vectors.
- */
- Number
- operator*(const Vector<Number> &V) const;
-
- /**
- * Add @p to all components. Note that @p a is a scalar not a vector.
- */
- void
- add(const Number a);
-
- /**
- * Simple addition of a multiple of a vector, i.e. <tt>*this += a*V</tt>.
- */
- void
- add(const Number a, const Vector<Number> &V);
-
- /**
- * Multiple additions of scaled vectors, i.e. <tt>*this += a*V+b*W</tt>.
- */
- void
- add(const Number a,
- const Vector<Number> &V,
- const Number b,
- const Vector<Number> &W);
-
- /**
- * Scaling and simple addition of a multiple of a vector, i.e. <tt>*this
- * = s*(*this)+a*V</tt>
- */
- void
- sadd(const Number s, const Number a, const Vector<Number> &V);
-
- /**
- * Scale each element of this vector by the corresponding element in the
- * argument. This function is mostly meant to simulate multiplication
- * (and immediate re-assignment) by a diagonal scaling matrix.
- */
- void
- scale(const Vector<Number> &scaling_factors);
-
- /**
- * Assignment <tt>*this = a*V</tt>.
- */
- void
- equ(const Number a, const Vector<Number> &V);
-
- /**
- * Return whether the vector contains only elements with value zero.
- */
- bool
- all_zero() const;
-
- /**
- * Return the mean value of all the entries of this vector.
- */
- value_type
- mean_value() const;
-
- /**
- * Return the l<sub>1</sub> norm of the vector (i.e., the sum of the
- * absolute values of all entries among all processors).
- */
- real_type
- l1_norm() const;
-
- /**
- * Return the l<sub>2</sub> norm of the vector (i.e., the square root of
- * the sum of the square of all entries among all processors).
- */
- real_type
- l2_norm() const;
-
- /**
- * Return the square of the $l_2$-norm.
- */
- real_type
- norm_sqr() const;
-
- /**
- * Return the maximum norm of the vector (i.e., the maximum absolute
- * value among all entries and among all processors).
- */
- real_type
- linfty_norm() const;
-
- /**
- * Perform a combined operation of a vector addition and a subsequent
- * inner product, returning the value of the inner product. In other
- * words, the result of this function is the same as if the user called
- * @code
- * this->add(a, V);
- * return_value = *this * W;
- * @endcode
- *
- * The reason this function exists is that this operation involves less
- * memory transfer than calling the two functions separately. This
- * method only needs to load three vectors, @p this, @p V, @p W, whereas
- * calling separate methods means to load the calling vector @p this
- * twice. Since most vector operations are memory transfer limited, this
- * reduces the time by 25\% (or 50\% if @p W equals @p this).
- *
- * For complex-valued vectors, the scalar product in the second step is
- * implemented as $\left<v,w\right>=\sum_i v_i \bar{w_i}$.
- */
- Number
- add_and_dot(const Number a,
- const Vector<Number> &V,
- const Vector<Number> &W);
-
- /**
- * Return the pointer to the underlying array. Ownership still resides
- * with this class.
- */
- Number *
- get_values() const;
-
- /**
- * Return the size of the vector.
- */
- size_type
- size() const;
-
- /**
- * Return an index set that describe which elements of this vector are
- * owned by the current processor, i.e. [0, size).
- */
- dealii::IndexSet
- locally_owned_elements() const;
-
- /**
- * Print the vector to the output stream @p out.
- */
- void
- print(std::ostream &out,
- const unsigned int precision = 2,
- const bool scientific = true,
- const bool across = true) const;
-
- /**
- * Return the memory consumption of this class in bytes.
- */
- std::size_t
- memory_consumption() const;
-
- /**
- * Attempt to perform an operation between two incompatible vector types.
- *
- * @ingroup Exceptions
- */
- DeclException0(ExcVectorTypeNotCompatible);
-
- private:
- /**
- * Pointer to the array of elements of this vector.
- */
- std::unique_ptr<Number[], void (*)(Number *)> val;
-
- /**
- * Number of elements in the vector.
- */
- size_type n_elements;
- };
- } // namespace CUDAWrappers
-} // namespace LinearAlgebra
-
-// ---------------------------- Inline functions --------------------------
-
-/**
- * Global function @p swap which overloads the default implementation of the
- * C++ standard library which uses a temporary object. The function simply
- * exchanges the data of the two vectors.
- *
- * @relatesalso Vector
- */
-template <typename Number>
-inline void
-swap(LinearAlgebra::CUDAWrappers::Vector<Number> &u,
- LinearAlgebra::CUDAWrappers::Vector<Number> &v)
-{
- u.swap(v);
-}
-
-namespace LinearAlgebra
-{
- namespace CUDAWrappers
- {
- template <typename Number>
- inline Number *
- Vector<Number>::get_values() const
- {
- return val.get();
- }
-
-
-
- template <typename Number>
- inline typename Vector<Number>::size_type
- Vector<Number>::size() const
- {
- return n_elements;
- }
-
-
- template <typename Number>
- inline IndexSet
- Vector<Number>::locally_owned_elements() const
- {
- return complete_index_set(n_elements);
- }
-
-
-
- template <typename Number>
- inline void
- Vector<Number>::swap(Vector<Number> &v)
- {
- std::swap(val, v.val);
- std::swap(n_elements, v.n_elements);
- }
- } // namespace CUDAWrappers
-} // namespace LinearAlgebra
-
-DEAL_II_NAMESPACE_CLOSE
-
-#endif
-
-#endif
#include <deal.II/base/config.h>
-#include <deal.II/base/cuda_size.h>
#include <deal.II/base/memory_space.h>
#include <deal.II/base/mutex.h>
#include <deal.II/base/parallel.h>
} // namespace TrilinosWrappers
# endif
-# ifdef DEAL_II_WITH_CUDA
-namespace LinearAlgebra
-{
- namespace CUDAWrappers
- {
- template <typename>
- class Vector;
- }
-} // namespace LinearAlgebra
-# endif
#endif
namespace LinearAlgebra
}
#endif
-#ifdef DEAL_II_WITH_CUDA
- /**
- * Import all the elements present in the vector's IndexSet from the input
- * vector @p cuda_vec. VectorOperation::values @p operation is used to
- * decide if the elements in @p V should be added to the current vector or
- * replace the current elements. The last parameter is not used.
- */
- void
- import_elements(
- const CUDAWrappers::Vector<Number> &cuda_vec,
- VectorOperation::values operation,
- const std::shared_ptr<const Utilities::MPI::CommunicationPatternBase>
- &communication_pattern = {});
-
-
- /**
- * @deprecated Use import_elements() instead.
- */
- DEAL_II_DEPRECATED
- void
- import(const CUDAWrappers::Vector<Number> &V,
- VectorOperation::values operation,
- const std::shared_ptr<const Utilities::MPI::CommunicationPatternBase>
- &communication_pattern = {})
- {
- import_elements(V, operation, communication_pattern);
- }
-#endif
-
/**
* The value returned by this function denotes the dimension of the vector
* spaces that are modeled by objects of this kind. However, objects of
# include <Epetra_Import.h>
#endif
-#ifdef DEAL_II_WITH_CUDA
-# include <deal.II/lac/cuda_vector.h>
-#endif
-
#include <boost/io/ios_state.hpp>
DEAL_II_NAMESPACE_OPEN
-#ifdef DEAL_II_WITH_CUDA
- template <typename Number>
- void
- ReadWriteVector<Number>::import_elements(
- const LinearAlgebra::CUDAWrappers::Vector<Number> &cuda_vec,
- VectorOperation::values operation,
- const std::shared_ptr<const Utilities::MPI::CommunicationPatternBase> &)
- {
- const unsigned int n_elements = stored_elements.n_elements();
- if (operation == VectorOperation::insert)
- {
- cudaError_t error_code = cudaMemcpy(values.data(),
- cuda_vec.get_values(),
- n_elements * sizeof(Number),
- cudaMemcpyDeviceToHost);
- AssertCuda(error_code);
- }
- else if (operation == VectorOperation::add)
- {
- // Copy the vector from the device to a temporary vector on the host
- std::vector<Number> tmp(n_elements);
- cudaError_t error_code = cudaMemcpy(tmp.data(),
- cuda_vec.get_values(),
- n_elements * sizeof(Number),
- cudaMemcpyDeviceToHost);
- AssertCuda(error_code);
-
- // Add the two vectors
- for (unsigned int i = 0; i < n_elements; ++i)
- values[i] += tmp[i];
- }
- else if (operation == VectorOperation::min)
- {
- // Copy the vector from the device to a temporary vector on the host
- std::vector<Number> tmp(n_elements);
- cudaError_t error_code = cudaMemcpy(tmp.data(),
- cuda_vec.get_values(),
- n_elements * sizeof(Number),
- cudaMemcpyDeviceToHost);
- AssertCuda(error_code);
-
- // To ensure that this code also compiles with complex
- // numbers, we only compare the real part of the
- // variable. Note that min/max do not make sense with complex
- // numbers.
- for (unsigned int i = 0; i < n_elements; ++i)
- {
- Assert(
- std::imag(tmp[i]) == 0.,
- ExcMessage(
- "VectorOperation::min is not defined if there is an imaginary part!)"));
- Assert(
- std::imag(values[i]) == 0.,
- ExcMessage(
- "VectorOperation::min is not defined if there is an imaginary part!)"));
- if (std::real(tmp[i]) - std::real(values[i]) < 0.0)
- values[i] = tmp[i];
- }
- }
- else if (operation == VectorOperation::max)
- {
- // Copy the vector from the device to a temporary vector on the host
- std::vector<Number> tmp(n_elements);
- cudaError_t error_code = cudaMemcpy(tmp.data(),
- cuda_vec.get_values(),
- n_elements * sizeof(Number),
- cudaMemcpyDeviceToHost);
- AssertCuda(error_code);
-
- for (unsigned int i = 0; i < n_elements; ++i)
- {
- Assert(
- std::imag(tmp[i]) == 0.,
- ExcMessage(
- "VectorOperation::max is not defined if there is an imaginary part!)"));
- Assert(
- std::imag(values[i]) == 0.,
- ExcMessage(
- "VectorOperation::max is not defined if there is an imaginary part!)"));
- if (std::real(tmp[i]) - std::real(values[i]) > 0.0)
- values[i] = tmp[i];
- }
- }
- else
- AssertThrow(false, ExcNotImplemented());
- }
-#endif
-
-
-
template <typename Number>
void
ReadWriteVector<Number>::swap(ReadWriteVector<Number> &v) noexcept
+++ /dev/null
-// ------------------------------------------------------------------------
-//
-// SPDX-License-Identifier: LGPL-2.1-or-later
-// Copyright (C) 2017 - 2024 by the deal.II authors
-//
-// This file is part of the deal.II library.
-//
-// Part of the source code is dual licensed under Apache-2.0 WITH
-// LLVM-exception OR LGPL-2.1-or-later. Detailed license information
-// governing the source code and code contributions can be found in
-// LICENSE.md and CONTRIBUTING.md at the top level directory of deal.II.
-//
-// ------------------------------------------------------------------------
-
-#ifndef dealii_cuda_fe_evaluation_h
-#define dealii_cuda_fe_evaluation_h
-
-#include <deal.II/matrix_free/portable_fe_evaluation.h>
-
-DEAL_II_NAMESPACE_OPEN
-
-/**
- * Namespace for the CUDA wrappers
- */
-// GCC 9 and before do not recognize the [[deprecated]] attribute
-#if defined(__GNUC__) && (__GNUC__ < 10)
-namespace CUDAWrappers
-#else
-namespace DEAL_II_DEPRECATED CUDAWrappers
-#endif
-{
- using namespace Portable;
-} // namespace CUDAWrappers
-
-DEAL_II_NAMESPACE_CLOSE
-
-#endif
+++ /dev/null
-// ------------------------------------------------------------------------
-//
-// SPDX-License-Identifier: LGPL-2.1-or-later
-// Copyright (C) 2018 - 2024 by the deal.II authors
-//
-// This file is part of the deal.II library.
-//
-// Part of the source code is dual licensed under Apache-2.0 WITH
-// LLVM-exception OR LGPL-2.1-or-later. Detailed license information
-// governing the source code and code contributions can be found in
-// LICENSE.md and CONTRIBUTING.md at the top level directory of deal.II.
-//
-// ------------------------------------------------------------------------
-
-#ifndef dealii_cuda_hanging_nodes_internal_h
-#define dealii_cuda_hanging_nodes_internal_h
-
-#include <deal.II/matrix_free/portable_hanging_nodes_internal.h>
-
-DEAL_II_NAMESPACE_OPEN
-// GCC 9 and before do not recognize the [[deprecated]] attribute
-#if defined(__GNUC__) && (__GNUC__ < 10)
-namespace CUDAWrappers
-#else
-namespace DEAL_II_DEPRECATED CUDAWrappers
-#endif
-{
- using namespace Portable;
-} // namespace CUDAWrappers
-
-DEAL_II_NAMESPACE_CLOSE
-#endif
+++ /dev/null
-// ------------------------------------------------------------------------
-//
-// SPDX-License-Identifier: LGPL-2.1-or-later
-// Copyright (C) 2017 - 2024 by the deal.II authors
-//
-// This file is part of the deal.II library.
-//
-// Part of the source code is dual licensed under Apache-2.0 WITH
-// LLVM-exception OR LGPL-2.1-or-later. Detailed license information
-// governing the source code and code contributions can be found in
-// LICENSE.md and CONTRIBUTING.md at the top level directory of deal.II.
-//
-// ------------------------------------------------------------------------
-
-
-#ifndef dealii_cuda_matrix_free_h
-#define dealii_cuda_matrix_free_h
-
-#include <deal.II/matrix_free/portable_matrix_free.h>
-
-DEAL_II_NAMESPACE_OPEN
-
-// GCC 9 and before do not recognize the [[deprecated]] attribute
-#if defined(__GNUC__) && (__GNUC__ < 10)
-namespace CUDAWrappers
-#else
-namespace DEAL_II_DEPRECATED CUDAWrappers
-#endif
-{
- using namespace Portable;
-} // namespace CUDAWrappers
-
-DEAL_II_NAMESPACE_CLOSE
-
-#endif
+++ /dev/null
-// ------------------------------------------------------------------------
-//
-// SPDX-License-Identifier: LGPL-2.1-or-later
-// Copyright (C) 2017 - 2024 by the deal.II authors
-//
-// This file is part of the deal.II library.
-//
-// Part of the source code is dual licensed under Apache-2.0 WITH
-// LLVM-exception OR LGPL-2.1-or-later. Detailed license information
-// governing the source code and code contributions can be found in
-// LICENSE.md and CONTRIBUTING.md at the top level directory of deal.II.
-//
-// ------------------------------------------------------------------------
-
-
-#ifndef dealii_cuda_matrix_free_templates_h
-#define dealii_cuda_matrix_free_templates_h
-
-#include <deal.II/matrix_free/portable_matrix_free.templates.h>
-
-DEAL_II_NAMESPACE_OPEN
-
-// GCC 9 and before do not recognize the [[deprecated]] attribute
-#if defined(__GNUC__) && (__GNUC__ < 10)
-namespace CUDAWrappers
-#else
-namespace DEAL_II_DEPRECATED CUDAWrappers
-#endif
-{
- using namespace Portable;
-} // namespace CUDAWrappers
-
-DEAL_II_NAMESPACE_CLOSE
-
-#endif
+++ /dev/null
-// ------------------------------------------------------------------------
-//
-// SPDX-License-Identifier: LGPL-2.1-or-later
-// Copyright (C) 2017 - 2024 by the deal.II authors
-//
-// This file is part of the deal.II library.
-//
-// Part of the source code is dual licensed under Apache-2.0 WITH
-// LLVM-exception OR LGPL-2.1-or-later. Detailed license information
-// governing the source code and code contributions can be found in
-// LICENSE.md and CONTRIBUTING.md at the top level directory of deal.II.
-//
-// ------------------------------------------------------------------------
-
-
-#ifndef dealii_cuda_tensor_product_kernels_h
-#define dealii_cuda_tensor_product_kernels_h
-
-
-#include <deal.II/matrix_free/portable_tensor_product_kernels.h>
-
-DEAL_II_NAMESPACE_OPEN
-
-
-// GCC 9 and before do not recognize the [[deprecated]] attribute
-#if defined(__GNUC__) && (__GNUC__ < 10)
-namespace CUDAWrappers
-#else
-namespace DEAL_II_DEPRECATED CUDAWrappers
-#endif
-{
- using namespace Portable;
-} // namespace CUDAWrappers
-
-DEAL_II_NAMESPACE_CLOSE
-
-#endif
/**
* This class creates the mask used in the treatment of hanging nodes in
- * CUDAWrappers::MatrixFree.
+ * Portable::MatrixFree.
* The implementation of this class is explained in detail in
* @cite munch2022hn.
*/
*
* @tparam Number Number format, @p double or @p float. Defaults to @p
* double.
- *
- * @ingroup CUDAWrappers
*/
template <int dim,
int fe_degree,
#include <deal.II/base/config.h>
-#include <deal.II/base/cuda_size.h>
-
#include <deal.II/matrix_free/hanging_nodes_internal.h>
#include <Kokkos_Macros.hpp>
#include <deal.II/base/config.h>
-#include <deal.II/base/cuda_size.h>
#include <deal.II/base/memory_space.h>
#include <deal.II/base/mpi_stub.h>
#include <deal.II/base/partitioner.h>
#include <deal.II/grid/filtered_iterator.h>
#include <deal.II/lac/affine_constraints.h>
-#include <deal.II/lac/cuda_vector.h>
#include <deal.II/lac/la_parallel_vector.h>
#include <Kokkos_Core.hpp>
* Triangulation class in deal.II.
*
* @note Only float and double are supported.
- *
- * @ingroup CUDAWrappers
*/
template <int dim, typename Number = double>
class MatrixFree : public Subscriptor
AssertThrow(
overlap_communication_computation == false,
ExcMessage(
- "Overlapping communication and computation requires CUDA-aware MPI."));
+ "Overlapping communication and computation requires device-aware MPI."));
#endif
if (overlap_communication_computation == true)
AssertThrow(
bool use_coloring;
/**
- * Overlap MPI communications with computation. This requires CUDA-aware
+ * Overlap MPI communications with computation. This requires device-aware
* MPI and use_coloring must be false.
*/
bool overlap_communication_computation;
void
set_constrained_values(const Number val, VectorType &dst) const;
-#ifdef DEAL_II_WITH_CUDA
- /**
- * Initialize a serial vector. The size corresponds to the number of degrees
- * of freedom in the DoFHandler object.
- */
- void
- initialize_dof_vector(
- LinearAlgebra::CUDAWrappers::Vector<Number> &vec) const;
-#endif
-
/**
* Initialize a distributed vector. The local elements correspond to the
* locally owned degrees of freedom and the ghost elements correspond to the
LinearAlgebra::distributed::Vector<Number, MemorySpace::Default> &dst)
const;
-#ifdef DEAL_II_WITH_CUDA
- /**
- * This function should never be called. Calling it results in an internal
- * error. This function exists only because cell_loop needs
- * distributed_cell_loop() to exist for LinearAlgebra::CUDAWrappers::Vector.
- */
- template <typename Functor>
- void
- distributed_cell_loop(
- const Functor &func,
- const LinearAlgebra::CUDAWrappers::Vector<Number> &src,
- LinearAlgebra::CUDAWrappers::Vector<Number> &dst) const;
-#endif
-
/**
* Unique ID associated with the object.
*/
bool use_coloring;
/**
- * Overlap MPI communications with computation. This requires CUDA-aware
+ * Overlap MPI communications with computation. This requires device-aware
* MPI and use_coloring must be false.
*/
bool overlap_communication_computation;
#include <deal.II/base/config.h>
-#include <deal.II/base/cuda.h>
-#include <deal.II/base/cuda_size.h>
#include <deal.II/base/graph_coloring.h>
#include <deal.II/base/memory_space.h>
#include <deal.II/fe/fe_values.h>
#include <deal.II/fe/mapping_q1.h>
-#include <deal.II/matrix_free/cuda_hanging_nodes_internal.h>
-#include <deal.II/matrix_free/cuda_matrix_free.h>
+#include <deal.II/matrix_free/portable_hanging_nodes_internal.h>
+#include <deal.II/matrix_free/portable_matrix_free.h>
#include <deal.II/matrix_free/shape_info.h>
#include <Kokkos_Core.hpp>
void
ReinitHelper<dim, Number>::resize(const unsigned int n_colors)
{
- // We need at least three colors when we are using CUDA-aware MPI and
+ // We need at least three colors when we are using device-aware MPI and
// overlapping the communication
data->n_cells.resize(std::max(n_colors, 3U), 0);
data->local_to_global.resize(n_colors);
}
};
-#ifdef DEAL_II_WITH_CUDA
- template <>
- struct VectorLocalSize<LinearAlgebra::CUDAWrappers::Vector<double>>
- {
- static unsigned int
- get(const LinearAlgebra::CUDAWrappers::Vector<double> &vec)
- {
- return vec.size();
- }
- };
-
- template <>
- struct VectorLocalSize<LinearAlgebra::CUDAWrappers::Vector<float>>
- {
- static unsigned int
- get(const LinearAlgebra::CUDAWrappers::Vector<float> &vec)
- {
- return vec.size();
- }
- };
-#endif
-
template <int dim, typename Number, typename Functor>
}
-#ifdef DEAL_II_WITH_CUDA
- template <int dim, typename Number>
- void
- MatrixFree<dim, Number>::initialize_dof_vector(
- LinearAlgebra::CUDAWrappers::Vector<Number> &vec) const
- {
- vec.reinit(n_dofs);
- }
-#endif
-
-
template <int dim, typename Number>
void
apply_kernel);
// We need a synchronization point because we don't want
- // CUDA-aware MPI to start the MPI communication until the
+ // device-aware MPI to start the MPI communication until the
// kernel is done.
Kokkos::fence();
}
}
}
-#ifdef DEAL_II_WITH_CUDA
- template <int dim, typename Number>
- template <typename Functor>
- void
- MatrixFree<dim, Number>::distributed_cell_loop(
- const Functor &,
- const LinearAlgebra::CUDAWrappers::Vector<Number> &,
- LinearAlgebra::CUDAWrappers::Vector<Number> &) const
- {
- DEAL_II_ASSERT_UNREACHABLE();
- }
-#endif
} // namespace Portable
DEAL_II_NAMESPACE_CLOSE
#include <deal.II/base/utilities.h>
-#include <deal.II/matrix_free/cuda_matrix_free.templates.h>
-
DEAL_II_NAMESPACE_OPEN
/**
* In this namespace, the evaluator routines that evaluate the tensor
* products are implemented.
- *
- * @ingroup CUDAWrappers
*/
// TODO: for now only the general variant is implemented
enum EvaluatorVariant
/**
* Generic evaluator framework.
- *
- * @ingroup CUDAWrappers
*/
template <EvaluatorVariant variant,
int dim,
/**
* Internal evaluator for 1d-3d shape function using the tensor product form
* of the basis functions.
- *
- * @ingroup CUDAWrappers
*/
template <int dim, int fe_degree, int n_q_points_1d, typename Number>
struct EvaluatorTensorProduct<evaluate_general,
symmetric_tensor.cc
)
-# Add CUDA wrapper files
-if(DEAL_II_WITH_CUDA)
- set(_separate_src
- ${_separate_src}
- cuda.cc
- )
-endif()
-
# determined by profiling
set(_n_includes_per_unity_file 29)
+++ /dev/null
-// ------------------------------------------------------------------------
-//
-// SPDX-License-Identifier: LGPL-2.1-or-later
-// Copyright (C) 2018 - 2022 by the deal.II authors
-//
-// This file is part of the deal.II library.
-//
-// Part of the source code is dual licensed under Apache-2.0 WITH
-// LLVM-exception OR LGPL-2.1-or-later. Detailed license information
-// governing the source code and code contributions can be found in
-// LICENSE.md and CONTRIBUTING.md at the top level directory of deal.II.
-//
-// ------------------------------------------------------------------------
-
-#include <deal.II/base/cuda.h>
-#include <deal.II/base/exceptions.h>
-#include <deal.II/base/memory_space.h>
-
-#include <deal.II/lac/cuda_vector.h>
-#include <deal.II/lac/la_parallel_vector.h>
-#include <deal.II/lac/vector_memory.h>
-#include <deal.II/lac/vector_memory.templates.h>
-
-DEAL_II_NAMESPACE_OPEN
-
-namespace Utilities
-{
- namespace CUDA
- {
- Handle::Handle()
- {
- cusolverStatus_t cusolver_error_code =
- cusolverDnCreate(&cusolver_dn_handle);
- AssertCusolver(cusolver_error_code);
-
- cusolver_error_code = cusolverSpCreate(&cusolver_sp_handle);
- AssertCusolver(cusolver_error_code);
-
- cusparseStatus_t cusparse_error_code = cusparseCreate(&cusparse_handle);
- AssertCusparse(cusparse_error_code);
- }
-
-
-
- Handle::~Handle()
- {
- cusolverStatus_t cusolver_error_code =
- cusolverDnDestroy(cusolver_dn_handle);
- AssertCusolver(cusolver_error_code);
-
- cusolver_error_code = cusolverSpDestroy(cusolver_sp_handle);
- AssertCusolver(cusolver_error_code);
-
- cusparseStatus_t cusparse_error_code = cusparseDestroy(cusparse_handle);
- AssertCusparse(cusparse_error_code);
- }
- } // namespace CUDA
-} // namespace Utilities
-
-DEAL_II_NAMESPACE_CLOSE
}
}
-
-
-#ifdef DEAL_II_WITH_CUDA
- std::string
- get_cusparse_error_string(const cusparseStatus_t error_code)
- {
- switch (error_code)
- {
- case CUSPARSE_STATUS_NOT_INITIALIZED:
- {
- return "The cuSPARSE library was not initialized";
- }
- case CUSPARSE_STATUS_ALLOC_FAILED:
- {
- return "Resource allocation failed inside the cuSPARSE library";
- }
- case CUSPARSE_STATUS_INVALID_VALUE:
- {
- return "An unsupported value of parameter was passed to the function";
- }
- case CUSPARSE_STATUS_ARCH_MISMATCH:
- {
- return "The function requires a feature absent from the device architecture";
- }
- case CUSPARSE_STATUS_MAPPING_ERROR:
- {
- return "An access to GPU memory space failed";
- }
- case CUSPARSE_STATUS_EXECUTION_FAILED:
- {
- return "The GPU program failed to execute";
- }
- case CUSPARSE_STATUS_INTERNAL_ERROR:
- {
- return "An internal cuSPARSE operation failed";
- }
- case CUSPARSE_STATUS_MATRIX_TYPE_NOT_SUPPORTED:
- {
- return "The matrix type is not supported by this function";
- }
- default:
- {
- return "Unknown error";
- }
- }
- }
-
-
-
- std::string
- get_cusolver_error_string(cusolverStatus_t error_code)
- {
- std::string message;
- switch (error_code)
- {
- case CUSOLVER_STATUS_NOT_INITIALIZED:
- {
- return "The cuSolver library was not initialized";
- }
- case CUSOLVER_STATUS_ALLOC_FAILED:
- {
- return "Resource allocation failed inside the cuSolver library";
- }
- case CUSOLVER_STATUS_INVALID_VALUE:
- {
- return "An unsupported value of a parameter was passed to the function";
- }
- case CUSOLVER_STATUS_ARCH_MISMATCH:
- {
- return "The function requires a feature absent from the device architecture";
- }
- case CUSOLVER_STATUS_EXECUTION_FAILED:
- {
- return "The GPU program failed to execute";
- }
- case CUSOLVER_STATUS_INTERNAL_ERROR:
- {
- return "An internal cuSolver operation failed";
- }
- case CUSOLVER_STATUS_MATRIX_TYPE_NOT_SUPPORTED:
- {
- return "The matrix type is not supported by this function";
- }
- default:
- {
- return "Unknown error";
- }
- }
- }
-#endif
-
} /*namespace internals*/
} /*namespace deal_II_exceptions*/
utilities.cc
)
-# Add CUDA wrapper files
-if(DEAL_II_WITH_CUDA)
- set(_separate_src
- ${_separate_src}
- vector_memory_cuda.cc
- )
-endif()
-
set(_inst
affine_constraints.inst.in
block_sparse_matrix.inst.in
)
endif()
-# Add CUDA wrapper files
-if(DEAL_II_WITH_CUDA)
- set(_separate_src
- ${_separate_src}
- cuda_kernels.cc
- cuda_precondition.cc
- cuda_solver_direct.cc
- cuda_sparse_matrix.cc
- cuda_vector.cc
- read_write_vector_cuda.cc
- )
-endif()
-
# determined by profiling
set(_n_includes_per_unity_file 20)
+++ /dev/null
-// ------------------------------------------------------------------------
-//
-// SPDX-License-Identifier: LGPL-2.1-or-later
-// Copyright (C) 2018 - 2023 by the deal.II authors
-//
-// This file is part of the deal.II library.
-//
-// Part of the source code is dual licensed under Apache-2.0 WITH
-// LLVM-exception OR LGPL-2.1-or-later. Detailed license information
-// governing the source code and code contributions can be found in
-// LICENSE.md and CONTRIBUTING.md at the top level directory of deal.II.
-//
-// ------------------------------------------------------------------------
-
-#include <deal.II/lac/cuda_kernels.templates.h>
-
-DEAL_II_NAMESPACE_OPEN
-
-namespace LinearAlgebra
-{
- namespace CUDAWrappers
- {
- namespace kernel
- {
- /////////////////////////////////////////////////////////////////////////
- // Explicit instantiation //
- /////////////////////////////////////////////////////////////////////////
-
- template __global__ void
- vec_scale<float>(float *, const float a, const size_type);
- template __global__ void
- vector_bin_op<float, Binop_Addition>(float *v1,
- const float *v2,
- const size_type N);
- template __global__ void
- vector_bin_op<float, Binop_Subtraction>(float *v1,
- const float *v2,
- const size_type N);
- template __global__ void
- masked_vector_bin_op<float, Binop_Addition>(const unsigned int *mask,
- float *v1,
- const float *v2,
- const size_type N);
- template __global__ void
- masked_vector_bin_op<float, Binop_Subtraction>(const unsigned int *mask,
- float *v1,
- const float *v2,
- const size_type N);
- template struct ElemSum<float>;
- template struct L1Norm<float>;
- template struct LInfty<float>;
- template __global__ void
- reduction<float, ElemSum<float>>(float *result,
- const float *v,
- const size_type N);
- template __global__ void
- reduction<float, L1Norm<float>>(float *result,
- const float *v,
- const size_type N);
- template __global__ void
- reduction<float, LInfty<float>>(float *result,
- const float *v,
- const size_type N);
- template struct DotProduct<float>;
- template __global__ void
- double_vector_reduction<float, DotProduct<float>>(float *result,
- const float *v1,
- const float *v2,
- const size_type N);
- template __global__ void
- vec_add<float>(float *val, const float, const size_type N);
- template __global__ void
- add_aV<float>(float *val,
- const float a,
- const float *V_val,
- const size_type N);
- template __global__ void
- add_aVbW<float>(float *val,
- const float a,
- const float *V_val,
- const float b,
- const float *W_val,
- const size_type N);
- template __global__ void
- sadd<float>(const float s,
- float *val,
- const float a,
- const float *V_val,
- const size_type N);
- template __global__ void
- sadd<float>(const float s,
- float *val,
- const float a,
- const float *V_val,
- const float b,
- const float *W_val,
- const size_type N);
- template __global__ void
- scale<float>(float *val, const float *V_val, const size_type N);
- template __global__ void
- equ<float>(float *val,
- const float a,
- const float *V_val,
- const size_type N);
- template __global__ void
- equ<float>(float *val,
- const float a,
- const float *V_val,
- const float b,
- const float *W_val,
- const size_type N);
- template __global__ void
- add_and_dot<float>(float *res,
- float *v1,
- const float *v2,
- const float *v3,
- const float a,
- const size_type N);
- template __global__ void
- set<float>(float *val, const float s, const size_type N);
- template __global__ void
- set_permutated<float, size_type>(const size_type *indices,
- float *val,
- const float *v,
- const size_type N);
- template __global__ void
- gather<float, size_type>(float *val,
- const size_type *indices,
- const float *v,
- const size_type N);
- template __global__ void
- add_permutated<float>(const size_type *indices,
- float *val,
- const float *v,
- const size_type N);
-
-
-
- template __global__ void
- vec_scale<double>(double *, const double a, const size_type);
- template __global__ void
- vector_bin_op<double, Binop_Addition>(double *v1,
- const double *v2,
- const size_type N);
- template __global__ void
- vector_bin_op<double, Binop_Subtraction>(double *v1,
- const double *v2,
- const size_type N);
- template __global__ void
- masked_vector_bin_op<double, Binop_Addition>(const unsigned int *mask,
- double *v1,
- const double *v2,
- const size_type N);
- template __global__ void
- masked_vector_bin_op<double, Binop_Subtraction>(const unsigned int *mask,
- double *v1,
- const double *v2,
- const size_type N);
- template struct ElemSum<double>;
- template struct L1Norm<double>;
- template struct LInfty<double>;
- template __global__ void
- reduction<double, ElemSum<double>>(double *result,
- const double *v,
- const size_type N);
- template __global__ void
- reduction<double, L1Norm<double>>(double *result,
- const double *v,
- const size_type N);
- template __global__ void
- reduction<double, LInfty<double>>(double *result,
- const double *v,
- const size_type N);
- template struct DotProduct<double>;
- template __global__ void
- double_vector_reduction<double, DotProduct<double>>(double *result,
- const double *v1,
- const double *v2,
- const size_type N);
- template __global__ void
- vec_add<double>(double *val, const double, const size_type N);
- template __global__ void
- add_aV<double>(double *val,
- const double a,
- const double *V_val,
- const size_type N);
- template __global__ void
- add_aVbW<double>(double *val,
- const double a,
- const double *V_val,
- const double b,
- const double *W_val,
- const size_type N);
- template __global__ void
- sadd<double>(const double s,
- double *val,
- const double a,
- const double *V_val,
- const size_type N);
- template __global__ void
- sadd<double>(const double s,
- double *val,
- const double a,
- const double *V_val,
- const double b,
- const double *W_val,
- const size_type N);
- template __global__ void
- scale<double>(double *val, const double *V_val, const size_type N);
- template __global__ void
- equ<double>(double *val,
- const double a,
- const double *V_val,
- const size_type N);
- template __global__ void
- equ<double>(double *val,
- const double a,
- const double *V_val,
- const double b,
- const double *W_val,
- const size_type N);
- template __global__ void
- add_and_dot<double>(double *res,
- double *v1,
- const double *v2,
- const double *v3,
- const double a,
- const size_type N);
- template __global__ void
- set<double>(double *val, const double s, const size_type N);
- template __global__ void
- set_permutated<double, size_type>(const size_type *indices,
- double *val,
- const double *v,
- const size_type N);
- template __global__ void
- gather<double, size_type>(double *val,
- const size_type *indices,
- const double *v,
- const size_type N);
- template __global__ void
- add_permutated<double>(const size_type *indices,
- double *val,
- const double *v,
- const size_type N);
- } // namespace kernel
- } // namespace CUDAWrappers
-} // namespace LinearAlgebra
-
-DEAL_II_NAMESPACE_CLOSE
+++ /dev/null
-// ------------------------------------------------------------------------
-//
-// SPDX-License-Identifier: LGPL-2.1-or-later
-// Copyright (C) 2018 - 2024 by the deal.II authors
-//
-// This file is part of the deal.II library.
-//
-// Part of the source code is dual licensed under Apache-2.0 WITH
-// LLVM-exception OR LGPL-2.1-or-later. Detailed license information
-// governing the source code and code contributions can be found in
-// LICENSE.md and CONTRIBUTING.md at the top level directory of deal.II.
-//
-// ------------------------------------------------------------------------
-
-#include <deal.II/lac/cuda_precondition.h>
-#include <deal.II/lac/cuda_sparse_matrix.h>
-
-DEAL_II_NAMESPACE_OPEN
-
-namespace
-{
- /**
- * Template wrapper for cusparse<t>csrilu02.
- * (https://docs.nvidia.com/cuda/cusparse/index.html#cusparse-lt-t-gt-csrilu02).
- * function performs the solve phase of the incomplete-LU factorization with
- * 0 fill-in and no pivoting.
- */
- template <typename Number>
- cusparseStatus_t
- cusparseXcsrilu02(cusparseHandle_t /*handle*/,
- int /*m*/,
- int /*nnz*/,
- const cusparseMatDescr_t /*descrA*/,
- Number * /*csrValA_valM*/,
- const int * /*csrRowPtrA*/,
- const int * /*csrColIndA*/,
- csrilu02Info_t /*info*/,
- cusparseSolvePolicy_t /*policy*/,
- void * /*pBuffer*/)
- {
- AssertThrow(false, ExcNotImplemented());
- return CUSPARSE_STATUS_INVALID_VALUE;
- }
-
- template <>
- cusparseStatus_t
- cusparseXcsrilu02<float>(cusparseHandle_t handle,
- int m,
- int nnz,
- const cusparseMatDescr_t descrA,
- float *csrValA_valM,
- const int *csrRowPtrA,
- const int *csrColIndA,
- csrilu02Info_t info,
- cusparseSolvePolicy_t policy,
- void *pBuffer)
- {
- return cusparseScsrilu02(handle,
- m,
- nnz,
- descrA,
- csrValA_valM,
- csrRowPtrA,
- csrColIndA,
- info,
- policy,
- pBuffer);
- }
-
- template <>
- cusparseStatus_t
- cusparseXcsrilu02<double>(cusparseHandle_t handle,
- int m,
- int nnz,
- const cusparseMatDescr_t descrA,
- double *csrValA_valM,
- const int *csrRowPtrA,
- const int *csrColIndA,
- csrilu02Info_t info,
- cusparseSolvePolicy_t policy,
- void *pBuffer)
- {
- return cusparseDcsrilu02(handle,
- m,
- nnz,
- descrA,
- csrValA_valM,
- csrRowPtrA,
- csrColIndA,
- info,
- policy,
- pBuffer);
- }
-
- /*
- template <>
- cusparseStatus_t
- cusparseXcsrilu02<cuComplex>(cusparseHandle_t handle,
- int m,
- int nnz,
- const cusparseMatDescr_t descrA,
- cuComplex * csrValA_valM,
- const int * csrRowPtrA,
- const int * csrColIndA,
- csrilu02Info_t info,
- cusparseSolvePolicy_t policy,
- void * pBuffer)
- {
- return cusparseCcsrilu02(handle,
- m,
- nnz,
- descrA,
- csrValA_valM,
- csrRowPtrA,
- csrColIndA,
- info,
- policy,
- pBuffer);
- }
-
- template <>
- cusparseStatus_t
- cusparseXcsrilu02<cuDoubleComplex>(cusparseHandle_t handle,
- int m,
- int nnz,
- const cusparseMatDescr_t descrA,
- cuDoubleComplex * csrValA_valM,
- const int * csrRowPtrA,
- const int * csrColIndA,
- csrilu02Info_t info,
- cusparseSolvePolicy_t policy,
- void * pBuffer)
- {
- return cusparseZcsrilu02(handle,
- m,
- nnz,
- descrA,
- csrValA_valM,
- csrRowPtrA,
- csrColIndA,
- info,
- policy,
- pBuffer);
- }
- */
-
-
-
- /**
- * Template wrapper for cusparse<t>csrilu02_analysis.
- * (https://docs.nvidia.com/cuda/cusparse/index.html#cusparse-lt-t-gt-csrilu02_analysis).
- * This function performs the analysis phase of the incomplete-LU
- * factorization with 0 fill-in and no pivoting.
- */
- template <typename Number>
- cusparseStatus_t
- cusparseXcsrilu02_analysis(cusparseHandle_t /*handle*/,
- int /*m*/,
- int /*nnz*/,
- const cusparseMatDescr_t /*descrA*/,
- const Number * /*csrValA*/,
- const int * /*csrRowPtrA*/,
- const int * /*csrColIndA*/,
- csrilu02Info_t /*info*/,
- cusparseSolvePolicy_t /*policy*/,
- void * /*pBuffer*/)
- {
- AssertThrow(false, ExcNotImplemented());
- return CUSPARSE_STATUS_INVALID_VALUE;
- }
-
- template <>
- cusparseStatus_t
- cusparseXcsrilu02_analysis<float>(cusparseHandle_t handle,
- int m,
- int nnz,
- const cusparseMatDescr_t descrA,
- const float *csrValA,
- const int *csrRowPtrA,
- const int *csrColIndA,
- csrilu02Info_t info,
- cusparseSolvePolicy_t policy,
- void *pBuffer)
- {
- return cusparseScsrilu02_analysis(handle,
- m,
- nnz,
- descrA,
- csrValA,
- csrRowPtrA,
- csrColIndA,
- info,
- policy,
- pBuffer);
- }
-
- template <>
- cusparseStatus_t
- cusparseXcsrilu02_analysis<double>(cusparseHandle_t handle,
- int m,
- int nnz,
- const cusparseMatDescr_t descrA,
- const double *csrValA,
- const int *csrRowPtrA,
- const int *csrColIndA,
- csrilu02Info_t info,
- cusparseSolvePolicy_t policy,
- void *pBuffer)
- {
- return cusparseDcsrilu02_analysis(handle,
- m,
- nnz,
- descrA,
- csrValA,
- csrRowPtrA,
- csrColIndA,
- info,
- policy,
- pBuffer);
- }
-
- /*
- template <>
- cusparseStatus_t
- cusparseXcsrilu02_analysis<cuComplex>(cusparseHandle_t handle,
- int m,
- int nnz,
- const cusparseMatDescr_t descrA,
- const cuComplex * csrValA,
- const int * csrRowPtrA,
- const int * csrColIndA,
- csrilu02Info_t info,
- cusparseSolvePolicy_t policy,
- void * pBuffer)
- {
- return cusparseCcsrilu02_analysis(handle,
- m,
- nnz,
- descrA,
- csrValA,
- csrRowPtrA,
- csrColIndA,
- info,
- policy,
- pBuffer);
- }
-
- template <>
- cusparseStatus_t
- cusparseXcsrilu02_analysis<cuDoubleComplex>(cusparseHandle_t handle,
- int m,
- int nnz,
- const cusparseMatDescr_t descrA,
- const cuDoubleComplex * csrValA,
- const int * csrRowPtrA,
- const int * csrColIndA,
- csrilu02Info_t info,
- cusparseSolvePolicy_t policy,
- void * pBuffer)
- {
- return cusparseZcsrilu02_analysis(handle,
- m,
- nnz,
- descrA,
- csrValA,
- csrRowPtrA,
- csrColIndA,
- info,
- policy,
- pBuffer);
- }
-*/
-
-
-
- /**
- * Template wrapper for cusparse<t>csrilu02_bufferSize.
- * (https://docs.nvidia.com/cuda/cusparse/index.html#cusparse-lt-t-gt-csrilu02_bufferSize).
- * This function returns size of the buffer used in computing the
- * incomplete-LU factorization with 0 fill-in and no pivoting.
- */
- template <typename Number>
- cusparseStatus_t
- cusparseXcsrilu02_bufferSize(cusparseHandle_t /*handle*/,
- int /*m*/,
- int /*nnz*/,
- const cusparseMatDescr_t /*descrA*/,
- Number * /*csrValA*/,
- const int * /*csrRowPtrA*/,
- const int * /*csrColIndA*/,
- csrilu02Info_t /*info*/,
- int * /*pBufferSizeInBytes*/)
- {
- AssertThrow(false, ExcNotImplemented());
- return CUSPARSE_STATUS_INVALID_VALUE;
- }
-
- template <>
- cusparseStatus_t
- cusparseXcsrilu02_bufferSize<float>(cusparseHandle_t handle,
- int m,
- int nnz,
- const cusparseMatDescr_t descrA,
- float *csrValA,
- const int *csrRowPtrA,
- const int *csrColIndA,
- csrilu02Info_t info,
- int *pBufferSizeInBytes)
- {
- return cusparseScsrilu02_bufferSize(handle,
- m,
- nnz,
- descrA,
- csrValA,
- csrRowPtrA,
- csrColIndA,
- info,
- pBufferSizeInBytes);
- }
-
- template <>
- cusparseStatus_t
- cusparseXcsrilu02_bufferSize<double>(cusparseHandle_t handle,
- int m,
- int nnz,
- const cusparseMatDescr_t descrA,
- double *csrValA,
- const int *csrRowPtrA,
- const int *csrColIndA,
- csrilu02Info_t info,
- int *pBufferSizeInBytes)
- {
- return cusparseDcsrilu02_bufferSize(handle,
- m,
- nnz,
- descrA,
- csrValA,
- csrRowPtrA,
- csrColIndA,
- info,
- pBufferSizeInBytes);
- }
-
- /*
- template <>
- cusparseStatus_t
- cusparseXcsrilu02_bufferSize<cuComplex>(cusparseHandle_t handle,
- int m,
- int nnz,
- const cusparseMatDescr_t descrA,
- cuComplex * csrValA,
- const int * csrRowPtrA,
- const int * csrColIndA,
- csrilu02Info_t info,
- int *pBufferSizeInBytes)
- {
- return cusparseCcsrilu02_bufferSize(handle,
- m,
- nnz,
- descrA,
- csrValA,
- csrRowPtrA,
- csrColIndA,
- info,
- pBufferSizeInBytes);
- }
-
- template <>
- cusparseStatus_t
- cusparseXcsrilu02_bufferSize<cuDoubleComplex>(cusparseHandle_t handle, int
- m, int nnz, const cusparseMatDescr_t descrA,
- cuDoubleComplex *csrValA,
- const int * csrRowPtrA,
- const int * csrColIndA,
- csrilu02Info_t info,
- int *pBufferSizeInBytes)
- {
- return cusparseZcsrilu02_bufferSize(handle,
- m,
- nnz,
- descrA,
- csrValA,
- csrRowPtrA,
- csrColIndA,
- info,
- pBufferSizeInBytes);
- }
-*/
-
-
-
- /**
- * Template wrapper for cusparse<t>csric02
- * (https://docs.nvidia.com/cuda/cusparse/index.html#cusparse-lt-t-gt-csric02).
- * This function performs the solve phase of the computing the
- * incomplete-Cholesky factorization with 0 fill-in and no pivoting.
- */
- template <typename Number>
- cusparseStatus_t
- cusparseXcsric02(cusparseHandle_t /*handle*/,
- int /*m*/,
- int /*nnz*/,
- const cusparseMatDescr_t /*descrA*/,
- Number * /*csrValA_valM*/,
- const int * /*csrRowPtrA*/,
- const int * /*csrColIndA*/,
- csric02Info_t /*info*/,
- cusparseSolvePolicy_t /*policy*/,
- void * /*pBuffer*/)
- {
- AssertThrow(false, ExcNotImplemented());
- return CUSPARSE_STATUS_INVALID_VALUE;
- }
-
- template <>
- cusparseStatus_t
- cusparseXcsric02<float>(cusparseHandle_t handle,
- int m,
- int nnz,
- const cusparseMatDescr_t descrA,
- float *csrValA_valM,
- const int *csrRowPtrA,
- const int *csrColIndA,
- csric02Info_t info,
- cusparseSolvePolicy_t policy,
- void *pBuffer)
- {
- return cusparseScsric02(handle,
- m,
- nnz,
- descrA,
- csrValA_valM,
- csrRowPtrA,
- csrColIndA,
- info,
- policy,
- pBuffer);
- }
-
- template <>
- cusparseStatus_t
- cusparseXcsric02<double>(cusparseHandle_t handle,
- int m,
- int nnz,
- const cusparseMatDescr_t descrA,
- double *csrValA_valM,
- const int *csrRowPtrA,
- const int *csrColIndA,
- csric02Info_t info,
- cusparseSolvePolicy_t policy,
- void *pBuffer)
- {
- return cusparseDcsric02(handle,
- m,
- nnz,
- descrA,
- csrValA_valM,
- csrRowPtrA,
- csrColIndA,
- info,
- policy,
- pBuffer);
- }
-
- /*
- template <>
- cusparseStatus_t
- cusparseXcsric02<cuComplex>(cusparseHandle_t handle,
- int m,
- int nnz,
- const cusparseMatDescr_t descrA,
- cuComplex * csrValA_valM,
- const int * csrRowPtrA,
- const int * csrColIndA,
- csric02Info_t info,
- cusparseSolvePolicy_t policy,
- void * pBuffer)
- {
- return cusparseCcsric02(handle,
- m,
- nnz,
- descrA,
- csrValA_valM,
- csrRowPtrA,
- csrColIndA,
- info,
- policy,
- pBuffer);
- }
-
- template <>
- cusparseStatus_t
- cusparseXcsric02<cuDoubleComplex>(cusparseHandle_t handle,
- int m,
- int nnz,
- const cusparseMatDescr_t descrA,
- cuDoubleComplex * csrValA_valM,
- const int * csrRowPtrA,
- const int * csrColIndA,
- csric02Info_t info,
- cusparseSolvePolicy_t policy,
- void * pBuffer)
- {
- return cusparseZcsric02(handle,
- m,
- nnz,
- descrA,
- csrValA_valM,
- csrRowPtrA,
- csrColIndA,
- info,
- policy,
- pBuffer);
- }
- */
-
-
-
- /**
- * Template wrapper for cusparse<t>csrsv2_solve
- * (https://docs.nvidia.com/cuda/cusparse/index.html#cusparse-lt-t-gt-csrsv2_solve).
- * This function performs the solve phase of csrsv2, a new sparse triangular
- * linear system op(A)*y = alpha*x.
- */
- template <typename Number>
- cusparseStatus_t
- cusparseXcsrsv2_solve(cusparseHandle_t /*handle*/,
- cusparseOperation_t /*transA*/,
- int /*m*/,
- int /*nnz*/,
- const Number * /*alpha*/,
- const cusparseMatDescr_t /*descra*/,
- const Number * /*csrValA*/,
- const int * /*csrRowPtrA*/,
- const int * /*csrColIndA*/,
- csrsv2Info_t /*info*/,
- const Number * /*x*/,
- Number * /*y*/,
- cusparseSolvePolicy_t /*policy*/,
- void * /*pBuffer*/)
- {
- AssertThrow(false, ExcNotImplemented());
- return CUSPARSE_STATUS_INVALID_VALUE;
- }
-
- template <>
- cusparseStatus_t
- cusparseXcsrsv2_solve<float>(cusparseHandle_t handle,
- cusparseOperation_t transA,
- int m,
- int nnz,
- const float *alpha,
- const cusparseMatDescr_t descra,
- const float *csrValA,
- const int *csrRowPtrA,
- const int *csrColIndA,
- csrsv2Info_t info,
- const float *x,
- float *y,
- cusparseSolvePolicy_t policy,
- void *pBuffer)
- {
- return cusparseScsrsv2_solve(handle,
- transA,
- m,
- nnz,
- alpha,
- descra,
- csrValA,
- csrRowPtrA,
- csrColIndA,
- info,
- x,
- y,
- policy,
- pBuffer);
- }
-
- template <>
- cusparseStatus_t
- cusparseXcsrsv2_solve<double>(cusparseHandle_t handle,
- cusparseOperation_t transA,
- int m,
- int nnz,
- const double *alpha,
- const cusparseMatDescr_t descra,
- const double *csrValA,
- const int *csrRowPtrA,
- const int *csrColIndA,
- csrsv2Info_t info,
- const double *x,
- double *y,
- cusparseSolvePolicy_t policy,
- void *pBuffer)
- {
- return cusparseDcsrsv2_solve(handle,
- transA,
- m,
- nnz,
- alpha,
- descra,
- csrValA,
- csrRowPtrA,
- csrColIndA,
- info,
- x,
- y,
- policy,
- pBuffer);
- }
-
- /*
- template <>
- cusparseStatus_t
- cusparseXcsrsv2_solve<cuComplex>(cusparseHandle_t handle,
- cusparseOperation_t transA,
- int m,
- int nnz,
- const cuComplex * alpha,
- const cusparseMatDescr_t descra,
- const cuComplex * csrValA,
- const int * csrRowPtrA,
- const int * csrColIndA,
- csrsv2Info_t info,
- const cuComplex * x,
- cuComplex * y,
- cusparseSolvePolicy_t policy,
- void * pBuffer)
- {
- return cusparseCcsrsv2_solve(handle,
- transA,
- m,
- nnz,
- alpha,
- descra,
- csrValA,
- csrRowPtrA,
- csrColIndA,
- info,
- x,
- y,
- policy,
- pBuffer);
- }
-
- template <>
- cusparseStatus_t
- cusparseXcsrsv2_solve<cuDoubleComplex>(cusparseHandle_t handle,
- cusparseOperation_t transA,
- int m,
- int nnz,
- const cuDoubleComplex * alpha,
- const cusparseMatDescr_t descra,
- const cuDoubleComplex * csrValA,
- const int * csrRowPtrA,
- const int * csrColIndA,
- csrsv2Info_t info,
- const cuDoubleComplex * x,
- cuDoubleComplex * y,
- cusparseSolvePolicy_t policy,
- void * pBuffer)
- {
- return cusparseZcsrsv2_solve(handle,
- transA,
- m,
- nnz,
- alpha,
- descra,
- csrValA,
- csrRowPtrA,
- csrColIndA,
- info,
- x,
- y,
- policy,
- pBuffer);
- }
-*/
-
-
-
- /**
- * Template wrapper for cusparse<t>csrsv2_analysis
- * (https://docs.nvidia.com/cuda/cusparse/index.html#cusparse-lt-t-gt-csrsv2_analysis).
- * This function performs the analysis phase of csrsv2, a new sparse
- * triangular linear system op(A)*y = alpha*x.
- */
- template <typename Number>
- cusparseStatus_t
- cusparseXcsrsv2_analysis(cusparseHandle_t /*handle*/,
- cusparseOperation_t /*transA*/,
- int /*m*/,
- int /*nnz*/,
- const cusparseMatDescr_t /*descrA*/,
- const Number * /*csrValA*/,
- const int * /*csrRowPtrA*/,
- const int * /*csrColIndA*/,
- csrsv2Info_t /*info*/,
- cusparseSolvePolicy_t /*policy*/,
- void * /*pBuffer*/)
- {
- AssertThrow(false, ExcNotImplemented());
- return CUSPARSE_STATUS_INVALID_VALUE;
- }
-
- template <>
- cusparseStatus_t
- cusparseXcsrsv2_analysis<float>(cusparseHandle_t handle,
- cusparseOperation_t transA,
- int m,
- int nnz,
- const cusparseMatDescr_t descrA,
- const float *csrValA,
- const int *csrRowPtrA,
- const int *csrColIndA,
- csrsv2Info_t info,
- cusparseSolvePolicy_t policy,
- void *pBuffer)
- {
- return cusparseScsrsv2_analysis(handle,
- transA,
- m,
- nnz,
- descrA,
- csrValA,
- csrRowPtrA,
- csrColIndA,
- info,
- policy,
- pBuffer);
- }
-
- template <>
- cusparseStatus_t
- cusparseXcsrsv2_analysis<double>(cusparseHandle_t handle,
- cusparseOperation_t transA,
- int m,
- int nnz,
- const cusparseMatDescr_t descrA,
- const double *csrValA,
- const int *csrRowPtrA,
- const int *csrColIndA,
- csrsv2Info_t info,
- cusparseSolvePolicy_t policy,
- void *pBuffer)
- {
- return cusparseDcsrsv2_analysis(handle,
- transA,
- m,
- nnz,
- descrA,
- csrValA,
- csrRowPtrA,
- csrColIndA,
- info,
- policy,
- pBuffer);
- }
-
- /*
- template <>
- cusparseStatus_t
- cusparseXcsrsv2_analysis<cuComplex>(cusparseHandle_t handle,
- cusparseOperation_t transA,
- int m,
- int nnz,
- const cusparseMatDescr_t descrA,
- const cuComplex * csrValA,
- const int * csrRowPtrA,
- const int * csrColIndA,
- csrsv2Info_t info,
- cusparseSolvePolicy_t policy,
- void * pBuffer)
- {
- return cusparseCcsrsv2_analysis(handle,
- transA,
- m,
- nnz,
- descrA,
- csrValA,
- csrRowPtrA,
- csrColIndA,
- info,
- policy,
- pBuffer);
- }
-
- template <>
- cusparseStatus_t
- cusparseXcsrsv2_analysis<cuDoubleComplex>(cusparseHandle_t handle,
- cusparseOperation_t transA,
- int m,
- int nnz,
- const cusparseMatDescr_t descrA,
- const cuDoubleComplex * csrValA,
- const int * csrRowPtrA,
- const int * csrColIndA,
- csrsv2Info_t info,
- cusparseSolvePolicy_t policy,
- void * pBuffer)
- {
- return cusparseZcsrsv2_analysis(handle,
- transA,
- m,
- nnz,
- descrA,
- csrValA,
- csrRowPtrA,
- csrColIndA,
- info,
- policy,
- pBuffer);
- }
-*/
-
-
- /**
- * Template wrapper for cusparse<t>csric02_analysis
- * (https://docs.nvidia.com/cuda/cusparse/index.html#cusparse-lt-t-gt-csric02_analysis).
- * This function performs the analysis phase of the incomplete-Cholesky
- * factorization with 0 fill-in and no pivoting.
- */
- template <typename Number>
- cusparseStatus_t
- cusparseXcsric02_analysis(cusparseHandle_t /*handle*/,
- int /*m*/,
- int /*nnz*/,
- const cusparseMatDescr_t /*descrA*/,
- const Number * /*csrValA*/,
- const int * /*csrRowPtrA*/,
- const int * /*csrColIndA*/,
- csric02Info_t /*info*/,
- cusparseSolvePolicy_t /*policy*/,
- void * /*pBuffer*/)
- {
- AssertThrow(false, ExcNotImplemented());
- return CUSPARSE_STATUS_INVALID_VALUE;
- }
-
- template <>
- cusparseStatus_t
- cusparseXcsric02_analysis<float>(cusparseHandle_t handle,
- int m,
- int nnz,
- const cusparseMatDescr_t descrA,
- const float *csrValA,
- const int *csrRowPtrA,
- const int *csrColIndA,
- csric02Info_t info,
- cusparseSolvePolicy_t policy,
- void *pBuffer)
- {
- return cusparseScsric02_analysis(handle,
- m,
- nnz,
- descrA,
- csrValA,
- csrRowPtrA,
- csrColIndA,
- info,
- policy,
- pBuffer);
- }
-
- template <>
- cusparseStatus_t
- cusparseXcsric02_analysis<double>(cusparseHandle_t handle,
- int m,
- int nnz,
- const cusparseMatDescr_t descrA,
- const double *csrValA,
- const int *csrRowPtrA,
- const int *csrColIndA,
- csric02Info_t info,
- cusparseSolvePolicy_t policy,
- void *pBuffer)
- {
- return cusparseDcsric02_analysis(handle,
- m,
- nnz,
- descrA,
- csrValA,
- csrRowPtrA,
- csrColIndA,
- info,
- policy,
- pBuffer);
- }
-
- /*
- template <>
- cusparseStatus_t
- cusparseXcsric02_analysis<cuComplex>(cusparseHandle_t handle,
- int m,
- int nnz,
- const cusparseMatDescr_t descrA,
- const cuComplex * csrValA,
- const int * csrRowPtrA,
- const int * csrColIndA,
- csric02Info_t info,
- cusparseSolvePolicy_t policy,
- void * pBuffer)
- {
- return cusparseCcsric02_analysis(handle,
- m,
- nnz,
- descrA,
- csrValA,
- csrRowPtrA,
- csrColIndA,
- info,
- policy,
- pBuffer);
- }
-
- template <>
- cusparseStatus_t
- cusparseXcsric02_analysis<cuDoubleComplex>(cusparseHandle_t handle,
- int m,
- int nnz,
- const cusparseMatDescr_t descrA,
- const cuDoubleComplex * csrValA,
- const int * csrRowPtrA,
- const int * csrColIndA,
- csric02Info_t info,
- cusparseSolvePolicy_t policy,
- void * pBuffer)
- {
- return cusparseZcsric02_analysis(handle,
- m,
- nnz,
- descrA,
- csrValA,
- csrRowPtrA,
- csrColIndA,
- info,
- policy,
- pBuffer);
- }
-*/
-
-
-
- /**
- * Template wrapper for cusparse<t>csrsv2_bufferSize
- * (https://docs.nvidia.com/cuda/cusparse/index.html#cusparse-lt-t-gt-csrsv2_bufferSize).
- * This function returns the size of the buffer used in csrsv2, a new sparse
- * triangular linear system op(A)*y = alpha*x.
- */
- template <typename Number>
- cusparseStatus_t
- cusparseXcsrsv2_bufferSize(cusparseHandle_t /*handle*/,
- cusparseOperation_t /*transA*/,
- int /*m*/,
- int /*nnz*/,
- const cusparseMatDescr_t /*descrA*/,
- Number * /*csrValA*/,
- const int * /*csrRowPtrA*/,
- const int * /*csrColIndA*/,
- csrsv2Info_t /*info*/,
- int * /*pBufferSizeInBytes*/)
- {
- AssertThrow(false, ExcNotImplemented());
- return CUSPARSE_STATUS_INVALID_VALUE;
- }
-
- template <>
- cusparseStatus_t
- cusparseXcsrsv2_bufferSize<float>(cusparseHandle_t handle,
- cusparseOperation_t transA,
- int m,
- int nnz,
- const cusparseMatDescr_t descrA,
- float *csrValA,
- const int *csrRowPtrA,
- const int *csrColIndA,
- csrsv2Info_t info,
- int *pBufferSizeInBytes)
- {
- return cusparseScsrsv2_bufferSize(handle,
- transA,
- m,
- nnz,
- descrA,
- csrValA,
- csrRowPtrA,
- csrColIndA,
- info,
- pBufferSizeInBytes);
- }
-
- template <>
- cusparseStatus_t
- cusparseXcsrsv2_bufferSize<double>(cusparseHandle_t handle,
- cusparseOperation_t transA,
- int m,
- int nnz,
- const cusparseMatDescr_t descrA,
- double *csrValA,
- const int *csrRowPtrA,
- const int *csrColIndA,
- csrsv2Info_t info,
- int *pBufferSizeInBytes)
- {
- return cusparseDcsrsv2_bufferSize(handle,
- transA,
- m,
- nnz,
- descrA,
- csrValA,
- csrRowPtrA,
- csrColIndA,
- info,
- pBufferSizeInBytes);
- }
-
- /*
- template <>
- cusparseStatus_t
- cusparseXcsrsv2_bufferSize<cuComplex>(cusparseHandle_t handle,
- cusparseOperation_t transA,
- int m,
- int nnz,
- const cusparseMatDescr_t descrA,
- cuComplex * csrValA,
- const int * csrRowPtrA,
- const int * csrColIndA,
- csrsv2Info_t info,
- int *pBufferSizeInBytes)
- {
- return cusparseCcsrsv2_bufferSize(handle,
- transA,
- m,
- nnz,
- descrA,
- csrValA,
- csrRowPtrA,
- csrColIndA,
- info,
- pBufferSizeInBytes);
- }
-
- template <>
- cusparseStatus_t
- cusparseXcsrsv2_bufferSize<cuDoubleComplex>(cusparseHandle_t handle,
- cusparseOperation_t transA,
- int m,
- int nnz,
- const cusparseMatDescr_t descrA,
- cuDoubleComplex * csrValA,
- const int * csrRowPtrA,
- const int * csrColIndA,
- csrsv2Info_t info,
- int * pBufferSizeInBytes)
- {
- return cusparseZcsrsv2_bufferSize(handle,
- transA,
- m,
- nnz,
- descrA,
- csrValA,
- csrRowPtrA,
- csrColIndA,
- info,
- pBufferSizeInBytes);
- }
-*/
-
-
-
- /**
- * Template wrapper for cusparse<t>csric02_bufferSize
- * (https://docs.nvidia.com/cuda/cusparse/index.html#cusparse-lt-t-gt-csric02_bufferSize).
- * This function returns size of buffer used in computing the
- * incomplete-Cholesky factorization with 0 fill-in and no pivoting.
- */
- template <typename Number>
- cusparseStatus_t
- cusparseXcsric02_bufferSize(cusparseHandle_t /*handle*/,
- int /*m*/,
- int /*nnz*/,
- const cusparseMatDescr_t /*descrA*/,
- Number * /*csrValA*/,
- const int * /*csrRowPtrA*/,
- const int * /*csrColIndA*/,
- csric02Info_t /*info*/,
- int * /*pBufferSizeInBytes*/)
- {
- AssertThrow(false, ExcNotImplemented());
- return CUSPARSE_STATUS_INVALID_VALUE;
- }
-
- template <>
- cusparseStatus_t
- cusparseXcsric02_bufferSize<float>(cusparseHandle_t handle,
- int m,
- int nnz,
- const cusparseMatDescr_t descrA,
- float *csrValA,
- const int *csrRowPtrA,
- const int *csrColIndA,
- csric02Info_t info,
- int *pBufferSizeInBytes)
- {
- return cusparseScsric02_bufferSize(handle,
- m,
- nnz,
- descrA,
- csrValA,
- csrRowPtrA,
- csrColIndA,
- info,
- pBufferSizeInBytes);
- }
-
- template <>
- cusparseStatus_t
- cusparseXcsric02_bufferSize<double>(cusparseHandle_t handle,
- int m,
- int nnz,
- const cusparseMatDescr_t descrA,
- double *csrValA,
- const int *csrRowPtrA,
- const int *csrColIndA,
- csric02Info_t info,
- int *pBufferSizeInBytes)
- {
- return cusparseDcsric02_bufferSize(handle,
- m,
- nnz,
- descrA,
- csrValA,
- csrRowPtrA,
- csrColIndA,
- info,
- pBufferSizeInBytes);
- }
-
- /*
- template <>
- cusparseStatus_t
- cusparseXcsric02_bufferSize<cuComplex>(cusparseHandle_t handle,
- int m,
- int nnz,
- const cusparseMatDescr_t descrA,
- cuComplex * csrValA,
- const int * csrRowPtrA,
- const int * csrColIndA,
- csric02Info_t info,
- int *pBufferSizeInBytes)
- {
- return cusparseCcsric02_bufferSize(handle,
- m,
- nnz,
- descrA,
- csrValA,
- csrRowPtrA,
- csrColIndA,
- info,
- pBufferSizeInBytes);
- }
-
- template <>
- cusparseStatus_t
- cusparseXcsric02_bufferSize<cuDoubleComplex>(cusparseHandle_t handle,
- int m,
- int nnz,
- const cusparseMatDescr_t descrA,
- cuDoubleComplex * csrValA,
- const int * csrRowPtrA,
- const int * csrColIndA,
- csric02Info_t info,
- int * pBufferSizeInBytes)
- {
- return cusparseZcsric02_bufferSize(handle,
- m,
- nnz,
- descrA,
- csrValA,
- csrRowPtrA,
- csrColIndA,
- info,
- pBufferSizeInBytes);
- }
- */
-} // namespace
-
-namespace CUDAWrappers
-{
- template <typename Number>
- PreconditionIC<Number>::AdditionalData::AdditionalData(
- bool use_level_analysis_)
- : use_level_analysis(use_level_analysis_)
- {}
-
-
-
- template <typename Number>
- PreconditionIC<Number>::PreconditionIC(const Utilities::CUDA::Handle &handle)
- : cusparse_handle(handle.cusparse_handle)
- , P_val_dev(nullptr, Utilities::CUDA::delete_device_data<Number>)
- , P_row_ptr_dev(nullptr)
- , P_column_index_dev(nullptr)
- , tmp_dev(nullptr, Utilities::CUDA::delete_device_data<Number>)
- , buffer_dev(nullptr, Utilities::CUDA::delete_device_data<void>)
- , policy_L(CUSPARSE_SOLVE_POLICY_USE_LEVEL)
- , policy_Lt(CUSPARSE_SOLVE_POLICY_USE_LEVEL)
- , policy_M(CUSPARSE_SOLVE_POLICY_USE_LEVEL)
- , n_rows(0)
- , n_nonzero_elements(0)
- {
- // step 1: create a descriptor which contains
- // - matrix M is base-0
- // - matrix L is base-0
- // - matrix L is lower triangular
- // - matrix L has non-unit diagonal
- cusparseStatus_t status = cusparseCreateMatDescr(&descr_M);
- AssertCusparse(status);
- status = cusparseSetMatIndexBase(descr_M, CUSPARSE_INDEX_BASE_ZERO);
- AssertCusparse(status);
- status = cusparseSetMatType(descr_M, CUSPARSE_MATRIX_TYPE_GENERAL);
- AssertCusparse(status);
-
- status = cusparseCreateMatDescr(&descr_L);
- AssertCusparse(status);
- status = cusparseSetMatIndexBase(descr_L, CUSPARSE_INDEX_BASE_ZERO);
- AssertCusparse(status);
- status = cusparseSetMatType(descr_L, CUSPARSE_MATRIX_TYPE_GENERAL);
- AssertCusparse(status);
- status = cusparseSetMatFillMode(descr_L, CUSPARSE_FILL_MODE_LOWER);
- AssertCusparse(status);
- status = cusparseSetMatDiagType(descr_L, CUSPARSE_DIAG_TYPE_NON_UNIT);
- AssertCusparse(status);
-
- // step 2: create a empty info structure
- // we need one info for csric02 and two info's for csrsv2
- status = cusparseCreateCsric02Info(&info_M);
- AssertCusparse(status);
- status = cusparseCreateCsrsv2Info(&info_L);
- AssertCusparse(status);
- status = cusparseCreateCsrsv2Info(&info_Lt);
- AssertCusparse(status);
- }
-
-
-
- template <typename Number>
- PreconditionIC<Number>::~PreconditionIC()
- {
- // step 8: free resources
- cusparseStatus_t status = cusparseDestroyMatDescr(descr_M);
- AssertNothrowCusparse(status);
-
- status = cusparseDestroyMatDescr(descr_L);
- AssertNothrowCusparse(status);
-
- status = cusparseDestroyCsric02Info(info_M);
- AssertNothrowCusparse(status);
-
- status = cusparseDestroyCsrsv2Info(info_L);
- AssertNothrowCusparse(status);
-
- status = cusparseDestroyCsrsv2Info(info_Lt);
- AssertNothrowCusparse(status);
- }
-
-
-
- template <typename Number>
- void
- PreconditionIC<Number>::initialize(const SparseMatrix<Number> &A,
- const AdditionalData &additional_data)
- {
- if (additional_data.use_level_analysis)
- {
- policy_L = CUSPARSE_SOLVE_POLICY_USE_LEVEL;
- policy_Lt = CUSPARSE_SOLVE_POLICY_USE_LEVEL;
- policy_M = CUSPARSE_SOLVE_POLICY_USE_LEVEL;
- }
- else
- {
- policy_L = CUSPARSE_SOLVE_POLICY_NO_LEVEL;
- policy_Lt = CUSPARSE_SOLVE_POLICY_NO_LEVEL;
- policy_M = CUSPARSE_SOLVE_POLICY_NO_LEVEL;
- }
-
- n_rows = A.m();
- n_nonzero_elements = A.n_nonzero_elements();
- AssertDimension(A.m(), A.n());
-
- matrix_pointer = &A;
- const Number *A_val_dev;
- std::tie(A_val_dev,
- P_column_index_dev,
- P_row_ptr_dev,
- std::ignore,
- std::ignore) = A.get_cusparse_matrix();
-
- // create a copy of the matrix entries since the algorithm works in-place.
- P_val_dev.reset(
- Utilities::CUDA::allocate_device_data<Number>(n_nonzero_elements));
- cudaError_t cuda_status = cudaMemcpy(P_val_dev.get(),
- A_val_dev,
- n_nonzero_elements * sizeof(Number),
- cudaMemcpyDeviceToDevice);
- AssertCuda(cuda_status);
-
- // initialize an internal buffer we need later on
- tmp_dev.reset(Utilities::CUDA::allocate_device_data<Number>(n_rows));
-
- // step 3: query how much memory used in csric02 and csrsv2, and allocate
- // the buffer
- int BufferSize_M;
- cusparseStatus_t status = cusparseXcsric02_bufferSize(cusparse_handle,
- n_rows,
- n_nonzero_elements,
- descr_M,
- P_val_dev.get(),
- P_row_ptr_dev,
- P_column_index_dev,
- info_M,
- &BufferSize_M);
- AssertCusparse(status);
-
- int BufferSize_L;
- status = cusparseXcsrsv2_bufferSize(cusparse_handle,
- CUSPARSE_OPERATION_NON_TRANSPOSE,
- n_rows,
- n_nonzero_elements,
- descr_L,
- P_val_dev.get(),
- P_row_ptr_dev,
- P_column_index_dev,
- info_L,
- &BufferSize_L);
- AssertCusparse(status);
-
- int BufferSize_Lt;
- status = cusparseXcsrsv2_bufferSize(cusparse_handle,
- CUSPARSE_OPERATION_TRANSPOSE,
- n_rows,
- n_nonzero_elements,
- descr_L,
- P_val_dev.get(),
- P_row_ptr_dev,
- P_column_index_dev,
- info_Lt,
- &BufferSize_Lt);
- AssertCusparse(status);
-
- const int BufferSize =
- std::max(BufferSize_M, std::max(BufferSize_L, BufferSize_Lt));
- // workaround: since allocate_device_data needs a type, we pass char
- // which is required to have size 1.
- buffer_dev.reset(static_cast<void *>(
- Utilities::CUDA::allocate_device_data<char>(BufferSize / sizeof(char))));
-
- // step 4: perform analysis of incomplete Cholesky on M
- // perform analysis of triangular solve on L
- // perform analysis of triangular solve on L'
- // The lower triangular part of M has the same sparsity pattern as L, so
- // we can do analysis of csric02 and csrsv2 simultaneously.
-
- status = cusparseXcsric02_analysis(cusparse_handle,
- n_rows,
- n_nonzero_elements,
- descr_M,
- P_val_dev.get(),
- P_row_ptr_dev,
- P_column_index_dev,
- info_M,
- policy_M,
- buffer_dev.get());
- AssertCusparse(status);
-
- int structural_zero;
- status =
- cusparseXcsric02_zeroPivot(cusparse_handle, info_M, &structural_zero);
- AssertCusparse(status);
-
- status = cusparseXcsrsv2_analysis(cusparse_handle,
- CUSPARSE_OPERATION_TRANSPOSE,
- n_rows,
- n_nonzero_elements,
- descr_L,
- P_val_dev.get(),
- P_row_ptr_dev,
- P_column_index_dev,
- info_Lt,
- policy_Lt,
- buffer_dev.get());
- AssertCusparse(status);
-
- status = cusparseXcsrsv2_analysis(cusparse_handle,
- CUSPARSE_OPERATION_NON_TRANSPOSE,
- n_rows,
- n_nonzero_elements,
- descr_L,
- P_val_dev.get(),
- P_row_ptr_dev,
- P_column_index_dev,
- info_L,
- policy_L,
- buffer_dev.get());
- AssertCusparse(status);
-
- // step 5: M = L * L'
- status = cusparseXcsric02(cusparse_handle,
- n_rows,
- n_nonzero_elements,
- descr_M,
- P_val_dev.get(),
- P_row_ptr_dev,
- P_column_index_dev,
- info_M,
- policy_M,
- buffer_dev.get());
- AssertCusparse(status);
-
- int numerical_zero;
- status =
- cusparseXcsric02_zeroPivot(cusparse_handle, info_M, &numerical_zero);
- AssertCusparse(status);
- }
-
-
-
- template <typename Number>
- void
- PreconditionIC<Number>::vmult(
- LinearAlgebra::CUDAWrappers::Vector<Number> &dst,
- const LinearAlgebra::CUDAWrappers::Vector<Number> &src) const
- {
- Assert(P_val_dev != nullptr, ExcNotInitialized());
- Assert(P_row_ptr_dev != nullptr, ExcNotInitialized());
- Assert(P_column_index_dev != nullptr, ExcNotInitialized());
- AssertDimension(dst.size(), static_cast<unsigned int>(n_rows));
- AssertDimension(src.size(), static_cast<unsigned int>(n_rows));
- Assert(tmp_dev != nullptr, ExcInternalError());
-
- const Number *const src_dev = src.get_values();
- Number *const dst_dev = dst.get_values();
- // step 6: solve L*z = alpha*x
- const Number alpha = internal::NumberType<Number>::value(1.);
- cusparseStatus_t status =
- cusparseXcsrsv2_solve(cusparse_handle,
- CUSPARSE_OPERATION_NON_TRANSPOSE,
- n_rows,
- n_nonzero_elements,
- &alpha,
- descr_L,
- P_val_dev.get(),
- P_row_ptr_dev,
- P_column_index_dev,
- info_L,
- src_dev,
- tmp_dev.get(),
- policy_L,
- buffer_dev.get());
- AssertCusparse(status);
-
- // step 7: solve L'*y = alpha*z
- status = cusparseXcsrsv2_solve(cusparse_handle,
- CUSPARSE_OPERATION_TRANSPOSE,
- n_rows,
- n_nonzero_elements,
- &alpha,
- descr_L,
- P_val_dev.get(),
- P_row_ptr_dev,
- P_column_index_dev,
- info_Lt,
- tmp_dev.get(),
- dst_dev,
- policy_Lt,
- buffer_dev.get());
- AssertCusparse(status);
- }
-
-
-
- template <typename Number>
- void
- PreconditionIC<Number>::Tvmult(
- LinearAlgebra::CUDAWrappers::Vector<Number> &dst,
- const LinearAlgebra::CUDAWrappers::Vector<Number> &src) const
- {
- // the constructed preconditioner is symmetric
- vmult(dst, src);
- }
-
-
-
- template <typename Number>
- PreconditionILU<Number>::AdditionalData::AdditionalData(
- bool use_level_analysis_)
- : use_level_analysis(use_level_analysis_)
- {}
-
-
-
- template <typename Number>
- PreconditionILU<Number>::PreconditionILU(
- const Utilities::CUDA::Handle &handle)
- : cusparse_handle(handle.cusparse_handle)
- , P_val_dev(nullptr, Utilities::CUDA::delete_device_data<Number>)
- , P_row_ptr_dev(nullptr)
- , P_column_index_dev(nullptr)
- , tmp_dev(nullptr, Utilities::CUDA::delete_device_data<Number>)
- , buffer_dev(nullptr, Utilities::CUDA::delete_device_data<void>)
- , policy_L(CUSPARSE_SOLVE_POLICY_USE_LEVEL)
- , policy_U(CUSPARSE_SOLVE_POLICY_USE_LEVEL)
- , policy_M(CUSPARSE_SOLVE_POLICY_USE_LEVEL)
- , n_rows(0)
- , n_nonzero_elements(0)
- {
- // step 1: create a descriptor which contains
- // - matrix M is base-0
- // - matrix L is base-0
- // - matrix L is lower triangular
- // - matrix L has unit diagonal
- // - matrix U is base-0
- // - matrix U is upper triangular
- // - matrix U has non-unit diagonal
- cusparseStatus_t status = cusparseCreateMatDescr(&descr_M);
- AssertCusparse(status);
- status = cusparseSetMatIndexBase(descr_M, CUSPARSE_INDEX_BASE_ZERO);
- AssertCusparse(status);
- status = cusparseSetMatType(descr_M, CUSPARSE_MATRIX_TYPE_GENERAL);
- AssertCusparse(status);
-
- status = cusparseCreateMatDescr(&descr_L);
- AssertCusparse(status);
- status = cusparseSetMatIndexBase(descr_L, CUSPARSE_INDEX_BASE_ZERO);
- AssertCusparse(status);
- status = cusparseSetMatType(descr_L, CUSPARSE_MATRIX_TYPE_GENERAL);
- AssertCusparse(status);
- status = cusparseSetMatFillMode(descr_L, CUSPARSE_FILL_MODE_LOWER);
- AssertCusparse(status);
- status = cusparseSetMatDiagType(descr_L, CUSPARSE_DIAG_TYPE_UNIT);
- AssertCusparse(status);
-
- status = cusparseCreateMatDescr(&descr_U);
- AssertCusparse(status);
- status = cusparseSetMatIndexBase(descr_U, CUSPARSE_INDEX_BASE_ZERO);
- AssertCusparse(status);
- status = cusparseSetMatType(descr_U, CUSPARSE_MATRIX_TYPE_GENERAL);
- AssertCusparse(status);
- status = cusparseSetMatFillMode(descr_U, CUSPARSE_FILL_MODE_UPPER);
- AssertCusparse(status);
- status = cusparseSetMatDiagType(descr_U, CUSPARSE_DIAG_TYPE_NON_UNIT);
- AssertCusparse(status);
-
- // step 2: create a empty info structure
- // we need one info for csrilu02 and two info's for csrsv2
- status = cusparseCreateCsrilu02Info(&info_M);
- AssertCusparse(status);
- status = cusparseCreateCsrsv2Info(&info_L);
- AssertCusparse(status);
- status = cusparseCreateCsrsv2Info(&info_U);
- AssertCusparse(status);
- }
-
-
-
- template <typename Number>
- PreconditionILU<Number>::~PreconditionILU()
- {
- // step 8: free resources
- cusparseStatus_t status = cusparseDestroyMatDescr(descr_M);
- AssertNothrowCusparse(status);
-
- status = cusparseDestroyMatDescr(descr_L);
- AssertNothrowCusparse(status);
-
- status = cusparseDestroyMatDescr(descr_U);
- AssertNothrowCusparse(status);
-
- status = cusparseDestroyCsrilu02Info(info_M);
- AssertNothrowCusparse(status);
-
- status = cusparseDestroyCsrsv2Info(info_L);
- AssertNothrowCusparse(status);
-
- status = cusparseDestroyCsrsv2Info(info_U);
- AssertNothrowCusparse(status);
- }
-
-
-
- template <typename Number>
- void
- PreconditionILU<Number>::initialize(const SparseMatrix<Number> &A,
- const AdditionalData &additional_data)
- {
- if (additional_data.use_level_analysis)
- {
- policy_L = CUSPARSE_SOLVE_POLICY_USE_LEVEL;
- policy_U = CUSPARSE_SOLVE_POLICY_USE_LEVEL;
- policy_M = CUSPARSE_SOLVE_POLICY_USE_LEVEL;
- }
- else
- {
- policy_L = CUSPARSE_SOLVE_POLICY_NO_LEVEL;
- policy_U = CUSPARSE_SOLVE_POLICY_NO_LEVEL;
- policy_M = CUSPARSE_SOLVE_POLICY_NO_LEVEL;
- }
-
- matrix_pointer = &A;
- n_rows = A.m();
- n_nonzero_elements = A.n_nonzero_elements();
- AssertDimension(A.m(), A.n());
-
- const Number *A_val_dev;
- std::tie(A_val_dev,
- P_column_index_dev,
- P_row_ptr_dev,
- std::ignore,
- std::ignore) = A.get_cusparse_matrix();
-
- // create a copy of the matrix entries since the algorithm works in-place.
- P_val_dev.reset(
- Utilities::CUDA::allocate_device_data<Number>(n_nonzero_elements));
- cudaError_t cuda_status = cudaMemcpy(P_val_dev.get(),
- A_val_dev,
- n_nonzero_elements * sizeof(Number),
- cudaMemcpyDeviceToDevice);
- AssertCuda(cuda_status);
-
- // initialize an internal buffer we need later on
- tmp_dev.reset(Utilities::CUDA::allocate_device_data<Number>(n_rows));
-
- // step 3: query how much memory used in csrilu02 and csrsv2, and allocate
- // the buffer
- int BufferSize_M;
- cusparseStatus_t status = cusparseXcsrilu02_bufferSize(cusparse_handle,
- n_rows,
- n_nonzero_elements,
- descr_M,
- P_val_dev.get(),
- P_row_ptr_dev,
- P_column_index_dev,
- info_M,
- &BufferSize_M);
- AssertCusparse(status);
-
- int BufferSize_L;
- status = cusparseXcsrsv2_bufferSize(cusparse_handle,
- CUSPARSE_OPERATION_NON_TRANSPOSE,
- n_rows,
- n_nonzero_elements,
- descr_L,
- P_val_dev.get(),
- P_row_ptr_dev,
- P_column_index_dev,
- info_L,
- &BufferSize_L);
- AssertCusparse(status);
-
- int BufferSize_U;
- status = cusparseXcsrsv2_bufferSize(cusparse_handle,
- CUSPARSE_OPERATION_NON_TRANSPOSE,
- n_rows,
- n_nonzero_elements,
- descr_U,
- P_val_dev.get(),
- P_row_ptr_dev,
- P_column_index_dev,
- info_U,
- &BufferSize_U);
- AssertCusparse(status);
-
- const int BufferSize =
- std::max(BufferSize_M, std::max(BufferSize_L, BufferSize_U));
- // workaround: since allocate_device_data needs a type, we pass char
- // which is required to have size 1.
- buffer_dev.reset(static_cast<void *>(
- Utilities::CUDA::allocate_device_data<char>(BufferSize / sizeof(char))));
-
- // step 4: perform analysis of incomplete Cholesky on M
- // perform analysis of triangular solve on L
- // perform analysis of triangular solve on U
- // The lower(upper) triangular part of M has the same sparsity pattern as
- // L(U), we can do analysis of csrilu0 and csrsv2 simultaneously.
-
- status = cusparseXcsrilu02_analysis(cusparse_handle,
- n_rows,
- n_nonzero_elements,
- descr_M,
- P_val_dev.get(),
- P_row_ptr_dev,
- P_column_index_dev,
- info_M,
- policy_M,
- buffer_dev.get());
- AssertCusparse(status);
-
- int structural_zero;
- status =
- cusparseXcsrilu02_zeroPivot(cusparse_handle, info_M, &structural_zero);
- AssertCusparse(status);
-
- status = cusparseXcsrsv2_analysis(cusparse_handle,
- CUSPARSE_OPERATION_NON_TRANSPOSE,
- n_rows,
- n_nonzero_elements,
- descr_L,
- P_val_dev.get(),
- P_row_ptr_dev,
- P_column_index_dev,
- info_L,
- policy_L,
- buffer_dev.get());
- AssertCusparse(status);
-
- status = cusparseXcsrsv2_analysis(cusparse_handle,
- CUSPARSE_OPERATION_NON_TRANSPOSE,
- n_rows,
- n_nonzero_elements,
- descr_U,
- P_val_dev.get(),
- P_row_ptr_dev,
- P_column_index_dev,
- info_U,
- policy_U,
- buffer_dev.get());
-
- // step 5: M = L * U
- status = cusparseXcsrilu02(cusparse_handle,
- n_rows,
- n_nonzero_elements,
- descr_M,
- P_val_dev.get(),
- P_row_ptr_dev,
- P_column_index_dev,
- info_M,
- policy_M,
- buffer_dev.get());
- AssertCusparse(status);
-
- int numerical_zero;
- status =
- cusparseXcsrilu02_zeroPivot(cusparse_handle, info_M, &numerical_zero);
- AssertCusparse(status);
- }
-
-
-
- template <typename Number>
- void
- PreconditionILU<Number>::vmult(
- LinearAlgebra::CUDAWrappers::Vector<Number> &dst,
- const LinearAlgebra::CUDAWrappers::Vector<Number> &src) const
- {
- Assert(P_val_dev != nullptr, ExcNotInitialized());
- Assert(P_row_ptr_dev != nullptr, ExcNotInitialized());
- Assert(P_column_index_dev != nullptr, ExcNotInitialized());
- AssertDimension(dst.size(), static_cast<unsigned int>(n_rows));
- AssertDimension(src.size(), static_cast<unsigned int>(n_rows));
- Assert(tmp_dev != nullptr, ExcInternalError());
-
- const Number *const src_dev = src.get_values();
- Number *const dst_dev = dst.get_values();
-
- // step 6: solve L*z = alpha*x
- const Number alpha = internal::NumberType<Number>::value(1.);
- cusparseStatus_t status =
- cusparseXcsrsv2_solve(cusparse_handle,
- CUSPARSE_OPERATION_NON_TRANSPOSE,
- n_rows,
- n_nonzero_elements,
- &alpha,
- descr_L,
- P_val_dev.get(),
- P_row_ptr_dev,
- P_column_index_dev,
- info_L,
- src_dev,
- tmp_dev.get(),
- policy_L,
- buffer_dev.get());
- AssertCusparse(status);
-
- // step 7: solve U*y = alpha*z
- status = cusparseXcsrsv2_solve(cusparse_handle,
- CUSPARSE_OPERATION_NON_TRANSPOSE,
- n_rows,
- n_nonzero_elements,
- &alpha,
- descr_U,
- P_val_dev.get(),
- P_row_ptr_dev,
- P_column_index_dev,
- info_U,
- tmp_dev.get(),
- dst_dev,
- policy_U,
- buffer_dev.get());
- AssertCusparse(status);
- }
-
-
-
- template <typename Number>
- void
- PreconditionILU<Number>::Tvmult(
- LinearAlgebra::CUDAWrappers::Vector<Number> & /*dst*/,
- const LinearAlgebra::CUDAWrappers::Vector<Number> & /*src*/) const
- {
- DEAL_II_NOT_IMPLEMENTED();
- }
-
-
-
- // explicit instantiations
- template class PreconditionIC<float>;
- template class PreconditionIC<double>;
- // template class PreconditionIC<cuComplex>;
- // template class PreconditionIC<cuDoubleComplex>;
- template class PreconditionILU<float>;
- template class PreconditionILU<double>;
- // template class PreconditionILU<cuComplex>;
- // template class PreconditionILU<cuDoubleComplex>;
-} // namespace CUDAWrappers
-
-DEAL_II_NAMESPACE_CLOSE
+++ /dev/null
-// ------------------------------------------------------------------------
-//
-// SPDX-License-Identifier: LGPL-2.1-or-later
-// Copyright (C) 2018 - 2023 by the deal.II authors
-//
-// This file is part of the deal.II library.
-//
-// Part of the source code is dual licensed under Apache-2.0 WITH
-// LLVM-exception OR LGPL-2.1-or-later. Detailed license information
-// governing the source code and code contributions can be found in
-// LICENSE.md and CONTRIBUTING.md at the top level directory of deal.II.
-//
-// ------------------------------------------------------------------------
-
-#include <deal.II/lac/cuda_solver_direct.h>
-
-DEAL_II_NAMESPACE_OPEN
-
-namespace CUDAWrappers
-{
- namespace
- {
- void
- cusparsecsr2dense(cusparseHandle_t cusparse_handle,
- const SparseMatrix<float> &matrix,
- float *dense_matrix_dev)
- {
- auto cusparse_matrix = matrix.get_cusparse_matrix();
-
- const cusparseStatus_t cusparse_error_code =
- cusparseScsr2dense(cusparse_handle,
- matrix.m(),
- matrix.n(),
- std::get<3>(cusparse_matrix),
- std::get<0>(cusparse_matrix),
- std::get<2>(cusparse_matrix),
- std::get<1>(cusparse_matrix),
- dense_matrix_dev,
- matrix.m());
- AssertCusparse(cusparse_error_code);
- }
-
-
-
- void
- cusparsecsr2dense(cusparseHandle_t cusparse_handle,
- const SparseMatrix<double> &matrix,
- double *dense_matrix_dev)
- {
- auto cusparse_matrix = matrix.get_cusparse_matrix();
-
- const cusparseStatus_t cusparse_error_code =
- cusparseDcsr2dense(cusparse_handle,
- matrix.m(),
- matrix.n(),
- std::get<3>(cusparse_matrix),
- std::get<0>(cusparse_matrix),
- std::get<2>(cusparse_matrix),
- std::get<1>(cusparse_matrix),
- dense_matrix_dev,
- matrix.m());
- AssertCusparse(cusparse_error_code);
- }
-
-
-
- void
- cusolverDngetrf_buffer_size(cusolverDnHandle_t cusolver_dn_handle,
- int m,
- int n,
- float *dense_matrix_dev,
- int &workspace_size)
- {
- const cusolverStatus_t cusolver_error_code = cusolverDnSgetrf_bufferSize(
- cusolver_dn_handle, m, n, dense_matrix_dev, m, &workspace_size);
- AssertCusolver(cusolver_error_code);
- }
-
-
-
- void
- cusolverDngetrf_buffer_size(cusolverDnHandle_t cusolver_dn_handle,
- int m,
- int n,
- double *dense_matrix_dev,
- int &workspace_size)
- {
- const cusolverStatus_t cusolver_error_code = cusolverDnDgetrf_bufferSize(
- cusolver_dn_handle, m, n, dense_matrix_dev, m, &workspace_size);
- AssertCusolver(cusolver_error_code);
- }
-
-
-
- void
- cusolverDngetrf(cusolverDnHandle_t cusolver_dn_handle,
- int m,
- int n,
- float *dense_matrix_dev,
- float *workspace_dev,
- int *pivot_dev,
- int *info_dev)
- {
- const cusolverStatus_t cusolver_error_code =
- cusolverDnSgetrf(cusolver_dn_handle,
- m,
- n,
- dense_matrix_dev,
- m,
- workspace_dev,
- pivot_dev,
- info_dev);
- AssertCusolver(cusolver_error_code);
- }
-
-
-
- void
- cusolverDngetrf(cusolverDnHandle_t cusolver_dn_handle,
- int m,
- int n,
- double *dense_matrix_dev,
- double *workspace_dev,
- int *pivot_dev,
- int *info_dev)
- {
- const cusolverStatus_t cusolver_error_code =
- cusolverDnDgetrf(cusolver_dn_handle,
- m,
- n,
- dense_matrix_dev,
- m,
- workspace_dev,
- pivot_dev,
- info_dev);
- AssertCusolver(cusolver_error_code);
- }
-
-
-
- void
- cusolverDngetrs(cusolverDnHandle_t cusolver_dn_handle,
- int m,
- float *dense_matrix_dev,
- int *pivot_dev,
- float *b,
- int *info_dev)
- {
- const int n_rhs = 1;
- const cusolverStatus_t cusolver_error_code =
- cusolverDnSgetrs(cusolver_dn_handle,
- CUBLAS_OP_N,
- m,
- n_rhs,
- dense_matrix_dev,
- m,
- pivot_dev,
- b,
- m,
- info_dev);
- AssertCusolver(cusolver_error_code);
- }
-
-
-
- void
- cusolverDngetrs(cusolverDnHandle_t cusolver_dn_handle,
- int m,
- double *dense_matrix_dev,
- int *pivot_dev,
- double *b,
- int *info_dev)
- {
- const int n_rhs = 1;
- const cusolverStatus_t cusolver_error_code =
- cusolverDnDgetrs(cusolver_dn_handle,
- CUBLAS_OP_N,
- m,
- n_rhs,
- dense_matrix_dev,
- m,
- pivot_dev,
- b,
- m,
- info_dev);
- AssertCusolver(cusolver_error_code);
- }
-
-
-
- void
- cusolverSpcsrlsvluHost(cusolverSpHandle_t cusolver_sp_handle,
- const unsigned int n_rows,
- const unsigned int nnz,
- cusparseMatDescr_t descr,
- const float *val_host,
- const int *row_ptr_host,
- const int *column_index_host,
- const float *b_host,
- float *x_host)
- {
- int singularity = 0;
- const cusolverStatus_t cusolver_error_code =
- cusolverSpScsrlsvluHost(cusolver_sp_handle,
- n_rows,
- nnz,
- descr,
- val_host,
- row_ptr_host,
- column_index_host,
- b_host,
- 0.,
- 1,
- x_host,
- &singularity);
- AssertCusolver(cusolver_error_code);
- Assert(singularity == -1, ExcMessage("Coarse matrix is singular"));
- }
-
-
-
- void
- cusolverSpcsrlsvluHost(cusolverSpHandle_t cusolver_sp_handle,
- const unsigned int n_rows,
- unsigned int nnz,
- cusparseMatDescr_t descr,
- const double *val_host,
- const int *row_ptr_host,
- const int *column_index_host,
- const double *b_host,
- double *x_host)
- {
- int singularity = 0;
- const cusolverStatus_t cusolver_error_code =
- cusolverSpDcsrlsvluHost(cusolver_sp_handle,
- n_rows,
- nnz,
- descr,
- val_host,
- row_ptr_host,
- column_index_host,
- b_host,
- 0.,
- 1,
- x_host,
- &singularity);
- AssertCusolver(cusolver_error_code);
- Assert(singularity == -1, ExcMessage("Coarse matrix is singular"));
- }
-
-
-
- void
- cholesky_factorization(cusolverSpHandle_t cusolver_sp_handle,
- const SparseMatrix<float> &matrix,
- const float *b,
- float *x)
- {
- auto cusparse_matrix = matrix.get_cusparse_matrix();
- int singularity = 0;
-
- const cusolverStatus_t cusolver_error_code =
- cusolverSpScsrlsvchol(cusolver_sp_handle,
- matrix.m(),
- matrix.n_nonzero_elements(),
- std::get<3>(cusparse_matrix),
- std::get<0>(cusparse_matrix),
- std::get<2>(cusparse_matrix),
- std::get<1>(cusparse_matrix),
- b,
- 0.,
- 0,
- x,
- &singularity);
- AssertCusolver(cusolver_error_code);
- Assert(singularity == -1, ExcMessage("Coarse matrix is not SPD"));
- }
-
-
-
- void
- cholesky_factorization(cusolverSpHandle_t cusolver_sp_handle,
- const SparseMatrix<double> &matrix,
- const double *b,
- double *x)
- {
- auto cusparse_matrix = matrix.get_cusparse_matrix();
- int singularity = 0;
-
- const cusolverStatus_t cusolver_error_code =
- cusolverSpDcsrlsvchol(cusolver_sp_handle,
- matrix.m(),
- matrix.n_nonzero_elements(),
- std::get<3>(cusparse_matrix),
- std::get<0>(cusparse_matrix),
- std::get<2>(cusparse_matrix),
- std::get<1>(cusparse_matrix),
- b,
- 0.,
- 0,
- x,
- &singularity);
- AssertCusolver(cusolver_error_code);
- Assert(singularity == -1, ExcMessage("Coarse matrix is not SPD"));
- }
-
-
-
- template <typename Number>
- void
- lu_factorization(cusparseHandle_t cusparse_handle,
- cusolverDnHandle_t cusolver_dn_handle,
- const SparseMatrix<Number> &matrix,
- const Number *b_dev,
- Number *x_dev)
- {
- // Change the format of the matrix from sparse to dense
- const unsigned int m = matrix.m();
- const unsigned int n = matrix.n();
- Assert(m == n, ExcMessage("The matrix is not square"));
- Number *dense_matrix_dev;
- Utilities::CUDA::malloc(dense_matrix_dev, m * n);
-
- // Change the format of matrix to dense
- cusparsecsr2dense(cusparse_handle, matrix, dense_matrix_dev);
-
- // Create the working space
- int workspace_size = 0;
- cusolverDngetrf_buffer_size(
- cusolver_dn_handle, m, n, dense_matrix_dev, workspace_size);
- Assert(workspace_size > 0, ExcMessage("No workspace was allocated"));
- Number *workspace_dev;
- Utilities::CUDA::malloc(workspace_dev, workspace_size);
-
- // LU factorization
- int *pivot_dev;
- Utilities::CUDA::malloc(pivot_dev, m);
- int *info_dev;
- Utilities::CUDA::malloc(info_dev, 1);
-
- cusolverDngetrf(cusolver_dn_handle,
- m,
- n,
- dense_matrix_dev,
- workspace_dev,
- pivot_dev,
- info_dev);
-
-#ifdef DEBUG
- int info = 0;
- cudaError_t cuda_error_code_debug =
- cudaMemcpy(&info, info_dev, sizeof(int), cudaMemcpyDeviceToHost);
- AssertCuda(cuda_error_code_debug);
- Assert(info == 0,
- ExcMessage("There was a problem during the LU factorization"));
-#endif
-
- // Solve Ax = b
- cudaError_t cuda_error_code =
- cudaMemcpy(x_dev, b_dev, m * sizeof(Number), cudaMemcpyDeviceToDevice);
- AssertCuda(cuda_error_code);
- cusolverDngetrs(
- cusolver_dn_handle, m, dense_matrix_dev, pivot_dev, x_dev, info_dev);
-#ifdef DEBUG
- cuda_error_code =
- cudaMemcpy(&info, info_dev, sizeof(int), cudaMemcpyDeviceToHost);
- AssertCuda(cuda_error_code);
- Assert(info == 0, ExcMessage("There was a problem during the LU solve"));
-#endif
-
- // Free the memory allocated
- Utilities::CUDA::free(dense_matrix_dev);
- Utilities::CUDA::free(workspace_dev);
- Utilities::CUDA::free(pivot_dev);
- Utilities::CUDA::free(info_dev);
- }
-
-
-
- template <typename Number>
- void
- lu_factorization(cusolverSpHandle_t cusolver_sp_handle,
- const SparseMatrix<Number> &matrix,
- const Number *b_dev,
- Number *x_dev)
- {
- // cuSOLVER does not support LU factorization of sparse matrix on the
- // device, so we need to move everything to the host first and then back
- // to the host.
- const unsigned int nnz = matrix.n_nonzero_elements();
- const unsigned int n_rows = matrix.m();
- std::vector<Number> val_host(nnz);
- std::vector<int> column_index_host(nnz);
- std::vector<int> row_ptr_host(n_rows + 1);
- auto cusparse_matrix = matrix.get_cusparse_matrix();
- Utilities::CUDA::copy_to_host(std::get<0>(cusparse_matrix), val_host);
- Utilities::CUDA::copy_to_host(std::get<1>(cusparse_matrix),
- column_index_host);
- Utilities::CUDA::copy_to_host(std::get<2>(cusparse_matrix), row_ptr_host);
- std::vector<Number> b_host(n_rows);
- Utilities::CUDA::copy_to_host(b_dev, b_host);
- std::vector<Number> x_host(n_rows);
- Utilities::CUDA::copy_to_host(x_dev, x_host);
-
- cusolverSpcsrlsvluHost(cusolver_sp_handle,
- n_rows,
- nnz,
- std::get<3>(cusparse_matrix),
- val_host.data(),
- row_ptr_host.data(),
- column_index_host.data(),
- b_host.data(),
- x_host.data());
-
- // Move the solution back to the device
- Utilities::CUDA::copy_to_dev(x_host, x_dev);
- }
- } // namespace
-
-
-
- template <typename Number>
- SolverDirect<Number>::AdditionalData::AdditionalData(
- const std::string &solver_type)
- : solver_type(solver_type)
- {}
-
-
-
- template <typename Number>
- SolverDirect<Number>::SolverDirect(const Utilities::CUDA::Handle &handle,
- SolverControl &cn,
- const AdditionalData &data)
- : cuda_handle(handle)
- , solver_control(cn)
- , additional_data(data.solver_type)
- {}
-
-
-
- template <typename Number>
- SolverControl &
- SolverDirect<Number>::control() const
- {
- return solver_control;
- }
-
-
-
- template <typename Number>
- void
- SolverDirect<Number>::solve(
- const SparseMatrix<Number> &A,
- LinearAlgebra::CUDAWrappers::Vector<Number> &x,
- const LinearAlgebra::CUDAWrappers::Vector<Number> &b)
- {
- if (additional_data.solver_type == "Cholesky")
- cholesky_factorization(cuda_handle.cusolver_sp_handle,
- A,
- b.get_values(),
- x.get_values());
- else if (additional_data.solver_type == "LU_dense")
- lu_factorization(cuda_handle.cusparse_handle,
- cuda_handle.cusolver_dn_handle,
- A,
- b.get_values(),
- x.get_values());
- else if (additional_data.solver_type == "LU_host")
- lu_factorization(cuda_handle.cusolver_sp_handle,
- A,
- b.get_values(),
- x.get_values());
- else
- AssertThrow(false,
- ExcMessage("The provided solver name " +
- additional_data.solver_type + " is invalid."));
-
- // Force the SolverControl object to report convergence
- solver_control.check(0, 0);
- }
-
-
- // Explicit Instanationation
- template class SolverDirect<float>;
- template class SolverDirect<double>;
-} // namespace CUDAWrappers
-
-DEAL_II_NAMESPACE_CLOSE
+++ /dev/null
-// ------------------------------------------------------------------------
-//
-// SPDX-License-Identifier: LGPL-2.1-or-later
-// Copyright (C) 2018 - 2023 by the deal.II authors
-//
-// This file is part of the deal.II library.
-//
-// Part of the source code is dual licensed under Apache-2.0 WITH
-// LLVM-exception OR LGPL-2.1-or-later. Detailed license information
-// governing the source code and code contributions can be found in
-// LICENSE.md and CONTRIBUTING.md at the top level directory of deal.II.
-//
-// ------------------------------------------------------------------------
-
-#include <deal.II/base/cuda_size.h>
-#include <deal.II/base/exceptions.h>
-
-#include <deal.II/lac/cuda_atomic.h>
-#include <deal.II/lac/cuda_sparse_matrix.h>
-
-#ifdef DEAL_II_WITH_CUDA
-
-# include <cusparse.h>
-
-DEAL_II_NAMESPACE_OPEN
-
-namespace CUDAWrappers
-{
- namespace internal
- {
- template <typename Number>
- __global__ void
- scale(Number *val,
- const Number a,
- const typename SparseMatrix<Number>::size_type N)
- {
- const typename SparseMatrix<Number>::size_type idx =
- threadIdx.x + blockIdx.x * blockDim.x;
- if (idx < N)
- val[idx] *= a;
- }
-
-
-
- void
- create_sp_mat_descr(int m,
- int n,
- int nnz,
- const float *A_val_dev,
- const int *A_row_ptr_dev,
- const int *A_column_index_dev,
- cusparseSpMatDescr_t &sp_descr)
- {
- cusparseStatus_t error_code = cusparseCreateCsr(
- &sp_descr,
- m,
- n,
- nnz,
- reinterpret_cast<void *>(const_cast<int *>(A_row_ptr_dev)),
- reinterpret_cast<void *>(const_cast<int *>(A_column_index_dev)),
- reinterpret_cast<void *>(const_cast<float *>(A_val_dev)),
- CUSPARSE_INDEX_32I,
- CUSPARSE_INDEX_32I,
- CUSPARSE_INDEX_BASE_ZERO,
- CUDA_R_32F);
- AssertCusparse(error_code);
- }
-
-
-
- void
- create_sp_mat_descr(int m,
- int n,
- int nnz,
- const double *A_val_dev,
- const int *A_row_ptr_dev,
- const int *A_column_index_dev,
- cusparseSpMatDescr_t &sp_descr)
- {
- cusparseStatus_t error_code = cusparseCreateCsr(
- &sp_descr,
- m,
- n,
- nnz,
- reinterpret_cast<void *>(const_cast<int *>(A_row_ptr_dev)),
- reinterpret_cast<void *>(const_cast<int *>(A_column_index_dev)),
- reinterpret_cast<void *>(const_cast<double *>(A_val_dev)),
- CUSPARSE_INDEX_32I,
- CUSPARSE_INDEX_32I,
- CUSPARSE_INDEX_BASE_ZERO,
- CUDA_R_64F);
- AssertCusparse(error_code);
- }
-
-
-
- void
- csrmv(cusparseHandle_t handle,
- bool transpose,
- int m,
- int n,
- const cusparseSpMatDescr_t sp_descr,
- const float *x,
- bool add,
- float *y)
- {
- float alpha = 1.;
- float beta = add ? 1. : 0.;
- cusparseOperation_t cusparse_operation =
- transpose ? CUSPARSE_OPERATION_TRANSPOSE :
- CUSPARSE_OPERATION_NON_TRANSPOSE;
-
- // Move the data to cuSPARSE data type
- cusparseDnVecDescr_t x_cuvec;
- cusparseStatus_t error_code =
- cusparseCreateDnVec(&x_cuvec,
- n,
- reinterpret_cast<void *>(const_cast<float *>(x)),
- CUDA_R_32F);
- AssertCusparse(error_code);
-
- cusparseDnVecDescr_t y_cuvec;
- error_code =
- cusparseCreateDnVec(&y_cuvec,
- m,
- reinterpret_cast<void *>(const_cast<float *>(y)),
- CUDA_R_32F);
- AssertCusparse(error_code);
-
- // This function performs y = alpha*op(A)*x + beta*y
- size_t buffer_size = 0;
- error_code = cusparseSpMV_bufferSize(handle,
- cusparse_operation,
- &alpha,
- sp_descr,
- x_cuvec,
- &beta,
- y_cuvec,
- CUDA_R_32F,
- CUSPARSE_MV_ALG_DEFAULT,
- &buffer_size);
-
- void *buffer = nullptr;
- cudaError_t cuda_error_code = cudaMalloc(&buffer, buffer_size);
- AssertCuda(cuda_error_code);
-
- // execute SpMV
- error_code = cusparseSpMV(handle,
- cusparse_operation,
- &alpha,
- sp_descr,
- x_cuvec,
- &beta,
- y_cuvec,
- CUDA_R_32F,
- CUSPARSE_MV_ALG_DEFAULT,
- buffer);
- AssertCusparse(error_code);
-
- cuda_error_code = cudaFree(buffer);
- AssertCuda(cuda_error_code);
- error_code = cusparseDestroyDnVec(x_cuvec);
- AssertCusparse(error_code);
- error_code = cusparseDestroyDnVec(y_cuvec);
- AssertCusparse(error_code);
- }
-
-
-
- void
- csrmv(cusparseHandle_t handle,
- bool transpose,
- int m,
- int n,
- const cusparseSpMatDescr_t sp_descr,
- const double *x,
- bool add,
- double *y)
- {
- double alpha = 1.;
- double beta = add ? 1. : 0.;
- cusparseOperation_t cusparse_operation =
- transpose ? CUSPARSE_OPERATION_TRANSPOSE :
- CUSPARSE_OPERATION_NON_TRANSPOSE;
-
- // Move the data to cuSPARSE data type
- cusparseDnVecDescr_t x_cuvec;
- cusparseStatus_t error_code =
- cusparseCreateDnVec(&x_cuvec,
- n,
- reinterpret_cast<void *>(const_cast<double *>(x)),
- CUDA_R_64F);
- AssertCusparse(error_code);
-
- cusparseDnVecDescr_t y_cuvec;
- error_code =
- cusparseCreateDnVec(&y_cuvec,
- m,
- reinterpret_cast<void *>(const_cast<double *>(y)),
- CUDA_R_64F);
- AssertCusparse(error_code);
-
- // This function performs y = alpha*op(A)*x + beta*y
- size_t buffer_size = 0;
- error_code = cusparseSpMV_bufferSize(handle,
- cusparse_operation,
- &alpha,
- sp_descr,
- x_cuvec,
- &beta,
- y_cuvec,
- CUDA_R_64F,
- CUSPARSE_MV_ALG_DEFAULT,
- &buffer_size);
-
- void *buffer = nullptr;
- cudaError_t cuda_error_code = cudaMalloc(&buffer, buffer_size);
- AssertCuda(cuda_error_code);
-
- // execute SpMV
- error_code = cusparseSpMV(handle,
- cusparse_operation,
- &alpha,
- sp_descr,
- x_cuvec,
- &beta,
- y_cuvec,
- CUDA_R_64F,
- CUSPARSE_MV_ALG_DEFAULT,
- buffer);
- AssertCusparse(error_code);
-
- cuda_error_code = cudaFree(buffer);
- AssertCuda(cuda_error_code);
- error_code = cusparseDestroyDnVec(x_cuvec);
- AssertCusparse(error_code);
- error_code = cusparseDestroyDnVec(y_cuvec);
- AssertCusparse(error_code);
- }
-
-
-
- template <typename Number>
- __global__ void
- l1_norm(const typename SparseMatrix<Number>::size_type n_rows,
- const Number *val_dev,
- const int *column_index_dev,
- const int *row_ptr_dev,
- Number *sums)
- {
- const typename SparseMatrix<Number>::size_type row =
- threadIdx.x + blockIdx.x * blockDim.x;
-
- if (row < n_rows)
- {
- for (int j = row_ptr_dev[row]; j < row_ptr_dev[row + 1]; ++j)
- atomicAdd(&sums[column_index_dev[j]], std::abs(val_dev[j]));
- }
- }
-
-
-
- template <typename Number>
- __global__ void
- linfty_norm(const typename SparseMatrix<Number>::size_type n_rows,
- const Number *val_dev,
- const int * /*column_index_dev*/,
- const int *row_ptr_dev,
- Number *sums)
- {
- const typename SparseMatrix<Number>::size_type row =
- threadIdx.x + blockIdx.x * blockDim.x;
-
- if (row < n_rows)
- {
- sums[row] = (Number)0.;
- for (int j = row_ptr_dev[row]; j < row_ptr_dev[row + 1]; ++j)
- sums[row] += std::abs(val_dev[j]);
- }
- }
- } // namespace internal
-
-
-
- template <typename Number>
- SparseMatrix<Number>::SparseMatrix()
- : nnz(0)
- , n_rows(0)
- , val_dev(nullptr, Utilities::CUDA::delete_device_data<Number>)
- , column_index_dev(nullptr, Utilities::CUDA::delete_device_data<int>)
- , row_ptr_dev(nullptr, Utilities::CUDA::delete_device_data<int>)
- , descr(nullptr)
- , sp_descr(nullptr)
- {}
-
-
-
- template <typename Number>
- SparseMatrix<Number>::SparseMatrix(
- Utilities::CUDA::Handle &handle,
- const ::dealii::SparseMatrix<Number> &sparse_matrix_host)
- : val_dev(nullptr, Utilities::CUDA::delete_device_data<Number>)
- , column_index_dev(nullptr, Utilities::CUDA::delete_device_data<int>)
- , row_ptr_dev(nullptr, Utilities::CUDA::delete_device_data<int>)
- , descr(nullptr)
- , sp_descr(nullptr)
- {
- reinit(handle, sparse_matrix_host);
- }
-
-
-
- template <typename Number>
- SparseMatrix<Number>::SparseMatrix(CUDAWrappers::SparseMatrix<Number> &&other)
- : cusparse_handle(other.cusparse_handle)
- , nnz(other.nnz)
- , n_rows(other.n_rows)
- , n_cols(other.n_cols)
- , val_dev(std::move(other.val_dev))
- , column_index_dev(std::move(other.column_index_dev))
- , row_ptr_dev(std::move(other.row_ptr_dev))
- , descr(other.descr)
- , sp_descr(other.sp_descr)
- {
- other.nnz = 0;
- other.n_rows = 0;
- other.n_cols = 0;
- other.descr = nullptr;
- other.sp_descr = nullptr;
- }
-
-
-
- template <typename Number>
- SparseMatrix<Number>::~SparseMatrix<Number>()
- {
- if (descr != nullptr)
- {
- const cusparseStatus_t cusparse_error_code =
- cusparseDestroyMatDescr(descr);
- AssertNothrowCusparse(cusparse_error_code);
- descr = nullptr;
- }
-
- if (sp_descr != nullptr)
- {
- const cusparseStatus_t cusparse_error_code =
- cusparseDestroySpMat(sp_descr);
- AssertNothrowCusparse(cusparse_error_code);
- sp_descr = nullptr;
- }
-
- nnz = 0;
- n_rows = 0;
- }
-
-
-
- template <typename Number>
- SparseMatrix<Number> &
- SparseMatrix<Number>::operator=(SparseMatrix<Number> &&other)
- {
- cusparse_handle = other.cusparse_handle;
- nnz = other.nnz;
- n_rows = other.n_rows;
- n_cols = other.n_cols;
- val_dev = std::move(other.val_dev);
- column_index_dev = std::move(other.column_index_dev);
- row_ptr_dev = std::move(other.row_ptr_dev);
- descr = other.descr;
- sp_descr = other.sp_descr;
-
- other.nnz = 0;
- other.n_rows = 0;
- other.n_cols = 0;
- other.descr = nullptr;
- other.sp_descr = nullptr;
-
- return *this;
- }
-
-
-
- template <typename Number>
- void
- SparseMatrix<Number>::reinit(
- Utilities::CUDA::Handle &handle,
- const ::dealii::SparseMatrix<Number> &sparse_matrix_host)
- {
- cusparse_handle = handle.cusparse_handle;
- nnz = sparse_matrix_host.n_nonzero_elements();
- n_rows = sparse_matrix_host.m();
- n_cols = sparse_matrix_host.n();
- const unsigned int row_ptr_size = n_rows + 1;
- std::vector<Number> val;
- val.reserve(nnz);
- std::vector<int> column_index;
- column_index.reserve(nnz);
- std::vector<int> row_ptr(row_ptr_size, 0);
-
- // dealii::SparseMatrix stores the diagonal first in each row so we need to
- // do some reordering
- for (int row = 0; row < n_rows; ++row)
- {
- auto p_end = sparse_matrix_host.end(row);
- unsigned int counter = 0;
- for (auto p = sparse_matrix_host.begin(row); p != p_end; ++p)
- {
- val.emplace_back(p->value());
- column_index.emplace_back(p->column());
- ++counter;
- }
- row_ptr[row + 1] = row_ptr[row] + counter;
-
- // Sort the elements in the row
- const unsigned int offset = row_ptr[row];
- const int diag_index = column_index[offset];
- Number diag_elem = sparse_matrix_host.diag_element(row);
- unsigned int pos = 1;
- while ((column_index[offset + pos] < row) && (pos < counter))
- {
- val[offset + pos - 1] = val[offset + pos];
- column_index[offset + pos - 1] = column_index[offset + pos];
- ++pos;
- }
- val[offset + pos - 1] = diag_elem;
- column_index[offset + pos - 1] = diag_index;
- }
-
- // Copy the elements to the gpu
- val_dev.reset(Utilities::CUDA::allocate_device_data<Number>(nnz));
- cudaError_t error_code = cudaMemcpy(val_dev.get(),
- val.data(),
- nnz * sizeof(Number),
- cudaMemcpyHostToDevice);
- AssertCuda(error_code);
-
- // Copy the column indices to the gpu
- column_index_dev.reset(Utilities::CUDA::allocate_device_data<int>(nnz));
- AssertCuda(error_code);
- error_code = cudaMemcpy(column_index_dev.get(),
- column_index.data(),
- nnz * sizeof(int),
- cudaMemcpyHostToDevice);
- AssertCuda(error_code);
-
- // Copy the row pointer to the gpu
- row_ptr_dev.reset(Utilities::CUDA::allocate_device_data<int>(row_ptr_size));
- AssertCuda(error_code);
- error_code = cudaMemcpy(row_ptr_dev.get(),
- row_ptr.data(),
- row_ptr_size * sizeof(int),
- cudaMemcpyHostToDevice);
- AssertCuda(error_code);
-
- // Create the matrix descriptor
- cusparseStatus_t cusparse_error_code = cusparseCreateMatDescr(&descr);
- AssertCusparse(cusparse_error_code);
- cusparse_error_code =
- cusparseSetMatType(descr, CUSPARSE_MATRIX_TYPE_GENERAL);
- AssertCusparse(cusparse_error_code);
- cusparse_error_code =
- cusparseSetMatIndexBase(descr, CUSPARSE_INDEX_BASE_ZERO);
- AssertCusparse(cusparse_error_code);
-
- // Create the sparse matrix descriptor
- internal::create_sp_mat_descr(n_rows,
- n_cols,
- nnz,
- val_dev.get(),
- row_ptr_dev.get(),
- column_index_dev.get(),
- sp_descr);
- }
-
-
-
- template <typename Number>
- SparseMatrix<Number> &
- SparseMatrix<Number>::operator*=(const Number factor)
- {
- AssertIsFinite(factor);
- const int n_blocks = 1 + (nnz - 1) / block_size;
- internal::scale<Number>
- <<<n_blocks, block_size>>>(val_dev.get(), factor, nnz);
- AssertCudaKernel();
-
- return *this;
- }
-
-
-
- template <typename Number>
- SparseMatrix<Number> &
- SparseMatrix<Number>::operator/=(const Number factor)
- {
- AssertIsFinite(factor);
- Assert(factor != Number(0.), ExcZero());
- const int n_blocks = 1 + (nnz - 1) / block_size;
- internal::scale<Number>
- <<<n_blocks, block_size>>>(val_dev.get(), 1. / factor, nnz);
- AssertCudaKernel();
-
- return *this;
- }
-
-
-
- template <typename Number>
- void
- SparseMatrix<Number>::vmult(
- LinearAlgebra::CUDAWrappers::Vector<Number> &dst,
- const LinearAlgebra::CUDAWrappers::Vector<Number> &src) const
- {
- internal::csrmv(cusparse_handle,
- false,
- n_rows,
- n_cols,
- sp_descr,
- src.get_values(),
- false,
- dst.get_values());
- }
-
-
-
- template <typename Number>
- void
- SparseMatrix<Number>::Tvmult(
- LinearAlgebra::CUDAWrappers::Vector<Number> &dst,
- const LinearAlgebra::CUDAWrappers::Vector<Number> &src) const
- {
- internal::csrmv(cusparse_handle,
- true,
- n_rows,
- n_cols,
- sp_descr,
- src.get_values(),
- false,
- dst.get_values());
- }
-
-
-
- template <typename Number>
- void
- SparseMatrix<Number>::vmult_add(
- LinearAlgebra::CUDAWrappers::Vector<Number> &dst,
- const LinearAlgebra::CUDAWrappers::Vector<Number> &src) const
- {
- internal::csrmv(cusparse_handle,
- false,
- n_rows,
- n_cols,
- sp_descr,
- src.get_values(),
- true,
- dst.get_values());
- }
-
-
-
- template <typename Number>
- void
- SparseMatrix<Number>::Tvmult_add(
- LinearAlgebra::CUDAWrappers::Vector<Number> &dst,
- const LinearAlgebra::CUDAWrappers::Vector<Number> &src) const
- {
- internal::csrmv(cusparse_handle,
- true,
- n_rows,
- n_cols,
- sp_descr,
- src.get_values(),
- true,
- dst.get_values());
- }
-
-
-
- template <typename Number>
- Number
- SparseMatrix<Number>::matrix_norm_square(
- const LinearAlgebra::CUDAWrappers::Vector<Number> &v) const
- {
- LinearAlgebra::CUDAWrappers::Vector<Number> tmp = v;
- vmult(tmp, v);
-
- return v * tmp;
- }
-
-
-
- template <typename Number>
- Number
- SparseMatrix<Number>::matrix_scalar_product(
- const LinearAlgebra::CUDAWrappers::Vector<Number> &u,
- const LinearAlgebra::CUDAWrappers::Vector<Number> &v) const
- {
- LinearAlgebra::CUDAWrappers::Vector<Number> tmp = v;
- vmult(tmp, v);
-
- return u * tmp;
- }
-
-
-
- template <typename Number>
- Number
- SparseMatrix<Number>::residual(
- LinearAlgebra::CUDAWrappers::Vector<Number> &dst,
- const LinearAlgebra::CUDAWrappers::Vector<Number> &x,
- const LinearAlgebra::CUDAWrappers::Vector<Number> &b) const
- {
- vmult(dst, x);
- dst.sadd(-1., 1., b);
-
- return dst.l2_norm();
- }
-
-
-
- template <typename Number>
- Number
- SparseMatrix<Number>::l1_norm() const
- {
- LinearAlgebra::CUDAWrappers::Vector<real_type> column_sums(n_cols);
- const int n_blocks = 1 + (nnz - 1) / block_size;
- internal::l1_norm<Number>
- <<<n_blocks, block_size>>>(n_rows,
- val_dev.get(),
- column_index_dev.get(),
- row_ptr_dev.get(),
- column_sums.get_values());
- AssertCudaKernel();
-
- return column_sums.linfty_norm();
- }
-
-
-
- template <typename Number>
- Number
- SparseMatrix<Number>::linfty_norm() const
- {
- LinearAlgebra::CUDAWrappers::Vector<real_type> row_sums(n_rows);
- const int n_blocks = 1 + (nnz - 1) / block_size;
- internal::linfty_norm<Number>
- <<<n_blocks, block_size>>>(n_rows,
- val_dev.get(),
- column_index_dev.get(),
- row_ptr_dev.get(),
- row_sums.get_values());
- AssertCudaKernel();
-
- return row_sums.linfty_norm();
- }
-
-
-
- template <typename Number>
- Number
- SparseMatrix<Number>::frobenius_norm() const
- {
- LinearAlgebra::CUDAWrappers::Vector<real_type> matrix_values(nnz);
- cudaError_t cuda_error = cudaMemcpy(matrix_values.get_values(),
- val_dev.get(),
- nnz * sizeof(Number),
- cudaMemcpyDeviceToDevice);
- AssertCuda(cuda_error);
-
- return matrix_values.l2_norm();
- }
-
-
-
- template <typename Number>
- std::tuple<Number *, int *, int *, cusparseMatDescr_t, cusparseSpMatDescr_t>
- SparseMatrix<Number>::get_cusparse_matrix() const
- {
- return std::make_tuple(val_dev.get(),
- column_index_dev.get(),
- row_ptr_dev.get(),
- descr,
- sp_descr);
- }
-
-
-
- template class SparseMatrix<float>;
- template class SparseMatrix<double>;
-} // namespace CUDAWrappers
-DEAL_II_NAMESPACE_CLOSE
-
-#endif
+++ /dev/null
-// ------------------------------------------------------------------------
-//
-// SPDX-License-Identifier: LGPL-2.1-or-later
-// Copyright (C) 2016 - 2023 by the deal.II authors
-//
-// This file is part of the deal.II library.
-//
-// Part of the source code is dual licensed under Apache-2.0 WITH
-// LLVM-exception OR LGPL-2.1-or-later. Detailed license information
-// governing the source code and code contributions can be found in
-// LICENSE.md and CONTRIBUTING.md at the top level directory of deal.II.
-//
-// ------------------------------------------------------------------------
-
-#include <deal.II/base/cuda.h>
-#include <deal.II/base/cuda_size.h>
-#include <deal.II/base/exceptions.h>
-
-#include <deal.II/lac/cuda_atomic.h>
-#include <deal.II/lac/cuda_kernels.h>
-#include <deal.II/lac/cuda_vector.h>
-#include <deal.II/lac/read_write_vector.h>
-
-#include <cmath>
-
-#ifdef DEAL_II_WITH_CUDA
-
-DEAL_II_NAMESPACE_OPEN
-
-namespace LinearAlgebra
-{
- namespace CUDAWrappers
- {
- using ::dealii::CUDAWrappers::block_size;
- using ::dealii::CUDAWrappers::chunk_size;
-
-
-
- template <typename Number>
- Vector<Number>::Vector()
- : val(nullptr, Utilities::CUDA::delete_device_data<Number>)
- , n_elements(0)
- {}
-
-
-
- template <typename Number>
- Vector<Number>::Vector(const Vector<Number> &V)
- : val(Utilities::CUDA::allocate_device_data<Number>(V.n_elements),
- Utilities::CUDA::delete_device_data<Number>)
- , n_elements(V.n_elements)
- {
- // Copy the values.
- const cudaError_t error_code = cudaMemcpy(val.get(),
- V.val.get(),
- n_elements * sizeof(Number),
- cudaMemcpyDeviceToDevice);
- AssertCuda(error_code);
- }
-
-
-
- template <typename Number>
- Vector<Number> &
- Vector<Number>::operator=(const Vector<Number> &V)
- {
- if (n_elements < V.n_elements)
- reinit(V.n_elements, true);
- else
- n_elements = V.n_elements;
-
- // Copy the values.
- const cudaError_t error_code = cudaMemcpy(val.get(),
- V.val.get(),
- n_elements * sizeof(Number),
- cudaMemcpyDeviceToDevice);
- AssertCuda(error_code);
-
- return *this;
- }
-
-
-
- template <typename Number>
- Vector<Number>::Vector(const size_type n)
- : val(nullptr, Utilities::CUDA::delete_device_data<Number>)
- , n_elements(0)
- {
- reinit(n, false);
- }
-
-
-
- template <typename Number>
- void
- Vector<Number>::reinit(const size_type n, const bool omit_zeroing_entries)
- {
- // Resize the underlying array if necessary
- if (n == 0)
- val.reset();
- else if (n != n_elements)
- val.reset(Utilities::CUDA::allocate_device_data<Number>(n));
-
- // If necessary set the elements to zero
- if (omit_zeroing_entries == false)
- {
- const cudaError_t error_code =
- cudaMemset(val.get(), 0, n * sizeof(Number));
- AssertCuda(error_code);
- }
- n_elements = n;
- }
-
-
-
- template <typename Number>
- void
- Vector<Number>::reinit(const Vector<Number> &V,
- const bool omit_zeroing_entries)
- {
- reinit(V.size(), omit_zeroing_entries);
- }
-
-
-
- template <typename Number>
- void
- Vector<Number>::import_elements(
- const ReadWriteVector<Number> &V,
- const VectorOperation::values operation,
- const std::shared_ptr<const Utilities::MPI::CommunicationPatternBase> &)
- {
- if (operation == VectorOperation::insert)
- {
- const cudaError_t error_code = cudaMemcpy(val.get(),
- V.begin(),
- n_elements * sizeof(Number),
- cudaMemcpyHostToDevice);
- AssertCuda(error_code);
- }
- else if (operation == VectorOperation::add)
- {
- // Create a temporary vector on the device
- Number *tmp;
- cudaError_t error_code =
- cudaMalloc(&tmp, n_elements * sizeof(Number));
- AssertCuda(error_code);
-
- // Copy the vector from the host to the temporary vector on the device
- error_code = cudaMemcpy(tmp,
- V.begin(),
- n_elements * sizeof(Number),
- cudaMemcpyHostToDevice);
- AssertCuda(error_code);
-
- // Add the two vectors
- const int n_blocks = 1 + (n_elements - 1) / (chunk_size * block_size);
-
- kernel::vector_bin_op<Number, kernel::Binop_Addition>
- <<<n_blocks, block_size>>>(val.get(), tmp, n_elements);
- AssertCudaKernel();
-
- // Delete the temporary vector
- Utilities::CUDA::free(tmp);
- }
- else
- AssertThrow(false, ExcNotImplemented());
- }
-
-
-
- template <typename Number>
- Vector<Number> &
- Vector<Number>::operator=(const Number s)
- {
- Assert(s == Number(), ExcMessage("Only 0 can be assigned to a vector."));
- (void)s;
-
- const cudaError_t error_code =
- cudaMemset(val.get(), 0, n_elements * sizeof(Number));
- AssertCuda(error_code);
-
- return *this;
- }
-
-
-
- template <typename Number>
- Vector<Number> &
- Vector<Number>::operator*=(const Number factor)
- {
- AssertIsFinite(factor);
- const int n_blocks = 1 + (n_elements - 1) / (chunk_size * block_size);
- kernel::vec_scale<Number>
- <<<n_blocks, block_size>>>(val.get(), factor, n_elements);
- AssertCudaKernel();
-
- return *this;
- }
-
-
-
- template <typename Number>
- Vector<Number> &
- Vector<Number>::operator/=(const Number factor)
- {
- AssertIsFinite(factor);
- Assert(factor != Number(0.), ExcZero());
- const int n_blocks = 1 + (n_elements - 1) / (chunk_size * block_size);
- kernel::vec_scale<Number>
- <<<n_blocks, block_size>>>(val.get(), 1. / factor, n_elements);
- AssertCudaKernel();
-
- return *this;
- }
-
-
-
- template <typename Number>
- Vector<Number> &
- Vector<Number>::operator+=(const Vector<Number> &V)
- {
- Assert(V.size() == this->size(),
- ExcMessage(
- "Cannot add two vectors with different numbers of elements"));
-
- const int n_blocks = 1 + (n_elements - 1) / (chunk_size * block_size);
-
- kernel::vector_bin_op<Number, kernel::Binop_Addition>
- <<<n_blocks, block_size>>>(val.get(), V.val.get(), n_elements);
- AssertCudaKernel();
-
- return *this;
- }
-
-
-
- template <typename Number>
- Vector<Number> &
- Vector<Number>::operator-=(const Vector<Number> &V)
- {
- Assert(V.size() == this->size(),
- ExcMessage(
- "Cannot add two vectors with different numbers of elements."));
-
- const int n_blocks = 1 + (n_elements - 1) / (chunk_size * block_size);
-
- kernel::vector_bin_op<Number, kernel::Binop_Subtraction>
- <<<n_blocks, block_size>>>(val.get(), V.val.get(), n_elements);
- AssertCudaKernel();
-
- return *this;
- }
-
-
-
- template <typename Number>
- Number
- Vector<Number>::operator*(const Vector<Number> &V) const
- {
- Assert(V.size() == this->size(),
- ExcMessage(
- "Cannot add two vectors with different numbers of elements"));
-
- Number *result_device;
- cudaError_t error_code =
- cudaMalloc(&result_device, n_elements * sizeof(Number));
- AssertCuda(error_code);
- error_code = cudaMemset(result_device, 0, sizeof(Number));
-
- const int n_blocks = 1 + (n_elements - 1) / (chunk_size * block_size);
- kernel::double_vector_reduction<Number, kernel::DotProduct<Number>>
- <<<dim3(n_blocks, 1), dim3(block_size)>>>(result_device,
- val.get(),
- V.val.get(),
- static_cast<unsigned int>(
- n_elements));
-
- // Copy the result back to the host
- Number result;
- error_code = cudaMemcpy(&result,
- result_device,
- sizeof(Number),
- cudaMemcpyDeviceToHost);
- AssertCuda(error_code);
- // Free the memory on the device
- Utilities::CUDA::free(result_device);
-
- return result;
- }
-
-
-
- template <typename Number>
- void
- Vector<Number>::add(const Number a)
- {
- AssertIsFinite(a);
- const int n_blocks = 1 + (n_elements - 1) / (chunk_size * block_size);
- kernel::vec_add<Number>
- <<<n_blocks, block_size>>>(val.get(), a, n_elements);
- AssertCudaKernel();
- }
-
-
-
- template <typename Number>
- void
- Vector<Number>::add(const Number a, const Vector<Number> &V)
- {
- AssertIsFinite(a);
-
- Assert(V.size() == this->size(),
- ExcMessage(
- "Cannot add two vectors with different numbers of elements."));
-
- const int n_blocks = 1 + (n_elements - 1) / (chunk_size * block_size);
- kernel::add_aV<Number><<<dim3(n_blocks, 1), dim3(block_size)>>>(
- val.get(), a, V.val.get(), n_elements);
- AssertCudaKernel();
- }
-
-
-
- template <typename Number>
- void
- Vector<Number>::add(const Number a,
- const Vector<Number> &V,
- const Number b,
- const Vector<Number> &W)
- {
- AssertIsFinite(a);
- AssertIsFinite(b);
-
- Assert(V.size() == this->size(),
- ExcMessage(
- "Cannot add two vectors with different numbers of elements."));
-
- Assert(W.size() == this->size(),
- ExcMessage(
- "Cannot add two vectors with different numbers of elements."));
-
- const int n_blocks = 1 + (n_elements - 1) / (chunk_size * block_size);
- kernel::add_aVbW<Number><<<dim3(n_blocks, 1), dim3(block_size)>>>(
- val.get(), a, V.val.get(), b, W.val.get(), n_elements);
- AssertCudaKernel();
- }
-
-
-
- template <typename Number>
- void
- Vector<Number>::sadd(const Number s,
- const Number a,
- const Vector<Number> &V)
- {
- AssertIsFinite(s);
- AssertIsFinite(a);
-
- Assert(V.size() == this->size(),
- ExcMessage(
- "Cannot add two vectors with different numbers of elements."));
-
- const int n_blocks = 1 + (n_elements - 1) / (chunk_size * block_size);
- kernel::sadd<Number><<<dim3(n_blocks, 1), dim3(block_size)>>>(
- s, val.get(), a, V.val.get(), n_elements);
- AssertCudaKernel();
- }
-
-
-
- template <typename Number>
- void
- Vector<Number>::scale(const Vector<Number> &scaling_factors)
- {
- Assert(scaling_factors.size() == this->size(),
- ExcMessage(
- "Cannot scale two vectors with different numbers of elements."));
-
- const int n_blocks = 1 + (n_elements - 1) / (chunk_size * block_size);
- kernel::scale<Number>
- <<<dim3(n_blocks, 1), dim3(block_size)>>>(val.get(),
- scaling_factors.val.get(),
- n_elements);
- AssertCudaKernel();
- }
-
-
-
- template <typename Number>
- void
- Vector<Number>::equ(const Number a, const Vector<Number> &V)
- {
- AssertIsFinite(a);
-
- Assert(
- V.size() == this->size(),
- ExcMessage(
- "Cannot assign two vectors with different numbers of elements."));
-
- const int n_blocks = 1 + (n_elements - 1) / (chunk_size * block_size);
- kernel::equ<Number><<<dim3(n_blocks, 1), dim3(block_size)>>>(val.get(),
- a,
- V.val.get(),
- n_elements);
- AssertCudaKernel();
- }
-
-
-
- template <typename Number>
- bool
- Vector<Number>::all_zero() const
- {
- return (linfty_norm() == 0) ? true : false;
- }
-
-
-
- template <typename Number>
- typename Vector<Number>::value_type
- Vector<Number>::mean_value() const
- {
- Number *result_device;
- cudaError_t error_code = cudaMalloc(&result_device, sizeof(Number));
- AssertCuda(error_code);
- error_code = cudaMemset(result_device, 0, sizeof(Number));
-
- const int n_blocks = 1 + (n_elements - 1) / (chunk_size * block_size);
- kernel::reduction<Number, kernel::ElemSum<Number>>
- <<<dim3(n_blocks, 1), dim3(block_size)>>>(result_device,
- val.get(),
- n_elements);
-
- // Copy the result back to the host
- Number result;
- error_code = cudaMemcpy(&result,
- result_device,
- sizeof(Number),
- cudaMemcpyDeviceToHost);
- AssertCuda(error_code);
- // Free the memory on the device
- Utilities::CUDA::free(result_device);
-
- return result /
- static_cast<typename Vector<Number>::value_type>(n_elements);
- }
-
-
-
- template <typename Number>
- typename Vector<Number>::real_type
- Vector<Number>::l1_norm() const
- {
- Number *result_device;
- cudaError_t error_code = cudaMalloc(&result_device, sizeof(Number));
- AssertCuda(error_code);
- error_code = cudaMemset(result_device, 0, sizeof(Number));
-
- const int n_blocks = 1 + (n_elements - 1) / (chunk_size * block_size);
- kernel::reduction<Number, kernel::L1Norm<Number>>
- <<<dim3(n_blocks, 1), dim3(block_size)>>>(result_device,
- val.get(),
- n_elements);
-
- // Copy the result back to the host
- Number result;
- error_code = cudaMemcpy(&result,
- result_device,
- sizeof(Number),
- cudaMemcpyDeviceToHost);
- AssertCuda(error_code);
- // Free the memory on the device
- Utilities::CUDA::free(result_device);
-
- return result;
- }
-
-
-
- template <typename Number>
- typename Vector<Number>::real_type
- Vector<Number>::l2_norm() const
- {
- return std::sqrt(norm_sqr());
- }
-
-
-
- template <typename Number>
- typename Vector<Number>::real_type
- Vector<Number>::norm_sqr() const
- {
- return (*this) * (*this);
- }
-
-
-
- template <typename Number>
- typename Vector<Number>::real_type
- Vector<Number>::linfty_norm() const
- {
- Number *result_device;
- cudaError_t error_code = cudaMalloc(&result_device, sizeof(Number));
- AssertCuda(error_code);
- error_code = cudaMemset(result_device, 0, sizeof(Number));
-
- const int n_blocks = 1 + (n_elements - 1) / (chunk_size * block_size);
- kernel::reduction<Number, kernel::LInfty<Number>>
- <<<dim3(n_blocks, 1), dim3(block_size)>>>(result_device,
- val.get(),
- n_elements);
-
- // Copy the result back to the host
- Number result;
- error_code = cudaMemcpy(&result,
- result_device,
- sizeof(Number),
- cudaMemcpyDeviceToHost);
- AssertCuda(error_code);
- // Free the memory on the device
- Utilities::CUDA::free(result_device);
-
- return result;
- }
-
-
-
- template <typename Number>
- Number
- Vector<Number>::add_and_dot(const Number a,
- const Vector<Number> &V,
- const Vector<Number> &W)
- {
- AssertIsFinite(a);
-
- Assert(V.size() == this->size(),
- ExcMessage("Vector V has the wrong size."));
- Assert(W.size() == this->size(),
- ExcMessage("Vector W has the wrong size."));
-
- Number *result_device;
- cudaError_t error_code = cudaMalloc(&result_device, sizeof(Number));
- AssertCuda(error_code);
- error_code = cudaMemset(result_device, 0, sizeof(Number));
- AssertCuda(error_code);
-
- const int n_blocks = 1 + (n_elements - 1) / (chunk_size * block_size);
- kernel::add_and_dot<Number><<<dim3(n_blocks, 1), dim3(block_size)>>>(
- result_device, val.get(), V.val.get(), W.val.get(), a, n_elements);
-
- Number result;
- error_code = cudaMemcpy(&result,
- result_device,
- sizeof(Number),
- cudaMemcpyDeviceToHost);
- Utilities::CUDA::free(result_device);
-
- return result;
- }
-
-
-
- template <typename Number>
- void
- Vector<Number>::print(std::ostream &out,
- const unsigned int precision,
- const bool scientific,
- const bool) const
- {
- AssertThrow(out.fail() == false, ExcIO());
- std::ios::fmtflags old_flags = out.flags();
- unsigned int old_precision = out.precision(precision);
-
- out.precision(precision);
- if (scientific)
- out.setf(std::ios::scientific, std::ios::floatfield);
- else
- out.setf(std::ios::fixed, std::ios::floatfield);
-
- out << "IndexSet: ";
- complete_index_set(n_elements).print(out);
- out << std::endl;
-
- // Copy the vector to the host
- std::vector<Number> cpu_val(n_elements);
- Utilities::CUDA::copy_to_host(val.get(), cpu_val);
- for (unsigned int i = 0; i < n_elements; ++i)
- out << cpu_val[i] << std::endl;
- out << std::flush;
-
- AssertThrow(out.fail() == false, ExcIO());
- // reset output format
- out.flags(old_flags);
- out.precision(old_precision);
- }
-
-
-
- template <typename Number>
- std::size_t
- Vector<Number>::memory_consumption() const
- {
- std::size_t memory = sizeof(*this);
- memory += sizeof(Number) * static_cast<std::size_t>(n_elements);
-
- return memory;
- }
-
-
-
- // Explicit Instanationation
- template class Vector<float>;
- template class Vector<double>;
- } // namespace CUDAWrappers
-} // namespace LinearAlgebra
-
-DEAL_II_NAMESPACE_CLOSE
-
-#endif
+++ /dev/null
-// ------------------------------------------------------------------------
-//
-// SPDX-License-Identifier: LGPL-2.1-or-later
-// Copyright (C) 2018 - 2023 by the deal.II authors
-//
-// This file is part of the deal.II library.
-//
-// Part of the source code is dual licensed under Apache-2.0 WITH
-// LLVM-exception OR LGPL-2.1-or-later. Detailed license information
-// governing the source code and code contributions can be found in
-// LICENSE.md and CONTRIBUTING.md at the top level directory of deal.II.
-//
-// ------------------------------------------------------------------------
-
-#include <deal.II/lac/read_write_vector.h>
-#include <deal.II/lac/read_write_vector.templates.h>
-
-DEAL_II_NAMESPACE_OPEN
-
-#ifndef DOXYGEN
-
-namespace LinearAlgebra
-{
- template void
- ReadWriteVector<float>::import_elements(
- const CUDAWrappers::Vector<float> &,
- VectorOperation::values,
- const std::shared_ptr<const Utilities::MPI::CommunicationPatternBase> &);
- template void
- ReadWriteVector<float>::import_elements(
- const distributed::Vector<float, ::dealii::MemorySpace::CUDA> &,
- VectorOperation::values,
- const std::shared_ptr<const Utilities::MPI::CommunicationPatternBase> &);
-
- template void
- ReadWriteVector<double>::import_elements(
- const CUDAWrappers::Vector<double> &,
- VectorOperation::values,
- const std::shared_ptr<const Utilities::MPI::CommunicationPatternBase> &);
- template void
- ReadWriteVector<double>::import_elements(
- const distributed::Vector<double, ::dealii::MemorySpace::CUDA> &,
- VectorOperation::values,
- const std::shared_ptr<const Utilities::MPI::CommunicationPatternBase> &);
-} // namespace LinearAlgebra
-
-#endif // DOXYGEN
-
-DEAL_II_NAMESPACE_CLOSE
# ifdef DEAL_II_WITH_COMPLEX_VALUES
# ifdef HAVE_TPETRA_INST_COMPLEX_FLOAT
# ifdef DEAL_II_HAVE_CXX20
- static_assert(concepts::is_vector_space_vector <
- BlockVector<std::complex<float>>);
+ static_assert(
+ concepts::is_vector_space_vector<BlockVector<std::complex<float>>>);
# endif
template class BlockVector<std::complex<float>>;
# endif
# ifdef HAVE_TPETRA_INST_COMPLEX_DOUBLE
# ifdef DEAL_II_HAVE_CXX20
- static_assert(concepts::is_vector_space_vector <
- BlockVector<std::complex<double>>);
+ static_assert(
+ concepts::is_vector_space_vector<BlockVector<std::complex<double>>>);
# endif
template class BlockVector<std::complex<double>>;
# endif
# ifdef DEAL_II_WITH_COMPLEX_VALUES
# ifdef HAVE_TPETRA_INST_COMPLEX_FLOAT
# ifdef DEAL_II_HAVE_CXX20
- static_assert(concepts::is_vector_space_vector <
- Vector<std::complex<float>>);
+ static_assert(
+ concepts::is_vector_space_vector<Vector<std::complex<float>>>);
# endif
template class Vector<std::complex<float>>;
template Vector<std::complex<float>> &
# ifdef HAVE_TPETRA_INST_COMPLEX_DOUBLE
# ifdef DEAL_II_HAVE_CXX20
- static_assert(concepts::is_vector_space_vector <
- Vector<std::complex<double>>);
+ static_assert(
+ concepts::is_vector_space_vector<Vector<std::complex<double>>>);
# endif
template class Vector<std::complex<double>>;
template Vector<std::complex<double>> &
{
namespace GrowingVectorMemoryImplementation
{
-#ifdef DEAL_II_WITH_CUDA
- void
- release_all_unused_cuda_memory();
-#endif
-
void
release_all_unused_memory()
{
dealii::GrowingVectorMemory<dealii::LinearAlgebra::distributed::Vector<
double,
MemorySpace::Default>>::release_unused_memory();
-#ifdef DEAL_II_WITH_CUDA
- release_all_unused_cuda_memory();
-#endif
}
} // namespace GrowingVectorMemoryImplementation
} // namespace internal
+++ /dev/null
-// ------------------------------------------------------------------------
-//
-// SPDX-License-Identifier: LGPL-2.1-or-later
-// Copyright (C) 2019 - 2022 by the deal.II authors
-//
-// This file is part of the deal.II library.
-//
-// Part of the source code is dual licensed under Apache-2.0 WITH
-// LLVM-exception OR LGPL-2.1-or-later. Detailed license information
-// governing the source code and code contributions can be found in
-// LICENSE.md and CONTRIBUTING.md at the top level directory of deal.II.
-//
-// ------------------------------------------------------------------------
-
-#include <deal.II/lac/cuda_vector.h>
-#include <deal.II/lac/la_parallel_vector.h>
-#include <deal.II/lac/vector_memory.templates.h>
-
-
-DEAL_II_NAMESPACE_OPEN
-
-template class VectorMemory<LinearAlgebra::CUDAWrappers::Vector<float>>;
-template class VectorMemory<LinearAlgebra::CUDAWrappers::Vector<double>>;
-template class GrowingVectorMemory<LinearAlgebra::CUDAWrappers::Vector<float>>;
-template class GrowingVectorMemory<LinearAlgebra::CUDAWrappers::Vector<double>>;
-
-namespace internal
-{
- namespace GrowingVectorMemoryImplementation
- {
- void
- release_all_unused_cuda_memory()
- {
- dealii::GrowingVectorMemory<dealii::LinearAlgebra::CUDAWrappers::Vector<
- float>>::release_unused_memory();
- dealii::GrowingVectorMemory<dealii::LinearAlgebra::CUDAWrappers::Vector<
- double>>::release_unused_memory();
- }
- } // namespace GrowingVectorMemoryImplementation
-} // namespace internal
-
-DEAL_II_NAMESPACE_CLOSE
//
// ------------------------------------------------------------------------
-// Test that Point operations on a CUDA device can be used.
+// Test that Point operations with the default Kokkos backend can be used.
#include <deal.II/base/point.h>
+++ /dev/null
-cmake_minimum_required(VERSION 3.13.4)
-include(../scripts/setup_testsubproject.cmake)
-project(testsuite CXX)
-if(DEAL_II_WITH_CUDA)
- deal_ii_pickup_tests()
-endif()
+++ /dev/null
-// ------------------------------------------------------------------------
-//
-// SPDX-License-Identifier: LGPL-2.1-or-later
-// Copyright (C) 2016 - 2023 by the deal.II authors
-//
-// This file is part of the deal.II library.
-//
-// Part of the source code is dual licensed under Apache-2.0 WITH
-// LLVM-exception OR LGPL-2.1-or-later. Detailed license information
-// governing the source code and code contributions can be found in
-// LICENSE.md and CONTRIBUTING.md at the top level directory of deal.II.
-//
-// ------------------------------------------------------------------------
-
-
-// Check LinearAlgebra::CUDAWrappers::Vector assignment and import
-
-#include <deal.II/base/utilities.h>
-
-#include <deal.II/lac/cuda_vector.h>
-#include <deal.II/lac/read_write_vector.h>
-
-#include <fstream>
-#include <iostream>
-
-#include "../tests.h"
-
-void
-test()
-{
- const unsigned int size = 100;
- LinearAlgebra::CUDAWrappers::Vector<double> a;
- LinearAlgebra::CUDAWrappers::Vector<double> b(size);
- LinearAlgebra::CUDAWrappers::Vector<double> c(b);
- LinearAlgebra::CUDAWrappers::Vector<double> d;
- d.reinit(c);
-
- AssertThrow(a.size() == 0, ExcMessage("Vector has the wrong size."));
- AssertThrow(b.size() == size, ExcMessage("Vector has the wrong size."));
- AssertThrow(c.size() == size, ExcMessage("Vector has the wrong size."));
- AssertThrow(d.size() == size, ExcMessage("Vector has the wrong size."));
-
- a.reinit(size);
- AssertThrow(a.size() == size, ExcMessage("Vector has the wrong size."));
-
-
- LinearAlgebra::ReadWriteVector<double> read_write_1(size);
- LinearAlgebra::ReadWriteVector<double> read_write_2(size);
- LinearAlgebra::ReadWriteVector<double> read_write_3(size);
- for (unsigned int i = 0; i < size; ++i)
- {
- read_write_1[i] = i;
- read_write_2[i] = 5. + i;
- }
-
- a.import_elements(read_write_2, VectorOperation::insert);
- b.import_elements(read_write_1, VectorOperation::insert);
- c.import_elements(read_write_2, VectorOperation::insert);
-
-
- read_write_3.import_elements(a, VectorOperation::insert);
- for (unsigned int i = 0; i < size; ++i)
- AssertThrow(read_write_2[i] == read_write_3[i],
- ExcMessage("Vector a has been modified."));
-
- read_write_3.import_elements(b, VectorOperation::insert);
- for (unsigned int i = 0; i < size; ++i)
- AssertThrow(read_write_1[i] == read_write_3[i],
- ExcMessage("Vector b has been modified."));
-
- read_write_3.import_elements(c, VectorOperation::insert);
- for (unsigned int i = 0; i < size; ++i)
- AssertThrow(read_write_2[i] == read_write_3[i],
- ExcMessage("Vector c has been modified."));
-
- a *= 2.;
- read_write_3.import_elements(a, VectorOperation::insert);
- for (unsigned int i = 0; i < size; ++i)
- AssertThrow(2. * read_write_2[i] == read_write_3[i],
- ExcMessage("Problem in operator *=."));
-
- c /= 2.;
- read_write_3.import_elements(c, VectorOperation::insert);
- for (unsigned int i = 0; i < size; ++i)
- AssertThrow(0.5 * read_write_2[i] == read_write_3[i],
- ExcMessage("Problem in operator /=."));
-
- b += a;
- read_write_3.import_elements(b, VectorOperation::insert);
- for (unsigned int i = 0; i < size; ++i)
- AssertThrow(2. * read_write_2[i] + read_write_1[i] == read_write_3[i],
- ExcMessage("Problem in operator +=."));
-
- b -= c;
- read_write_3.import_elements(b, VectorOperation::insert);
- for (unsigned int i = 0; i < size; ++i)
- AssertThrow(1.5 * read_write_2[i] + read_write_1[i] == read_write_3[i],
- ExcMessage("Problem in operator -=."));
-
- b.import_elements(read_write_1, VectorOperation::insert);
- c.import_elements(read_write_1, VectorOperation::insert);
- const double val = b * c;
- AssertThrow(val == 328350., ExcMessage("Problem in operator *."));
-
- b = 0.;
- read_write_3.import_elements(b, VectorOperation::insert);
- for (unsigned int i = 0; i < size; ++i)
- AssertThrow(read_write_3[i] == 0., ExcMessage("Problem in operator =."));
-}
-
-int
-main(int argc, char **argv)
-{
- initlog();
- deallog.depth_console(0);
-
- init_cuda();
-
- test();
-
- deallog << "OK" << std::endl;
-
- return 0;
-}
+++ /dev/null
-
-DEAL::OK
+++ /dev/null
-// ------------------------------------------------------------------------
-//
-// SPDX-License-Identifier: LGPL-2.1-or-later
-// Copyright (C) 2016 - 2023 by the deal.II authors
-//
-// This file is part of the deal.II library.
-//
-// Part of the source code is dual licensed under Apache-2.0 WITH
-// LLVM-exception OR LGPL-2.1-or-later. Detailed license information
-// governing the source code and code contributions can be found in
-// LICENSE.md and CONTRIBUTING.md at the top level directory of deal.II.
-//
-// ------------------------------------------------------------------------
-
-
-#include <deal.II/base/utilities.h>
-
-#include <deal.II/lac/cuda_vector.h>
-#include <deal.II/lac/read_write_vector.h>
-
-#include <fstream>
-#include <iostream>
-#include <vector>
-
-#include "../tests.h"
-
-// Check LinearAlgebra::CUDAWrappers::Vector add and sadd.
-
-void
-test()
-{
- const unsigned int size = 100;
- LinearAlgebra::CUDAWrappers::Vector<double> a(size);
- LinearAlgebra::CUDAWrappers::Vector<double> b(size);
- LinearAlgebra::CUDAWrappers::Vector<double> c(size);
-
- LinearAlgebra::ReadWriteVector<double> read_write_1(size);
- LinearAlgebra::ReadWriteVector<double> read_write_2(size);
- LinearAlgebra::ReadWriteVector<double> read_write_3(size);
-
- for (unsigned int i = 0; i < size; ++i)
- {
- read_write_1[i] = i;
- read_write_2[i] = 5. + i;
- }
-
- a.import_elements(read_write_1, VectorOperation::insert);
- b.import_elements(read_write_2, VectorOperation::insert);
- c.import_elements(read_write_2, VectorOperation::insert);
-
- a.add(1.);
- read_write_3.import_elements(a, VectorOperation::insert);
- for (unsigned int i = 0; i < size; ++i)
- AssertThrow(1. + read_write_1[i] == read_write_3[i],
- ExcMessage("Problem in add(scalar)."));
-
- a.add(2., b);
- read_write_3.import_elements(a, VectorOperation::insert);
- for (unsigned int i = 0; i < size; ++i)
- AssertThrow(1. + read_write_1[i] + 2. * read_write_2[i] == read_write_3[i],
- ExcMessage("Problem in add(scalar,Vector)."));
-
- LinearAlgebra::CUDAWrappers::Vector<double> d(a);
- a.add(2., b, 3., d);
- read_write_3.import_elements(a, VectorOperation::insert);
- for (unsigned int i = 0; i < size; ++i)
- AssertThrow(4. + 4. * read_write_1[i] + 10. * read_write_2[i] ==
- read_write_3[i],
- ExcMessage("Problem in add(scalar,Vector,scalar,Vector)."));
-
- a.import_elements(read_write_1, VectorOperation::insert);
- a.sadd(3., 2., c);
- read_write_3.import_elements(a, VectorOperation::insert);
- for (unsigned int i = 0; i < size; ++i)
- AssertThrow(3. * read_write_1[i] + 2. * read_write_2[i] == read_write_3[i],
- ExcMessage("Problem in sadd(scalar,scalar,Vector)."));
-
- a.import_elements(read_write_1, VectorOperation::insert);
- a.scale(b);
- read_write_3.import_elements(a, VectorOperation::insert);
- for (unsigned int i = 0; i < size; ++i)
- AssertThrow(read_write_1[i] * read_write_2[i] == read_write_3[i],
- ExcMessage("Problem in scale."));
-
- a.equ(2., c);
- read_write_3.import_elements(a, VectorOperation::insert);
- for (unsigned int i = 0; i < size; ++i)
- AssertThrow(2. * read_write_2[i] == read_write_3[i],
- ExcMessage("Problem in equ."));
-
- AssertThrow(b.mean_value() == 54.50, ExcMessage("Problem in mean_value."));
-
- AssertThrow(b.l1_norm() == 5450., ExcMessage("Problem in l1_norm."));
-
- const double eps = 1e-3;
- AssertThrow(std::fabs(b.l2_norm() - 616.725222) < eps,
- ExcMessage("Problem in l2_norm"));
-
- AssertThrow(b.linfty_norm() == 104., ExcMessage("Problem in linfty_norm."));
-
- a.import_elements(read_write_1, VectorOperation::insert);
- const double val = a.add_and_dot(2., a, b);
- AssertThrow(val == 1059300., ExcMessage("Problem in add_and_dot"));
-}
-
-
-int
-main(int argc, char **argv)
-{
- initlog();
- deallog.depth_console(0);
-
- init_cuda();
-
- test();
-
- deallog << "OK" << std::endl;
-
- return 0;
-}
+++ /dev/null
-
-DEAL::OK
+++ /dev/null
-// ------------------------------------------------------------------------
-//
-// SPDX-License-Identifier: LGPL-2.1-or-later
-// Copyright (C) 2018 - 2023 by the deal.II authors
-//
-// This file is part of the deal.II library.
-//
-// Part of the source code is dual licensed under Apache-2.0 WITH
-// LLVM-exception OR LGPL-2.1-or-later. Detailed license information
-// governing the source code and code contributions can be found in
-// LICENSE.md and CONTRIBUTING.md at the top level directory of deal.II.
-//
-// ------------------------------------------------------------------------
-
-#include <deal.II/lac/cuda_vector.h>
-#include <deal.II/lac/read_write_vector.h>
-
-#include "../tests.h"
-
-// Check that reinit correctly set all the entries of the vector to zero
-
-void
-test()
-{
- const unsigned int size = 100;
- LinearAlgebra::CUDAWrappers::Vector<double> a(size);
- LinearAlgebra::ReadWriteVector<double> read_write(size);
- for (unsigned int i = 0; i < size; ++i)
- read_write[i] = i;
- a.import_elements(read_write, VectorOperation::insert);
-
- a.reinit(size / 2);
- AssertThrow(a.l1_norm() == 0., ExcMessage("reinit did not zero the entry"));
-}
-
-
-int
-main(int argc, char **argv)
-{
- initlog();
- deallog.depth_console(0);
-
- init_cuda();
-
- test();
-
- deallog << "OK" << std::endl;
-
- return 0;
-}
+++ /dev/null
-
-DEAL::OK
+++ /dev/null
-// ------------------------------------------------------------------------
-//
-// SPDX-License-Identifier: LGPL-2.1-or-later
-// Copyright (C) 2015 - 2023 by the deal.II authors
-//
-// This file is part of the deal.II library.
-//
-// Part of the source code is dual licensed under Apache-2.0 WITH
-// LLVM-exception OR LGPL-2.1-or-later. Detailed license information
-// governing the source code and code contributions can be found in
-// LICENSE.md and CONTRIBUTING.md at the top level directory of deal.II.
-//
-// ------------------------------------------------------------------------
-
-
-// Check LinearAlgebra::CUDAWrappers::Vector::print()
-
-#include <deal.II/base/utilities.h>
-
-#include <deal.II/lac/cuda_vector.h>
-#include <deal.II/lac/read_write_vector.h>
-
-#include <fstream>
-#include <iostream>
-
-#include "../tests.h"
-
-void
-test()
-{
- const unsigned int size = 100;
- LinearAlgebra::CUDAWrappers::Vector<double> cuda_vector(size);
-
- LinearAlgebra::ReadWriteVector<double> read_write_1(size);
- for (unsigned int i = 0; i < size; ++i)
- {
- read_write_1[i] = i;
- }
-
- cuda_vector.import_elements(read_write_1, VectorOperation::insert);
-
- cuda_vector.print(deallog.get_file_stream());
-}
-
-int
-main(int argc, char **argv)
-{
- initlog();
- deallog.depth_console(0);
-
- init_cuda();
-
- test();
-
- deallog << "OK" << std::endl;
-
- return 0;
-}
+++ /dev/null
-
-IndexSet: {[0,99]}
-
-0.00e+00
-1.00e+00
-2.00e+00
-3.00e+00
-4.00e+00
-5.00e+00
-6.00e+00
-7.00e+00
-8.00e+00
-9.00e+00
-1.00e+01
-1.10e+01
-1.20e+01
-1.30e+01
-1.40e+01
-1.50e+01
-1.60e+01
-1.70e+01
-1.80e+01
-1.90e+01
-2.00e+01
-2.10e+01
-2.20e+01
-2.30e+01
-2.40e+01
-2.50e+01
-2.60e+01
-2.70e+01
-2.80e+01
-2.90e+01
-3.00e+01
-3.10e+01
-3.20e+01
-3.30e+01
-3.40e+01
-3.50e+01
-3.60e+01
-3.70e+01
-3.80e+01
-3.90e+01
-4.00e+01
-4.10e+01
-4.20e+01
-4.30e+01
-4.40e+01
-4.50e+01
-4.60e+01
-4.70e+01
-4.80e+01
-4.90e+01
-5.00e+01
-5.10e+01
-5.20e+01
-5.30e+01
-5.40e+01
-5.50e+01
-5.60e+01
-5.70e+01
-5.80e+01
-5.90e+01
-6.00e+01
-6.10e+01
-6.20e+01
-6.30e+01
-6.40e+01
-6.50e+01
-6.60e+01
-6.70e+01
-6.80e+01
-6.90e+01
-7.00e+01
-7.10e+01
-7.20e+01
-7.30e+01
-7.40e+01
-7.50e+01
-7.60e+01
-7.70e+01
-7.80e+01
-7.90e+01
-8.00e+01
-8.10e+01
-8.20e+01
-8.30e+01
-8.40e+01
-8.50e+01
-8.60e+01
-8.70e+01
-8.80e+01
-8.90e+01
-9.00e+01
-9.10e+01
-9.20e+01
-9.30e+01
-9.40e+01
-9.50e+01
-9.60e+01
-9.70e+01
-9.80e+01
-9.90e+01
-DEAL::OK
+++ /dev/null
-// ------------------------------------------------------------------------
-//
-// SPDX-License-Identifier: LGPL-2.1-or-later
-// Copyright (C) 2019 - 2023 by the deal.II authors
-//
-// This file is part of the deal.II library.
-//
-// Part of the source code is dual licensed under Apache-2.0 WITH
-// LLVM-exception OR LGPL-2.1-or-later. Detailed license information
-// governing the source code and code contributions can be found in
-// LICENSE.md and CONTRIBUTING.md at the top level directory of deal.II.
-//
-// ------------------------------------------------------------------------
-
-
-#include <deal.II/base/utilities.h>
-
-#include <deal.II/lac/cuda_vector.h>
-#include <deal.II/lac/read_write_vector.h>
-#include <deal.II/lac/vector.h>
-
-#include <fstream>
-#include <iostream>
-#include <vector>
-
-#include "../tests.h"
-
-// There was a bug where add_and_dot would give the wrong result if the size of
-// the vectors was greater than BLOCK_SIZE*CHUNK_SIZE.
-
-void
-test()
-{
- const unsigned int size = 4100;
- LinearAlgebra::CUDAWrappers::Vector<double> a(size);
- LinearAlgebra::CUDAWrappers::Vector<double> b(size);
- Vector<double> a_host(size);
- Vector<double> b_host(size);
-
- LinearAlgebra::ReadWriteVector<double> read_write_1(size);
- LinearAlgebra::ReadWriteVector<double> read_write_2(size);
-
- for (unsigned int i = 0; i < size; ++i)
- {
- read_write_1[i] = i;
- read_write_2[i] = 5. + i;
- a_host[i] = i;
- b_host[i] = 5. + i;
- }
-
- a.import_elements(read_write_1, VectorOperation::insert);
- b.import_elements(read_write_2, VectorOperation::insert);
- AssertThrow(a.add_and_dot(2., a, b) == a_host.add_and_dot(2., a_host, b_host),
- ExcMessage("Problem in add_and_dot"));
-}
-
-
-int
-main(int argc, char **argv)
-{
- initlog();
- deallog.depth_console(0);
-
- init_cuda();
-
- test();
-
- deallog << "OK" << std::endl;
-
- return 0;
-}
+++ /dev/null
-
-DEAL::OK
+++ /dev/null
-// ------------------------------------------------------------------------
-//
-// SPDX-License-Identifier: LGPL-2.1-or-later
-// Copyright (C) 2018 - 2023 by the deal.II authors
-//
-// This file is part of the deal.II library.
-//
-// Part of the source code is dual licensed under Apache-2.0 WITH
-// LLVM-exception OR LGPL-2.1-or-later. Detailed license information
-// governing the source code and code contributions can be found in
-// LICENSE.md and CONTRIBUTING.md at the top level directory of deal.II.
-//
-// ------------------------------------------------------------------------
-
-// Check that dealii::SolverCG works with CUDAWrappers::SparseMatrix
-// and PreconditionIC
-
-#include <deal.II/base/cuda.h>
-#include <deal.II/base/exceptions.h>
-
-#include <deal.II/lac/cuda_precondition.h>
-#include <deal.II/lac/cuda_sparse_matrix.h>
-#include <deal.II/lac/read_write_vector.h>
-#include <deal.II/lac/solver_cg.h>
-#include <deal.II/lac/solver_control.h>
-
-#include "../tests.h"
-
-#include "../testmatrix.h"
-
-template <typename Number>
-void
-test(Utilities::CUDA::Handle &cuda_handle)
-{
- // Build the sparse matrix on the host
- const unsigned int problem_size = 10;
- unsigned int size = (problem_size - 1) * (problem_size - 1);
- FDMatrix testproblem(problem_size, problem_size);
- SparsityPattern structure(size, size, 5);
- SparseMatrix<Number> A;
- testproblem.five_point_structure(structure);
- structure.compress();
- A.reinit(structure);
- testproblem.five_point(A);
-
- // Solve on the device
- CUDAWrappers::SparseMatrix<Number> A_dev(cuda_handle, A);
- LinearAlgebra::CUDAWrappers::Vector<Number> sol_dev(size);
- LinearAlgebra::CUDAWrappers::Vector<Number> rhs_dev(size);
- LinearAlgebra::ReadWriteVector<Number> rw_vector(size);
- for (unsigned int i = 0; i < size; ++i)
- rw_vector[i] = static_cast<Number>(i);
- rhs_dev.import_elements(rw_vector, VectorOperation::insert);
- const Number tolerance = 1000. * std::numeric_limits<Number>::epsilon();
- SolverControl control(100, tolerance);
- SolverCG<LinearAlgebra::CUDAWrappers::Vector<Number>> cg_dev(control);
-
- CUDAWrappers::PreconditionIC<Number> prec_ic(cuda_handle);
- prec_ic.initialize(A_dev);
-
- cg_dev.solve(A_dev, sol_dev, rhs_dev, prec_ic);
-
- // Check the result
- LinearAlgebra::CUDAWrappers::Vector<Number> residual(size);
- A_dev.residual(residual, sol_dev, rhs_dev);
- Assert(residual.l2_norm() < 20 * tolerance, ExcInternalError());
- deallog << "OK" << std::endl;
-}
-
-int
-main()
-{
- initlog();
- deallog << std::setprecision(10);
- deallog.depth_console(0);
-
- init_cuda();
-
- Utilities::CUDA::Handle cuda_handle;
- deallog << "Testing float" << std::endl;
- test<float>(cuda_handle);
- deallog << "Testing double" << std::endl;
- test<double>(cuda_handle);
-
- deallog << "OK" << std::endl;
-
- return 0;
-}
+++ /dev/null
-
-DEAL::Testing float
-DEAL:cg::Starting value 416.9891968
-DEAL:cg::Convergence step 11 value 3.993874634e-05
-DEAL::OK
-DEAL::Testing double
-DEAL:cg::Starting value 416.9892085
-DEAL:cg::Convergence step 20 value 9.834412497e-14
-DEAL::OK
-DEAL::OK
+++ /dev/null
-// ------------------------------------------------------------------------
-//
-// SPDX-License-Identifier: LGPL-2.1-or-later
-// Copyright (C) 2018 - 2023 by the deal.II authors
-//
-// This file is part of the deal.II library.
-//
-// Part of the source code is dual licensed under Apache-2.0 WITH
-// LLVM-exception OR LGPL-2.1-or-later. Detailed license information
-// governing the source code and code contributions can be found in
-// LICENSE.md and CONTRIBUTING.md at the top level directory of deal.II.
-//
-// ------------------------------------------------------------------------
-
-// Check that dealii::SolverCG works with CUDAWrappers::SparseMatrix
-// and PreconditionILU
-
-#include <deal.II/base/cuda.h>
-#include <deal.II/base/exceptions.h>
-
-#include <deal.II/lac/cuda_precondition.h>
-#include <deal.II/lac/cuda_sparse_matrix.h>
-#include <deal.II/lac/read_write_vector.h>
-#include <deal.II/lac/solver_cg.h>
-#include <deal.II/lac/solver_control.h>
-
-#include "../tests.h"
-
-#include "../testmatrix.h"
-
-template <typename Number>
-void
-test(Utilities::CUDA::Handle &cuda_handle)
-{
- // Build the sparse matrix on the host
- const unsigned int problem_size = 10;
- unsigned int size = (problem_size - 1) * (problem_size - 1);
- FDMatrix testproblem(problem_size, problem_size);
- SparsityPattern structure(size, size, 5);
- SparseMatrix<Number> A;
- testproblem.five_point_structure(structure);
- structure.compress();
- A.reinit(structure);
- testproblem.five_point(A);
-
- // Solve on the device
- CUDAWrappers::SparseMatrix<Number> A_dev(cuda_handle, A);
- LinearAlgebra::CUDAWrappers::Vector<Number> sol_dev(size);
- LinearAlgebra::CUDAWrappers::Vector<Number> rhs_dev(size);
- LinearAlgebra::ReadWriteVector<Number> rw_vector(size);
- for (unsigned int i = 0; i < size; ++i)
- rw_vector[i] = static_cast<Number>(i);
- rhs_dev.import_elements(rw_vector, VectorOperation::insert);
- const Number tolerance = 1000. * std::numeric_limits<Number>::epsilon();
- SolverControl control(100, tolerance);
- SolverCG<LinearAlgebra::CUDAWrappers::Vector<Number>> cg_dev(control);
-
- CUDAWrappers::PreconditionILU<Number> prec_ilu(cuda_handle);
- prec_ilu.initialize(A_dev);
-
- cg_dev.solve(A_dev, sol_dev, rhs_dev, prec_ilu);
-
- // Check the result
- LinearAlgebra::CUDAWrappers::Vector<Number> residual(size);
- A_dev.residual(residual, sol_dev, rhs_dev);
- Assert(residual.l2_norm() < 20 * tolerance, ExcInternalError());
- deallog << "OK" << std::endl;
-}
-
-int
-main()
-{
- initlog();
- deallog << std::setprecision(10);
- deallog.depth_console(0);
-
- init_cuda();
-
- Utilities::CUDA::Handle cuda_handle;
- deallog << "Testing float" << std::endl;
- test<float>(cuda_handle);
- deallog << "Testing double" << std::endl;
- test<double>(cuda_handle);
-
- deallog << "OK" << std::endl;
-
- return 0;
-}
+++ /dev/null
-
-DEAL::Testing float
-DEAL:cg::Starting value 416.9891968
-DEAL:cg::Convergence step 11 value 3.993944847e-05
-DEAL::OK
-DEAL::Testing double
-DEAL:cg::Starting value 416.9892085
-DEAL:cg::Convergence step 20 value 9.834484941e-14
-DEAL::OK
-DEAL::OK
+++ /dev/null
-// ------------------------------------------------------------------------
-//
-// SPDX-License-Identifier: LGPL-2.1-or-later
-// Copyright (C) 2018 - 2023 by the deal.II authors
-//
-// This file is part of the deal.II library.
-//
-// Part of the source code is dual licensed under Apache-2.0 WITH
-// LLVM-exception OR LGPL-2.1-or-later. Detailed license information
-// governing the source code and code contributions can be found in
-// LICENSE.md and CONTRIBUTING.md at the top level directory of deal.II.
-//
-// ------------------------------------------------------------------------
-
-// Check that dealii::SolverCG works with CUDAWrappers::SparseMatrix
-
-#include <deal.II/base/cuda.h>
-#include <deal.II/base/exceptions.h>
-
-#include <deal.II/lac/cuda_sparse_matrix.h>
-#include <deal.II/lac/precondition.h>
-#include <deal.II/lac/read_write_vector.h>
-#include <deal.II/lac/solver_cg.h>
-#include <deal.II/lac/solver_control.h>
-#include <deal.II/lac/vector.h>
-
-#include "../tests.h"
-
-#include "../testmatrix.h"
-
-void
-test(Utilities::CUDA::Handle &cuda_handle)
-{
- // Build the sparse matrix on the host
- const unsigned int problem_size = 10;
- unsigned int size = (problem_size - 1) * (problem_size - 1);
- FDMatrix testproblem(problem_size, problem_size);
- SparsityPattern structure(size, size, 5);
- SparseMatrix<double> A;
- testproblem.five_point_structure(structure);
- structure.compress();
- A.reinit(structure);
- testproblem.five_point(A);
-
- // Solve on the host
- PreconditionIdentity prec_no;
- SolverControl control(100, 1.e-10);
- SolverCG<> cg_host(control);
- Vector<double> sol_host(size);
- Vector<double> rhs_host(size);
- for (unsigned int i = 0; i < size; ++i)
- rhs_host[i] = static_cast<double>(i);
- cg_host.solve(A, sol_host, rhs_host, prec_no);
-
- // Solve on the device
- CUDAWrappers::SparseMatrix<double> A_dev(cuda_handle, A);
- LinearAlgebra::CUDAWrappers::Vector<double> sol_dev(size);
- LinearAlgebra::CUDAWrappers::Vector<double> rhs_dev(size);
- LinearAlgebra::ReadWriteVector<double> rw_vector(size);
- for (unsigned int i = 0; i < size; ++i)
- rw_vector[i] = static_cast<double>(i);
- rhs_dev.import_elements(rw_vector, VectorOperation::insert);
- SolverCG<LinearAlgebra::CUDAWrappers::Vector<double>> cg_dev(control);
- cg_dev.solve(A_dev, sol_dev, rhs_dev, prec_no);
-
- // Check the result
- rw_vector.import_elements(sol_dev, VectorOperation::insert);
- for (unsigned int i = 0; i < size; ++i)
- AssertThrow(std::fabs(rw_vector[i] - sol_host[i]) < 1e-8,
- ExcInternalError());
-}
-
-int
-main()
-{
- initlog();
- deallog.depth_console(0);
-
- init_cuda();
-
- Utilities::CUDA::Handle cuda_handle;
- test(cuda_handle);
-
- deallog << "OK" << std::endl;
-
- return 0;
-}
+++ /dev/null
-
-DEAL:cg::Starting value 416.989
-DEAL:cg::Convergence step 31 value 8.71925e-12
-DEAL:cg::Starting value 416.989
-DEAL:cg::Convergence step 31 value 8.71925e-12
-DEAL::OK
+++ /dev/null
-// ------------------------------------------------------------------------
-//
-// SPDX-License-Identifier: LGPL-2.1-or-later
-// Copyright (C) 2018 - 2023 by the deal.II authors
-//
-// This file is part of the deal.II library.
-//
-// Part of the source code is dual licensed under Apache-2.0 WITH
-// LLVM-exception OR LGPL-2.1-or-later. Detailed license information
-// governing the source code and code contributions can be found in
-// LICENSE.md and CONTRIBUTING.md at the top level directory of deal.II.
-//
-// ------------------------------------------------------------------------
-
-// Check that CUDA direct solvers work
-
-#include <deal.II/base/cuda.h>
-
-#include <deal.II/lac/cuda_solver_direct.h>
-#include <deal.II/lac/cuda_sparse_matrix.h>
-#include <deal.II/lac/cuda_vector.h>
-#include <deal.II/lac/read_write_vector.h>
-#include <deal.II/lac/solver_control.h>
-#include <deal.II/lac/vector.h>
-
-#include "../tests.h"
-
-#include "../testmatrix.h"
-
-
-void
-test(Utilities::CUDA::Handle &cuda_handle)
-{
- // Create the matrix on the host.
- dealii::SparsityPattern sparsity_pattern;
- dealii::SparseMatrix<double> matrix;
- const unsigned int size = 30;
- std::vector<std::vector<unsigned int>> column_indices(size);
- for (unsigned int i = 0; i < size; ++i)
- {
- unsigned int j_max = std::min(size, i + 2);
- unsigned int j_min = (i == 0) ? 0 : i - 1;
- for (unsigned int j = j_min; j < j_max; ++j)
- column_indices[i].emplace_back(j);
- }
- sparsity_pattern.copy_from(size,
- size,
- column_indices.begin(),
- column_indices.end());
- matrix.reinit(sparsity_pattern);
- for (unsigned int i = 0; i < size; ++i)
- {
- unsigned int j_max = std::min(size - 1, i + 1);
- unsigned int j_min = (i == 0) ? 0 : i - 1;
- matrix.set(i, j_min, -1.);
- matrix.set(i, j_max, -1.);
- matrix.set(i, i, 4.);
- }
-
- // Generate a random solution and then compute the rhs
- dealii::Vector<double> sol_ref(size);
- for (auto &val : sol_ref)
- val = random_value(5., 15.);
-
- dealii::Vector<double> rhs(size);
- matrix.vmult(rhs, sol_ref);
-
- // Move the matrix and the rhs to the host
- CUDAWrappers::SparseMatrix<double> matrix_dev(cuda_handle, matrix);
-
- LinearAlgebra::CUDAWrappers::Vector<double> rhs_dev(size);
- LinearAlgebra::ReadWriteVector<double> rhs_host(size);
- std::copy(rhs.begin(), rhs.end(), rhs_host.begin());
- rhs_dev.import_elements(rhs_host, VectorOperation::insert);
-
- LinearAlgebra::CUDAWrappers::Vector<double> solution_dev(size);
- const std::array<std::string, 3> solver_names{
- {"Cholesky", "LU_dense", "LU_host"}};
-
- for (auto solver_type : solver_names)
- {
- // Solve on the device
- CUDAWrappers::SolverDirect<double>::AdditionalData data(solver_type);
- SolverControl solver_control;
-
- CUDAWrappers::SolverDirect<double> solver(cuda_handle,
- solver_control,
- data);
- solver.solve(matrix_dev, solution_dev, rhs_dev);
-
- // Move the result back to the host
- LinearAlgebra::ReadWriteVector<double> solution_host(size);
- solution_host.import_elements(solution_dev, VectorOperation::insert);
-
- // Check the result
- for (unsigned int i = 0; i < size; ++i)
- AssertThrow(std::abs(solution_host[i] - sol_ref[i]) < 1e-12,
- ExcInternalError());
- deallog << solver_type << std::endl;
- }
-}
-
-int
-main()
-{
- initlog();
- deallog.depth_console(0);
-
- init_cuda();
-
- Utilities::CUDA::Handle cuda_handle;
- test(cuda_handle);
-
- deallog << "OK" << std::endl;
-
- return 0;
-}
+++ /dev/null
-
-DEAL::Starting value 0.00000
-DEAL::Convergence step 0 value 0.00000
-DEAL::Cholesky
-DEAL::Starting value 0.00000
-DEAL::Convergence step 0 value 0.00000
-DEAL::LU_dense
-DEAL::Starting value 0.00000
-DEAL::Convergence step 0 value 0.00000
-DEAL::LU_host
-DEAL::OK
+++ /dev/null
-// ------------------------------------------------------------------------
-//
-// SPDX-License-Identifier: LGPL-2.1-or-later
-// Copyright (C) 2018 - 2023 by the deal.II authors
-//
-// This file is part of the deal.II library.
-//
-// Part of the source code is dual licensed under Apache-2.0 WITH
-// LLVM-exception OR LGPL-2.1-or-later. Detailed license information
-// governing the source code and code contributions can be found in
-// LICENSE.md and CONTRIBUTING.md at the top level directory of deal.II.
-//
-// ------------------------------------------------------------------------
-
-// Check that dealii::SolverGMRES works with CUDAWrappers::SparseMatrix
-
-#include <deal.II/base/cuda.h>
-#include <deal.II/base/exceptions.h>
-
-#include <deal.II/lac/cuda_sparse_matrix.h>
-#include <deal.II/lac/precondition.h>
-#include <deal.II/lac/read_write_vector.h>
-#include <deal.II/lac/solver_control.h>
-#include <deal.II/lac/solver_gmres.h>
-#include <deal.II/lac/vector.h>
-
-#include "../tests.h"
-
-#include "../testmatrix.h"
-
-void
-test(Utilities::CUDA::Handle &cuda_handle)
-{
- // Build the sparse matrix on the host
- const unsigned int problem_size = 10;
- unsigned int size = (problem_size - 1) * (problem_size - 1);
- FDMatrix testproblem(problem_size, problem_size);
- SparsityPattern structure(size, size, 5);
- SparseMatrix<double> A;
- testproblem.five_point_structure(structure);
- structure.compress();
- A.reinit(structure);
- testproblem.five_point(A);
-
- // Solve on the host
- PreconditionIdentity prec_no;
- SolverControl control(100, 1.e-10);
- SolverGMRES<> cg_host(control);
- Vector<double> sol_host(size);
- Vector<double> rhs_host(size);
- for (unsigned int i = 0; i < size; ++i)
- rhs_host[i] = static_cast<double>(i);
- cg_host.solve(A, sol_host, rhs_host, prec_no);
-
- // Solve on the device
- CUDAWrappers::SparseMatrix<double> A_dev(cuda_handle, A);
- LinearAlgebra::CUDAWrappers::Vector<double> sol_dev(size);
- LinearAlgebra::CUDAWrappers::Vector<double> rhs_dev(size);
- LinearAlgebra::ReadWriteVector<double> rw_vector(size);
- for (unsigned int i = 0; i < size; ++i)
- rw_vector[i] = static_cast<double>(i);
- rhs_dev.import_elements(rw_vector, VectorOperation::insert);
- SolverGMRES<LinearAlgebra::CUDAWrappers::Vector<double>> cg_dev(control);
- cg_dev.solve(A_dev, sol_dev, rhs_dev, prec_no);
-
- // Check the result
- rw_vector.import_elements(sol_dev, VectorOperation::insert);
- for (unsigned int i = 0; i < size; ++i)
- AssertThrow(std::fabs(rw_vector[i] - sol_host[i]) < 1e-8,
- ExcInternalError());
-}
-
-int
-main()
-{
- initlog();
- deallog.depth_console(0);
-
- init_cuda();
-
- Utilities::CUDA::Handle cuda_handle;
- test(cuda_handle);
-
- deallog << "OK" << std::endl;
-
- return 0;
-}
+++ /dev/null
-
-DEAL:GMRES::Starting value 416.989
-DEAL:GMRES::Convergence step 32 value 4.50651e-11
-DEAL:GMRES::Starting value 416.989
-DEAL:GMRES::Convergence step 32 value 4.50477e-11
-DEAL::OK
+++ /dev/null
-// ------------------------------------------------------------------------
-//
-// SPDX-License-Identifier: LGPL-2.1-or-later
-// Copyright (C) 2018 - 2023 by the deal.II authors
-//
-// This file is part of the deal.II library.
-//
-// Part of the source code is dual licensed under Apache-2.0 WITH
-// LLVM-exception OR LGPL-2.1-or-later. Detailed license information
-// governing the source code and code contributions can be found in
-// LICENSE.md and CONTRIBUTING.md at the top level directory of deal.II.
-//
-// ------------------------------------------------------------------------
-
-// Check that dealii::SolverBicgstab works with CUDAWrappers::SparseMatrix
-
-#include <deal.II/base/cuda.h>
-#include <deal.II/base/exceptions.h>
-
-#include <deal.II/lac/cuda_sparse_matrix.h>
-#include <deal.II/lac/precondition.h>
-#include <deal.II/lac/read_write_vector.h>
-#include <deal.II/lac/solver_bicgstab.h>
-#include <deal.II/lac/solver_control.h>
-#include <deal.II/lac/vector.h>
-
-#include "../tests.h"
-
-#include "../testmatrix.h"
-
-void
-test(Utilities::CUDA::Handle &cuda_handle)
-{
- // Build the sparse matrix on the host
- const unsigned int problem_size = 10;
- unsigned int size = (problem_size - 1) * (problem_size - 1);
- FDMatrix testproblem(problem_size, problem_size);
- SparsityPattern structure(size, size, 5);
- SparseMatrix<double> A;
- testproblem.five_point_structure(structure);
- structure.compress();
- A.reinit(structure);
- testproblem.five_point(A);
-
- // Solve on the host
- PreconditionIdentity prec_no;
- SolverControl control(100, 1.e-10);
- SolverBicgstab<> bicgstab_host(control);
- Vector<double> sol_host(size);
- Vector<double> rhs_host(size);
- for (unsigned int i = 0; i < size; ++i)
- rhs_host[i] = static_cast<double>(i);
- bicgstab_host.solve(A, sol_host, rhs_host, prec_no);
-
- // Solve on the device
- CUDAWrappers::SparseMatrix<double> A_dev(cuda_handle, A);
- LinearAlgebra::CUDAWrappers::Vector<double> sol_dev(size);
- LinearAlgebra::CUDAWrappers::Vector<double> rhs_dev(size);
- LinearAlgebra::ReadWriteVector<double> rw_vector(size);
- for (unsigned int i = 0; i < size; ++i)
- rw_vector[i] = static_cast<double>(i);
- rhs_dev.import_elements(rw_vector, VectorOperation::insert);
- SolverBicgstab<LinearAlgebra::CUDAWrappers::Vector<double>> bicgstab_dev(
- control);
- bicgstab_dev.solve(A_dev, sol_dev, rhs_dev, prec_no);
-
- // Check the result
- rw_vector.import_elements(sol_dev, VectorOperation::insert);
- for (unsigned int i = 0; i < size; ++i)
- AssertThrow(std::fabs(rw_vector[i] - sol_host[i]) < 1e-8,
- ExcInternalError());
-}
-
-int
-main()
-{
- initlog();
- deallog.depth_console(0);
-
- init_cuda();
-
- Utilities::CUDA::Handle cuda_handle;
- test(cuda_handle);
-
- deallog << "OK" << std::endl;
-
- return 0;
-}
+++ /dev/null
-
-DEAL:Bicgstab::Starting value 416.989
-DEAL:Bicgstab::Convergence step 23 value 1.39578e-11
-DEAL:Bicgstab::Starting value 416.989
-DEAL:Bicgstab::Convergence step 23 value 1.39578e-11
-DEAL::OK
+++ /dev/null
-// ------------------------------------------------------------------------
-//
-// SPDX-License-Identifier: LGPL-2.1-or-later
-// Copyright (C) 2018 - 2023 by the deal.II authors
-//
-// This file is part of the deal.II library.
-//
-// Part of the source code is dual licensed under Apache-2.0 WITH
-// LLVM-exception OR LGPL-2.1-or-later. Detailed license information
-// governing the source code and code contributions can be found in
-// LICENSE.md and CONTRIBUTING.md at the top level directory of deal.II.
-//
-// ------------------------------------------------------------------------
-
-// Check that dealii::SolverFGMRES works with CUDAWrappers::SparseMatrix
-
-#include <deal.II/base/cuda.h>
-#include <deal.II/base/exceptions.h>
-
-#include <deal.II/lac/cuda_sparse_matrix.h>
-#include <deal.II/lac/precondition.h>
-#include <deal.II/lac/read_write_vector.h>
-#include <deal.II/lac/solver_control.h>
-#include <deal.II/lac/solver_gmres.h>
-#include <deal.II/lac/vector.h>
-
-#include "../tests.h"
-
-#include "../testmatrix.h"
-
-void
-test(Utilities::CUDA::Handle &cuda_handle)
-{
- // Build the sparse matrix on the host
- const unsigned int problem_size = 10;
- unsigned int size = (problem_size - 1) * (problem_size - 1);
- FDMatrix testproblem(problem_size, problem_size);
- SparsityPattern structure(size, size, 5);
- SparseMatrix<double> A;
- testproblem.five_point_structure(structure);
- structure.compress();
- A.reinit(structure);
- testproblem.five_point(A);
-
- // Solve on the host
- PreconditionIdentity prec_no;
- SolverControl control(100, 1.e-10);
- SolverFGMRES<> fgmres_host(control);
- Vector<double> sol_host(size);
- Vector<double> rhs_host(size);
- for (unsigned int i = 0; i < size; ++i)
- rhs_host[i] = static_cast<double>(i);
- fgmres_host.solve(A, sol_host, rhs_host, prec_no);
-
- // Solve on the device
- CUDAWrappers::SparseMatrix<double> A_dev(cuda_handle, A);
- LinearAlgebra::CUDAWrappers::Vector<double> sol_dev(size);
- LinearAlgebra::CUDAWrappers::Vector<double> rhs_dev(size);
- LinearAlgebra::ReadWriteVector<double> rw_vector(size);
- for (unsigned int i = 0; i < size; ++i)
- rw_vector[i] = static_cast<double>(i);
- rhs_dev.import_elements(rw_vector, VectorOperation::insert);
- SolverFGMRES<LinearAlgebra::CUDAWrappers::Vector<double>> fgmres_dev(control);
- fgmres_dev.solve(A_dev, sol_dev, rhs_dev, prec_no);
-
- // Check the result
- rw_vector.import_elements(sol_dev, VectorOperation::insert);
- for (unsigned int i = 0; i < size; ++i)
- AssertThrow(std::fabs(rw_vector[i] - sol_host[i]) < 1e-8,
- ExcInternalError());
-}
-
-int
-main()
-{
- initlog();
- deallog.depth_console(0);
-
- init_cuda();
-
- Utilities::CUDA::Handle cuda_handle;
- test(cuda_handle);
-
- deallog << "OK" << std::endl;
-
- return 0;
-}
+++ /dev/null
-
-DEAL:FGMRES::Starting value 416.989
-DEAL:FGMRES::Convergence step 31 value 3.31663e-11
-DEAL:FGMRES::Starting value 416.989
-DEAL:FGMRES::Convergence step 31 value 3.31763e-11
-DEAL::OK
+++ /dev/null
-// ------------------------------------------------------------------------
-//
-// SPDX-License-Identifier: LGPL-2.1-or-later
-// Copyright (C) 2018 - 2023 by the deal.II authors
-//
-// This file is part of the deal.II library.
-//
-// Part of the source code is dual licensed under Apache-2.0 WITH
-// LLVM-exception OR LGPL-2.1-or-later. Detailed license information
-// governing the source code and code contributions can be found in
-// LICENSE.md and CONTRIBUTING.md at the top level directory of deal.II.
-//
-// ------------------------------------------------------------------------
-
-// Check that dealii::SolverFIRE works with CUDAWrappers::SparseMatrix
-
-#include <deal.II/base/cuda.h>
-#include <deal.II/base/exceptions.h>
-
-#include <deal.II/lac/cuda_sparse_matrix.h>
-#include <deal.II/lac/precondition.h>
-#include <deal.II/lac/read_write_vector.h>
-#include <deal.II/lac/solver_control.h>
-#include <deal.II/lac/solver_fire.h>
-#include <deal.II/lac/vector.h>
-
-#include "../tests.h"
-
-#include "../testmatrix.h"
-
-void
-test(Utilities::CUDA::Handle &cuda_handle)
-{
- // Build the sparse matrix on the host
- const unsigned int problem_size = 10;
- unsigned int size = (problem_size - 1) * (problem_size - 1);
- FDMatrix testproblem(problem_size, problem_size);
- SparsityPattern structure(size, size, 5);
- SparseMatrix<double> A;
- testproblem.five_point_structure(structure);
- structure.compress();
- A.reinit(structure);
- testproblem.five_point(A);
-
- // Solve on the host
- PreconditionIdentity prec_no;
- SolverControl control(10000, 1.e-3);
- SolverFIRE<> fire_host(control);
- Vector<double> sol_host(size);
- Vector<double> rhs_host(size);
- for (unsigned int i = 0; i < size; ++i)
- rhs_host[i] = static_cast<double>(i);
- fire_host.solve(A, sol_host, rhs_host, prec_no);
-
- // Solve on the device
- CUDAWrappers::SparseMatrix<double> A_dev(cuda_handle, A);
- LinearAlgebra::CUDAWrappers::Vector<double> sol_dev(size);
- LinearAlgebra::CUDAWrappers::Vector<double> rhs_dev(size);
- LinearAlgebra::ReadWriteVector<double> rw_vector(size);
- for (unsigned int i = 0; i < size; ++i)
- rw_vector[i] = static_cast<double>(i);
- rhs_dev.import_elements(rw_vector, VectorOperation::insert);
- SolverFIRE<LinearAlgebra::CUDAWrappers::Vector<double>> fire_dev(control);
- fire_dev.solve(A_dev, sol_dev, rhs_dev, prec_no);
-
- // Check the result
- rw_vector.import_elements(sol_dev, VectorOperation::insert);
- for (unsigned int i = 0; i < size; ++i)
- AssertThrow(std::fabs(rw_vector[i] - sol_host[i]) < 1e-8,
- ExcInternalError());
-}
-
-int
-main()
-{
- initlog();
- deallog.depth_console(0);
-
- init_cuda();
-
- Utilities::CUDA::Handle cuda_handle;
- test(cuda_handle);
-
- deallog << "OK" << std::endl;
-
- return 0;
-}
+++ /dev/null
-
-DEAL:FIRE::Starting value 173880.
-DEAL:FIRE::Convergence step 465 value 0.000927878
-DEAL:FIRE::Starting value 173880.
-DEAL:FIRE::Convergence step 465 value 0.000927878
-DEAL::OK
+++ /dev/null
-// ------------------------------------------------------------------------
-//
-// SPDX-License-Identifier: LGPL-2.1-or-later
-// Copyright (C) 2018 - 2023 by the deal.II authors
-//
-// This file is part of the deal.II library.
-//
-// Part of the source code is dual licensed under Apache-2.0 WITH
-// LLVM-exception OR LGPL-2.1-or-later. Detailed license information
-// governing the source code and code contributions can be found in
-// LICENSE.md and CONTRIBUTING.md at the top level directory of deal.II.
-//
-// ------------------------------------------------------------------------
-
-// Check that dealii::SolverMinRes works with CUDAWrappers::SparseMatrix
-
-#include <deal.II/base/cuda.h>
-#include <deal.II/base/exceptions.h>
-
-#include <deal.II/lac/cuda_sparse_matrix.h>
-#include <deal.II/lac/precondition.h>
-#include <deal.II/lac/read_write_vector.h>
-#include <deal.II/lac/solver_control.h>
-#include <deal.II/lac/solver_minres.h>
-#include <deal.II/lac/vector.h>
-
-#include "../tests.h"
-
-#include "../testmatrix.h"
-
-void
-test(Utilities::CUDA::Handle &cuda_handle)
-{
- // Build the sparse matrix on the host
- const unsigned int problem_size = 10;
- unsigned int size = (problem_size - 1) * (problem_size - 1);
- FDMatrix testproblem(problem_size, problem_size);
- SparsityPattern structure(size, size, 5);
- SparseMatrix<double> A;
- testproblem.five_point_structure(structure);
- structure.compress();
- A.reinit(structure);
- testproblem.five_point(A);
-
- // Solve on the host
- PreconditionIdentity prec_no;
- SolverControl control(100, 1.e-10);
- SolverMinRes<> minres_host(control);
- Vector<double> sol_host(size);
- Vector<double> rhs_host(size);
- for (unsigned int i = 0; i < size; ++i)
- rhs_host[i] = static_cast<double>(i);
- minres_host.solve(A, sol_host, rhs_host, prec_no);
-
- // Solve on the device
- CUDAWrappers::SparseMatrix<double> A_dev(cuda_handle, A);
- LinearAlgebra::CUDAWrappers::Vector<double> sol_dev(size);
- LinearAlgebra::CUDAWrappers::Vector<double> rhs_dev(size);
- LinearAlgebra::ReadWriteVector<double> rw_vector(size);
- for (unsigned int i = 0; i < size; ++i)
- rw_vector[i] = static_cast<double>(i);
- rhs_dev.import_elements(rw_vector, VectorOperation::insert);
- SolverMinRes<LinearAlgebra::CUDAWrappers::Vector<double>> minres_dev(control);
- minres_dev.solve(A_dev, sol_dev, rhs_dev, prec_no);
-
- // Check the result
- rw_vector.import_elements(sol_dev, VectorOperation::insert);
- for (unsigned int i = 0; i < size; ++i)
- AssertThrow(std::fabs(rw_vector[i] - sol_host[i]) < 1e-8,
- ExcInternalError());
-}
-
-int
-main()
-{
- initlog();
- deallog.depth_console(0);
-
- init_cuda();
-
- Utilities::CUDA::Handle cuda_handle;
- test(cuda_handle);
-
- deallog << "OK" << std::endl;
-
- return 0;
-}
+++ /dev/null
-
-DEAL:minres::Starting value 416.989
-DEAL:minres::Convergence step 31 value 8.71122e-12
-DEAL:minres::Starting value 416.989
-DEAL:minres::Convergence step 31 value 8.71119e-12
-DEAL::OK
+++ /dev/null
-// ------------------------------------------------------------------------
-//
-// SPDX-License-Identifier: LGPL-2.1-or-later
-// Copyright (C) 2018 - 2023 by the deal.II authors
-//
-// This file is part of the deal.II library.
-//
-// Part of the source code is dual licensed under Apache-2.0 WITH
-// LLVM-exception OR LGPL-2.1-or-later. Detailed license information
-// governing the source code and code contributions can be found in
-// LICENSE.md and CONTRIBUTING.md at the top level directory of deal.II.
-//
-// ------------------------------------------------------------------------
-
-// Check that dealii::SolverQMRS works with CUDAWrappers::SparseMatrix
-
-#include <deal.II/base/cuda.h>
-#include <deal.II/base/exceptions.h>
-
-#include <deal.II/lac/cuda_sparse_matrix.h>
-#include <deal.II/lac/precondition.h>
-#include <deal.II/lac/read_write_vector.h>
-#include <deal.II/lac/solver_control.h>
-#include <deal.II/lac/solver_qmrs.h>
-#include <deal.II/lac/vector.h>
-
-#include "../tests.h"
-
-#include "../testmatrix.h"
-
-void
-test(Utilities::CUDA::Handle &cuda_handle)
-{
- // Build the sparse matrix on the host
- const unsigned int problem_size = 10;
- unsigned int size = (problem_size - 1) * (problem_size - 1);
- FDMatrix testproblem(problem_size, problem_size);
- SparsityPattern structure(size, size, 5);
- SparseMatrix<double> A;
- testproblem.five_point_structure(structure);
- structure.compress();
- A.reinit(structure);
- testproblem.five_point(A);
-
- // Solve on the host
- PreconditionIdentity prec_no;
- SolverControl control(1000, 1.e-3);
- SolverQMRS<> qmrs_host(control);
- Vector<double> sol_host(size);
- Vector<double> rhs_host(size);
- for (unsigned int i = 0; i < size; ++i)
- rhs_host[i] = static_cast<double>(i);
- qmrs_host.solve(A, sol_host, rhs_host, prec_no);
-
- // Solve on the device
- CUDAWrappers::SparseMatrix<double> A_dev(cuda_handle, A);
- LinearAlgebra::CUDAWrappers::Vector<double> sol_dev(size);
- LinearAlgebra::CUDAWrappers::Vector<double> rhs_dev(size);
- LinearAlgebra::ReadWriteVector<double> rw_vector(size);
- for (unsigned int i = 0; i < size; ++i)
- rw_vector[i] = static_cast<double>(i);
- rhs_dev.import_elements(rw_vector, VectorOperation::insert);
- SolverQMRS<LinearAlgebra::CUDAWrappers::Vector<double>> qmrs_dev(control);
- qmrs_dev.solve(A_dev, sol_dev, rhs_dev, prec_no);
-
- // Check the result
- rw_vector.import_elements(sol_dev, VectorOperation::insert);
- for (unsigned int i = 0; i < size; ++i)
- AssertThrow(std::fabs(rw_vector[i] - sol_host[i]) < 1e-8,
- ExcInternalError());
-}
-
-int
-main()
-{
- initlog();
- deallog.depth_console(0);
-
- init_cuda();
-
- Utilities::CUDA::Handle cuda_handle;
- test(cuda_handle);
-
- deallog << "OK" << std::endl;
-
- return 0;
-}
+++ /dev/null
-
-DEAL:SQMR::Starting value 416.989
-DEAL:SQMR::Convergence step 22 value 0.000879597
-DEAL:SQMR::Starting value 416.989
-DEAL:SQMR::Convergence step 22 value 0.000879597
-DEAL::OK
+++ /dev/null
-// ------------------------------------------------------------------------
-//
-// SPDX-License-Identifier: LGPL-2.1-or-later
-// Copyright (C) 2018 - 2023 by the deal.II authors
-//
-// This file is part of the deal.II library.
-//
-// Part of the source code is dual licensed under Apache-2.0 WITH
-// LLVM-exception OR LGPL-2.1-or-later. Detailed license information
-// governing the source code and code contributions can be found in
-// LICENSE.md and CONTRIBUTING.md at the top level directory of deal.II.
-//
-// ------------------------------------------------------------------------
-
-// Check that dealii::SolverRichardson works with CUDAWrappers::SparseMatrix
-
-#include <deal.II/base/cuda.h>
-#include <deal.II/base/exceptions.h>
-
-#include <deal.II/lac/cuda_sparse_matrix.h>
-#include <deal.II/lac/precondition.h>
-#include <deal.II/lac/read_write_vector.h>
-#include <deal.II/lac/solver_control.h>
-#include <deal.II/lac/solver_richardson.h>
-#include <deal.II/lac/vector.h>
-
-#include "../tests.h"
-
-#include "../testmatrix.h"
-
-template <typename MatrixType>
-class PreconditionOperator
-{
-public:
- PreconditionOperator(const MatrixType &inverse_diagonal_matrix_)
- : inverse_diagonal_matrix(inverse_diagonal_matrix_)
- {}
-
- template <typename VectorType>
- void
- vmult(VectorType &u, const VectorType &v) const
- {
- inverse_diagonal_matrix.vmult(u, v);
- }
-
-private:
- const MatrixType &inverse_diagonal_matrix;
-};
-
-
-void
-test(Utilities::CUDA::Handle &cuda_handle)
-{
- // Build the sparse matrix on the host
- const unsigned int problem_size = 10;
- unsigned int size = (problem_size - 1) * (problem_size - 1);
- FDMatrix testproblem(problem_size, problem_size);
- SparsityPattern structure(size, size, 5);
- SparseMatrix<double> A;
- testproblem.five_point_structure(structure);
- structure.compress();
- A.reinit(structure);
- testproblem.five_point(A);
- SparseMatrix<double> A_diagonal_inverse;
- A_diagonal_inverse.reinit(structure);
- for (unsigned int i = 0; i < size; ++i)
- A_diagonal_inverse(i, i) = 1. / A(i, i);
-
- // Solve on the host
- PreconditionOperator<SparseMatrix<double>> preconditioner(A_diagonal_inverse);
- SolverControl control(1000, 1.e-2);
- SolverRichardson<> richardson_host(control);
- Vector<double> sol_host(size);
- Vector<double> rhs_host(size);
- for (unsigned int i = 0; i < size; ++i)
- rhs_host[i] = static_cast<double>(i);
- richardson_host.solve(A, sol_host, rhs_host, preconditioner);
-
- // Solve on the device
- CUDAWrappers::SparseMatrix<double> A_dev(cuda_handle, A);
- CUDAWrappers::SparseMatrix<double> A_diagonal_inverse_dev(cuda_handle,
- A_diagonal_inverse);
- PreconditionOperator<CUDAWrappers::SparseMatrix<double>> preconditioner_dev(
- A_diagonal_inverse_dev);
- LinearAlgebra::CUDAWrappers::Vector<double> sol_dev(size);
- LinearAlgebra::CUDAWrappers::Vector<double> rhs_dev(size);
- LinearAlgebra::ReadWriteVector<double> rw_vector(size);
- for (unsigned int i = 0; i < size; ++i)
- rw_vector[i] = static_cast<double>(i);
- rhs_dev.import_elements(rw_vector, VectorOperation::insert);
- SolverRichardson<LinearAlgebra::CUDAWrappers::Vector<double>> richardson_dev(
- control);
- richardson_dev.solve(A_dev, sol_dev, rhs_dev, preconditioner_dev);
-
- // Check the result
- rw_vector.import_elements(sol_dev, VectorOperation::insert);
- for (unsigned int i = 0; i < size; ++i)
- AssertThrow(std::fabs(rw_vector[i] - sol_host[i]) < 1e-8,
- ExcInternalError());
-}
-
-int
-main()
-{
- initlog();
- deallog.depth_console(0);
-
- init_cuda();
-
- Utilities::CUDA::Handle cuda_handle;
- test(cuda_handle);
-
- deallog << "OK" << std::endl;
-
- return 0;
-}
+++ /dev/null
-
-DEAL:Richardson::Starting value 416.989
-DEAL:Richardson::Convergence step 207 value 0.00982595
-DEAL:Richardson::Starting value 416.989
-DEAL:Richardson::Convergence step 207 value 0.00982595
-DEAL::OK
+++ /dev/null
-// ------------------------------------------------------------------------
-//
-// SPDX-License-Identifier: LGPL-2.1-or-later
-// Copyright (C) 2018 - 2023 by the deal.II authors
-//
-// This file is part of the deal.II library.
-//
-// Part of the source code is dual licensed under Apache-2.0 WITH
-// LLVM-exception OR LGPL-2.1-or-later. Detailed license information
-// governing the source code and code contributions can be found in
-// LICENSE.md and CONTRIBUTING.md at the top level directory of deal.II.
-//
-// ------------------------------------------------------------------------
-
-// Check that dealii::SolverRelaxation works with CUDAWrappers::SparseMatrix
-
-#include <deal.II/base/cuda.h>
-#include <deal.II/base/exceptions.h>
-
-#include <deal.II/lac/cuda_sparse_matrix.h>
-#include <deal.II/lac/precondition.h>
-#include <deal.II/lac/read_write_vector.h>
-#include <deal.II/lac/solver_control.h>
-#include <deal.II/lac/solver_relaxation.h>
-#include <deal.II/lac/vector.h>
-
-#include "../tests.h"
-
-#include "../testmatrix.h"
-
-
-template <typename MatrixType>
-class RelaxationOperator
-{
-public:
- RelaxationOperator(const MatrixType &system_matrix_,
- const MatrixType &inverse_diagonal_matrix_)
- : system_matrix(system_matrix_)
- , inverse_diagonal_matrix(inverse_diagonal_matrix_)
- {}
-
- template <typename VectorType>
- void
- step(VectorType &u, const VectorType &v) const
- {
- // u = u - omega*inverse_diagonal_matrix*(system_matrix*u-v)
- const double omega = 1.;
- VectorType tmp_1(v.size());
- system_matrix.vmult(tmp_1, u);
- tmp_1 -= v;
- VectorType tmp_2(u.size());
- inverse_diagonal_matrix.vmult(tmp_2, tmp_1);
- tmp_2 *= omega;
- u -= tmp_2;
- }
-
- template <typename VectorType>
- void
- Tstep(VectorType &u, const VectorType &v) const
- {
- AssertThrow(false, ExcNotImplemented());
- }
-
-private:
- const MatrixType &system_matrix;
- const MatrixType &inverse_diagonal_matrix;
-};
-
-
-void
-test(Utilities::CUDA::Handle &cuda_handle)
-{
- // Build the sparse matrix on the host
- const unsigned int problem_size = 10;
- unsigned int size = (problem_size - 1) * (problem_size - 1);
- FDMatrix testproblem(problem_size, problem_size);
- SparsityPattern structure(size, size, 5);
- SparseMatrix<double> A;
- testproblem.five_point_structure(structure);
- structure.compress();
- A.reinit(structure);
- testproblem.five_point(A);
- SparseMatrix<double> A_diagonal_inverse;
- A_diagonal_inverse.reinit(structure);
- for (unsigned int i = 0; i < size; ++i)
- A_diagonal_inverse(i, i) = 1. / A(i, i);
-
- // Solve on the host
- RelaxationOperator<SparseMatrix<double>> relaxation_operator(
- A, A_diagonal_inverse);
- SolverControl control(1000, 1.e-3);
- SolverRelaxation<> relaxation_host(control);
- Vector<double> sol_host(size);
- Vector<double> rhs_host(size);
- for (unsigned int i = 0; i < size; ++i)
- rhs_host[i] = static_cast<double>(i);
- relaxation_host.solve(A, sol_host, rhs_host, relaxation_operator);
-
- // Solve on the device
- CUDAWrappers::SparseMatrix<double> A_dev(cuda_handle, A);
- CUDAWrappers::SparseMatrix<double> A_diagonal_inverse_dev(cuda_handle,
- A_diagonal_inverse);
- RelaxationOperator<CUDAWrappers::SparseMatrix<double>>
- relaxation_operator_dev(A_dev, A_diagonal_inverse_dev);
- LinearAlgebra::CUDAWrappers::Vector<double> sol_dev(size);
- LinearAlgebra::CUDAWrappers::Vector<double> rhs_dev(size);
- LinearAlgebra::ReadWriteVector<double> rw_vector(size);
- for (unsigned int i = 0; i < size; ++i)
- rw_vector[i] = static_cast<double>(i);
- rhs_dev.import_elements(rw_vector, VectorOperation::insert);
- SolverRelaxation<LinearAlgebra::CUDAWrappers::Vector<double>> relaxation_dev(
- control);
- relaxation_dev.solve(A_dev, sol_dev, rhs_dev, relaxation_operator_dev);
-
- // Check the result
- rw_vector.import_elements(sol_dev, VectorOperation::insert);
- for (unsigned int i = 0; i < size; ++i)
- AssertThrow(std::fabs(rw_vector[i] - sol_host[i]) < 1e-8,
- ExcInternalError());
-}
-
-int
-main()
-{
- initlog();
- deallog.depth_console(10);
-
- init_cuda();
-
- Utilities::CUDA::Handle cuda_handle;
- test(cuda_handle);
-
- deallog << "OK" << std::endl;
-
- return 0;
-}
+++ /dev/null
-
-DEAL:Relaxation::Starting value 416.989
-DEAL:Relaxation::Convergence step 253 value 0.000976934
-DEAL:Relaxation::Starting value 416.989
-DEAL:Relaxation::Convergence step 253 value 0.000976934
-DEAL::OK
+++ /dev/null
-// ------------------------------------------------------------------------
-//
-// SPDX-License-Identifier: LGPL-2.1-or-later
-// Copyright (C) 2018 - 2023 by the deal.II authors
-//
-// This file is part of the deal.II library.
-//
-// Part of the source code is dual licensed under Apache-2.0 WITH
-// LLVM-exception OR LGPL-2.1-or-later. Detailed license information
-// governing the source code and code contributions can be found in
-// LICENSE.md and CONTRIBUTING.md at the top level directory of deal.II.
-//
-// ------------------------------------------------------------------------
-
-// Check multiplications and norms
-
-#include <deal.II/base/cuda.h>
-#include <deal.II/base/exceptions.h>
-
-#include <deal.II/lac/cuda_sparse_matrix.h>
-#include <deal.II/lac/read_write_vector.h>
-#include <deal.II/lac/vector.h>
-
-#include "../tests.h"
-
-#include "../testmatrix.h"
-
-
-void
-check_matrix(const SparseMatrix<double> &A,
- CUDAWrappers::SparseMatrix<double> &A_dev)
-{
- cudaError_t cuda_error_code;
- double *val_dev = nullptr;
- int *column_index_dev = nullptr;
- int *row_ptr_dev = nullptr;
- std::tie(val_dev, column_index_dev, row_ptr_dev, std::ignore, std::ignore) =
- A_dev.get_cusparse_matrix();
-
- int nnz = A_dev.n_nonzero_elements();
- std::vector<double> val_host(nnz);
- cuda_error_code = cudaMemcpy(&val_host[0],
- val_dev,
- nnz * sizeof(double),
- cudaMemcpyDeviceToHost);
- AssertCuda(cuda_error_code);
-
- std::vector<int> column_index_host(nnz);
- cuda_error_code = cudaMemcpy(&column_index_host[0],
- column_index_dev,
- nnz * sizeof(int),
- cudaMemcpyDeviceToHost);
- AssertCuda(cuda_error_code);
-
- const int n_rows = A_dev.m() + 1;
- std::vector<int> row_ptr_host(n_rows + 1);
- cuda_error_code = cudaMemcpy(&row_ptr_host[0],
- row_ptr_dev,
- (A_dev.m() + 1) * sizeof(int),
- cudaMemcpyDeviceToHost);
- AssertCuda(cuda_error_code);
-
- for (int i = 0; i < n_rows; ++i)
- for (int j = row_ptr_host[i]; j < row_ptr_host[i + 1]; ++j)
- AssertThrow(std::abs(val_host[j] - A(i, column_index_host[j])) < 1e-15,
- ExcInternalError());
-}
-
-void
-check_vector(const Vector<double> &a,
- const LinearAlgebra::ReadWriteVector<double> &b)
-{
- unsigned int size = a.size();
- for (unsigned int i = 0; i < size; ++i)
- AssertThrow(std::abs(a[i] - b[i]) < 1e-15, ExcInternalError());
-}
-
-void
-test(Utilities::CUDA::Handle &cuda_handle)
-{
- // Build the sparse matrix on the host
- const unsigned int size = 10;
- unsigned int dim = (size - 1) * (size - 1);
- FDMatrix testproblem(size, size);
- SparsityPattern structure(dim, dim, 5);
- SparseMatrix<double> A;
- testproblem.five_point_structure(structure);
- structure.compress();
- A.reinit(structure);
- testproblem.five_point(A, true);
-
- // Create the sparse matrix on the device
- CUDAWrappers::SparseMatrix<double> A_dev(cuda_handle, A);
- check_matrix(A, A_dev);
-
- AssertDimension(A.m(), A_dev.m());
- AssertDimension(A.n(), A_dev.n());
-
- // Multiply by a constant
- A *= 2.;
- A_dev *= 2.;
- check_matrix(A, A_dev);
-
- // Divide by a constant
- A /= 2.;
- A_dev /= 2.;
- check_matrix(A, A_dev);
-
- // Matrix-vector multiplication
- const unsigned int vector_size = A.n();
- Vector<double> dst(vector_size);
- Vector<double> src(vector_size);
- for (unsigned int i = 0; i < vector_size; ++i)
- src[i] = i;
- A.vmult(dst, src);
- LinearAlgebra::CUDAWrappers::Vector<double> dst_dev(vector_size);
- LinearAlgebra::CUDAWrappers::Vector<double> src_dev(vector_size);
- LinearAlgebra::ReadWriteVector<double> read_write(vector_size);
- for (unsigned int i = 0; i < vector_size; ++i)
- read_write[i] = i;
- src_dev.import_elements(read_write, VectorOperation::insert);
- A_dev.vmult(dst_dev, src_dev);
- read_write.import_elements(dst_dev, VectorOperation::insert);
- check_vector(dst, read_write);
-
- // Transpose matrix-vector multiplication
- A.Tvmult(dst, src);
- A_dev.Tvmult(dst_dev, src_dev);
- read_write.import_elements(dst_dev, VectorOperation::insert);
- check_vector(dst, read_write);
-
- // Matrix-vector multiplication and add
- A.vmult_add(dst, src);
- A_dev.vmult_add(dst_dev, src_dev);
- read_write.import_elements(dst_dev, VectorOperation::insert);
- check_vector(dst, read_write);
-
- // Transpose matrix-vector multiplication and add
- A.Tvmult_add(dst, src);
- A_dev.Tvmult_add(dst_dev, src_dev);
- read_write.import_elements(dst_dev, VectorOperation::insert);
- check_vector(dst, read_write);
-
- // Matrix norm square
- double value = A.matrix_norm_square(src);
- double value_host = A_dev.matrix_norm_square(src_dev);
- AssertThrow(std::abs(value - value_host) < 1e-15, ExcInternalError());
-
- // Matrix scalar product (reuse dst and src but they are both input)
- value = A.matrix_scalar_product(dst, src);
- value_host = A_dev.matrix_scalar_product(dst_dev, src_dev);
- AssertThrow(std::abs(value - value_host) < 1e-15, ExcInternalError());
-
- // Compute the residual
- Vector<double> b(src);
- for (unsigned int i = 0; i < vector_size; ++i)
- {
- b[i] = i;
- src[i] = i;
- read_write[i] = i;
- }
- LinearAlgebra::CUDAWrappers::Vector<double> b_dev(vector_size);
- b_dev.import_elements(read_write, VectorOperation::insert);
- src_dev.import_elements(read_write, VectorOperation::insert);
- value = A.residual(dst, src, b);
- value_host = A_dev.residual(dst_dev, src_dev, b_dev);
- AssertThrow(std::abs(value - value_host) < 1e-15, ExcInternalError());
- read_write.import_elements(dst_dev, VectorOperation::insert);
- check_vector(dst, read_write);
-
- // Compute L1 norm
- value = A.l1_norm();
- value_host = A_dev.l1_norm();
- AssertThrow(std::abs(value - value_host) < 1e-15, ExcInternalError());
-
- // Compute Linfty norm
- value = A.linfty_norm();
- value_host = A_dev.linfty_norm();
- AssertThrow(std::abs(value - value_host) < 1e-15, ExcInternalError());
-
- // Compute Frobenius norm
- value = A.frobenius_norm();
- value_host = A_dev.frobenius_norm();
- AssertThrow(std::abs(value - value_host) < 1e-15, ExcInternalError());
-
- // Compute L1 norm second test
- SparsityPattern sparsity_pattern(vector_size, vector_size, 3);
- for (unsigned int i = 0; i < vector_size; ++i)
- {
- sparsity_pattern.add(i, 0);
- sparsity_pattern.add(i, i);
- if (i < vector_size - 1)
- sparsity_pattern.add(i, i + 1);
- }
- sparsity_pattern.compress();
- SparseMatrix<double> B(sparsity_pattern);
- for (unsigned int i = 0; i < vector_size; ++i)
- {
- B.set(i, 0, 1);
- B.set(i, i, 1);
- if (i < vector_size - 1)
- B.set(i, i + 1, 1);
- }
- CUDAWrappers::SparseMatrix<double> B_dev(cuda_handle, B);
- value = B.l1_norm();
- value_host = B_dev.l1_norm();
- AssertThrow(std::abs(value - value_host) < 1e-15, ExcInternalError());
-}
-
-int
-main()
-{
- initlog();
- deallog.depth_console(0);
-
- init_cuda();
-
- Utilities::CUDA::Handle cuda_handle;
-
- test(cuda_handle);
-
- deallog << "OK" << std::endl;
-
- return 0;
-}
+++ /dev/null
-
-DEAL::OK
+++ /dev/null
-// ------------------------------------------------------------------------
-//
-// SPDX-License-Identifier: LGPL-2.1-or-later
-// Copyright (C) 2018 - 2022 by the deal.II authors
-//
-// This file is part of the deal.II library.
-//
-// Part of the source code is dual licensed under Apache-2.0 WITH
-// LLVM-exception OR LGPL-2.1-or-later. Detailed license information
-// governing the source code and code contributions can be found in
-// LICENSE.md and CONTRIBUTING.md at the top level directory of deal.II.
-//
-// ------------------------------------------------------------------------
-
-// Check print and print_format
-
-#include <deal.II/base/cuda.h>
-#include <deal.II/base/exceptions.h>
-
-#include <deal.II/lac/cuda_sparse_matrix.h>
-
-#include "../tests.h"
-
-#include "../testmatrix.h"
-
-
-void
-test(Utilities::CUDA::Handle &cuda_handle)
-{
- // Build the sparse matrix on the host
- const unsigned int size = 3;
- unsigned int dim = (size - 1) * (size - 1);
-
- FDMatrix testproblem(size, size);
- SparsityPattern structure(dim, dim, 5);
- testproblem.five_point_structure(structure);
- structure.compress();
- SparseMatrix<double> A(structure);
- testproblem.upwind(A, true);
- A.print(deallog.get_file_stream());
- A.print_formatted(deallog.get_file_stream());
-
- // Create the sparse matrix on the device
- CUDAWrappers::SparseMatrix<double> A_dev(cuda_handle, A);
- A_dev.print(deallog.get_file_stream());
- A_dev.print_formatted(deallog.get_file_stream());
-}
-
-int
-main()
-{
- initlog();
- deallog.depth_console(0);
-
- init_cuda();
-
- Utilities::CUDA::Handle cuda_handle;
-
- test(cuda_handle);
-
- deallog << "OK" << std::endl;
-
- return 0;
-}
+++ /dev/null
-
-(0,0) 3.00000
-(0,1) -1.00000
-(0,2) 0.00000
-(1,1) 3.00000
-(1,0) 0.00000
-(1,3) 0.00000
-(2,2) 3.00000
-(2,0) 0.00000
-(2,3) -1.00000
-(3,3) 3.00000
-(3,1) 0.00000
-(3,2) 0.00000
-3.000e+00 -1.000e+00 0.000e+00
-0.000e+00 3.000e+00 0.000e+00
-0.000e+00 3.000e+00 -1.000e+00
- 0.000e+00 0.000e+00 3.000e+00
-(0,0) 3.00000
-(0,1) -1.00000
-(0,2) 0.00000
-(1,1) 3.00000
-(1,0) 0.00000
-(1,3) 0.00000
-(2,2) 3.00000
-(2,0) 0.00000
-(2,3) -1.00000
-(3,3) 3.00000
-(3,1) 0.00000
-(3,2) 0.00000
-3.000e+00 -1.000e+00 0.000e+00
-0.000e+00 3.000e+00 0.000e+00
-0.000e+00 3.000e+00 -1.000e+00
- 0.000e+00 0.000e+00 3.000e+00
-DEAL::OK
// check AffineConstraints<double>::set_zero(Vector) for parallel distributed
// vectors
-#include <deal.II/base/cuda_size.h>
-
#include <deal.II/dofs/dof_tools.h>
#include <deal.II/grid/grid_generator.h>
// check correct initialization of parallel vector without any ghosts
-#include <deal.II/base/cuda.h>
#include <deal.II/base/index_set.h>
#include <deal.II/base/utilities.h>
// check addition into ghosts for parallel vector
-#include <deal.II/base/cuda.h>
#include <deal.II/base/index_set.h>
#include <deal.II/base/utilities.h>
// check set of ghosts for parallel vector
-#include <deal.II/base/cuda.h>
#include <deal.II/base/index_set.h>
#include <deal.II/base/utilities.h>
// similar to parallel_sparse_vector_03.cc, but make sure
// compress(insert) zeroes out ghosts in Release mode
-#include <deal.II/base/cuda.h>
#include <deal.II/base/index_set.h>
#include <deal.II/base/utilities.h>
// check that operator= resets ghosts, both if they have been set and if they
// have not been set
-#include <deal.II/base/cuda.h>
#include <deal.II/base/index_set.h>
#include <deal.II/base/utilities.h>
// check that compress(add) with zero add does not change the vector entry
-#include <deal.II/base/cuda.h>
#include <deal.II/base/index_set.h>
#include <deal.II/base/utilities.h>
// check global reduction operation (norms, operator==, operator!=) on
// parallel vector
-#include <deal.II/base/cuda.h>
#include <deal.II/base/index_set.h>
#include <deal.II/base/utilities.h>
// check parallel_vector assignment and ghost values. Same vector layout as in
// parallel_vector_07.cc
-#include <deal.II/base/cuda.h>
#include <deal.II/base/index_set.h>
#include <deal.II/base/utilities.h>
// check operator= when we do some operations with ghosts
-#include <deal.II/base/cuda.h>
#include <deal.II/base/index_set.h>
#include <deal.II/base/utilities.h>
// check that add, sadd, equ, scale work correctly on a vector where some
// processor do not own any degrees of freedom
-#include <deal.II/base/cuda.h>
#include <deal.II/base/index_set.h>
#include <deal.II/base/utilities.h>
// check LinearAlgebra::distributed::Vector::swap
-#include <deal.II/base/cuda.h>
+#include <deal.II/base/.h>
#include <deal.II/base/index_set.h>
#include <deal.II/base/utilities.h>
// setting where one ghost is zero and should not have an effect on vector
// entries
-#include <deal.II/base/cuda.h>
#include <deal.II/base/index_set.h>
#include <deal.II/base/utilities.h>
// check that handling of ghost elements in parallel distributed vectors works
// appropriately when assigning from ghosted to non-ghosted vectors
-#include <deal.II/base/cuda.h>
#include <deal.II/base/index_set.h>
#include <deal.II/base/utilities.h>
// appropriately when creating a vector from a non-ghosted source vector using
// the assignment operator
-#include <deal.II/base/cuda.h>
#include <deal.II/base/index_set.h>
#include <deal.II/base/utilities.h>
// when doing reinit() from another vector and manually setting the local
// range
-#include <deal.II/base/cuda.h>
#include <deal.II/base/index_set.h>
#include <deal.II/base/utilities.h>
// check import from LA::d::Vector to another LA::d::Vector
-#include <deal.II/base/cuda.h>
#include <deal.II/base/index_set.h>
#include <deal.II/base/utilities.h>
#include <deal.II/grid/manifold_lib.h>
#include <deal.II/grid/tria.h>
-#include <deal.II/lac/cuda_vector.h>
#include <deal.II/lac/la_parallel_vector.h>
#include <deal.II/matrix_free/portable_matrix_free.templates.h>
// this function tests the correctness of the 1d evaluation functions used in
-// CUDAWrappers::FEEvaluation. These functions are marked 'internal' but it is
+// Portable::FEEvaluation. These functions are marked 'internal' but it is
// much easier to check their correctness directly rather than from the results
// in dependent functions
#include <deal.II/base/memory_space.h>
-#include <deal.II/lac/cuda_vector.h>
#include <deal.II/lac/read_write_vector.h>
-#include <deal.II/matrix_free/cuda_fe_evaluation.h>
+#include <deal.II/matrix_free/portable_tensor_product_kernels.h>
#include <fstream>
#include <iostream>
Kokkos::View<double *, MemorySpace::Default::kokkos_space> dst,
Kokkos::View<double *, MemorySpace::Default::kokkos_space> src)
{
- CUDAWrappers::internal::EvaluatorTensorProduct<
- CUDAWrappers::internal::evaluate_general,
+ Portable::internal::EvaluatorTensorProduct<
+ Portable::internal::evaluate_general,
1,
M - 1,
N,
// this function tests the correctness of the 2d evaluation functions used in
-// CUDAWrappers::FEEvaluation. These functions are marked 'internal' but it is
+// Portable::FEEvaluation. These functions are marked 'internal' but it is
// much easier to check their correctness directly rather than from the results
// in dependent functions
-#include <deal.II/lac/cuda_vector.h>
+#include <deal.II/lac/full_matrix.h>
#include <deal.II/lac/read_write_vector.h>
-#include <deal.II/matrix_free/cuda_fe_evaluation.h>
+#include <deal.II/matrix_free/portable_tensor_product_kernels.h>
#include <fstream>
#include <iostream>
Kokkos::View<double *, MemorySpace::Default::kokkos_space> dst,
Kokkos::View<double *, MemorySpace::Default::kokkos_space> src)
{
- CUDAWrappers::internal::EvaluatorTensorProduct<
- CUDAWrappers::internal::evaluate_general,
+ Portable::internal::EvaluatorTensorProduct<
+ Portable::internal::evaluate_general,
2,
M - 1,
N,
#include <deal.II/grid/grid_generator.h>
#include <deal.II/lac/affine_constraints.h>
-#include <deal.II/lac/cuda_vector.h>
#include <deal.II/matrix_free/portable_matrix_free.h>
ExcInternalError());
}
-#ifdef DEAL_II_WITH_CUDA
-template <typename Number>
-void
-check(const LinearAlgebra::CUDAWrappers::Vector<Number> &vector,
- const Utilities::MPI::Partitioner &reference_partitioner)
-{
- AssertDimension(vector.size(), reference_partitioner.size());
-}
-#endif
-
template <int dim, int fe_degree, typename VectorType>
void
test()
1,
LinearAlgebra::distributed::Vector<double, MemorySpace::Default>>();
-#ifdef DEAL_II_WITH_CUDA
- if (Utilities::MPI::n_mpi_processes(MPI_COMM_WORLD) == 1)
- test<2, 1, LinearAlgebra::CUDAWrappers::Vector<double>>();
-#endif
return 0;
}
// Same as matrix_free_matrix_vector_06a but uses LA::distributed::Vector
-// instead of CUDAWrappers::Vector
+// instead of Portable::Vector
#include <deal.II/base/function.h>
#include <deal.II/grid/tria.h>
#include <deal.II/lac/affine_constraints.h>
-#include <deal.II/lac/cuda_vector.h>
#include <deal.II/lac/dynamic_sparsity_pattern.h>
#include <deal.II/lac/la_parallel_vector.h>
#include <deal.II/lac/read_write_vector.h>
#include <deal.II/grid/tria.h>
#include <deal.II/lac/affine_constraints.h>
-#include <deal.II/lac/cuda_vector.h>
#include <deal.II/lac/dynamic_sparsity_pattern.h>
#include <deal.II/lac/la_parallel_vector.h>
#include <deal.II/lac/read_write_vector.h>
// (zero and first derivatives) on different kinds of meshes (Cartesian,
// general, with and without hanging nodes).
-#include <deal.II/lac/cuda_vector.h>
#include <deal.II/lac/la_parallel_vector.h>
#include <deal.II/matrix_free/portable_fe_evaluation.h>
*
* Description:
*
- * This test compares the MatrixFree and CUDAWrapper::MatrixFree
+ * This test compares the MatrixFree and Portable::MatrixFree
* infrastructure on the CPU. Considered are the initialization
* costs and the costs for an operator evaluation.
- * CUDAWrapper::MatrixFree was written with CUDA and now uses
+ * Portable::MatrixFree was written with CUDA and now uses
* Kokkos as backend and, as consequence, favors GPU hardware. This
* performance test is meant to track the improvement of
- * the performance of CUDAWrapper::MatrixFree on the CPU.
+ * the performance of Portable::MatrixFree on the CPU.
*
* Status: experimental
*/
#include <deal.II/grid/grid_generator.h>
-#include <deal.II/matrix_free/cuda_fe_evaluation.h>
-#include <deal.II/matrix_free/cuda_matrix_free.h>
#include <deal.II/matrix_free/fe_evaluation.h>
#include <deal.II/matrix_free/matrix_free.h>
public:
DEAL_II_HOST_DEVICE void
operator()(
- CUDAWrappers::FEEvaluation<dim, fe_degree, fe_degree + 1, 1, Number>
- *fe_eval,
+ Portable::FEEvaluation<dim, fe_degree, fe_degree + 1, 1, Number> *fe_eval,
const int q_point) const
{
fe_eval->submit_gradient(fe_eval->get_gradient(q_point), q_point);
{
public:
DEAL_II_HOST_DEVICE void
- operator()(
- const unsigned int cell,
- const typename CUDAWrappers::MatrixFree<dim, Number>::Data *gpu_data,
- CUDAWrappers::SharedData<dim, Number> *shared_data,
- const Number *src,
- Number *dst) const
+ operator()(const unsigned int cell,
+ const typename Portable::MatrixFree<dim, Number>::Data *gpu_data,
+ Portable::SharedData<dim, Number> *shared_data,
+ const Number *src,
+ Number *dst) const
{
(void)cell; // TODO?
- CUDAWrappers::FEEvaluation<dim, fe_degree, fe_degree + 1, 1, Number>
- fe_eval(/*cell,*/ gpu_data, shared_data);
+ Portable::FEEvaluation<dim, fe_degree, fe_degree + 1, 1, Number> fe_eval(
+ /*cell,*/ gpu_data, shared_data);
fe_eval.read_dof_values(src);
fe_eval.evaluate(EvaluationFlags::gradients);
fe_eval.apply_for_each_quad_point(
const AffineConstraints<Number> &constraints,
const Quadrature<1> &quadrature)
{
- typename CUDAWrappers::MatrixFree<dim, Number>::AdditionalData
- additional_data;
+ typename Portable::MatrixFree<dim, Number>::AdditionalData additional_data;
additional_data.mapping_update_flags = update_JxW_values | update_gradients;
matrix_free.reinit(
}
private:
- CUDAWrappers::MatrixFree<dim, Number> matrix_free;
+ Portable::MatrixFree<dim, Number> matrix_free;
};
+++ /dev/null
-// ------------------------------------------------------------------------
-//
-// SPDX-License-Identifier: LGPL-2.1-or-later
-// Copyright (C) 2017 - 2023 by the deal.II authors
-//
-// This file is part of the deal.II library.
-//
-// Part of the source code is dual licensed under Apache-2.0 WITH
-// LLVM-exception OR LGPL-2.1-or-later. Detailed license information
-// governing the source code and code contributions can be found in
-// LICENSE.md and CONTRIBUTING.md at the top level directory of deal.II.
-//
-// ------------------------------------------------------------------------
-
-
-#include <deal.II/base/exceptions.h>
-
-#include <array>
-#include <iostream>
-#include <numeric>
-
-using namespace dealii;
-
-__global__ void
-double_value(double *x, double *y)
-{
- y[threadIdx.x] = 2. * x[threadIdx.x];
-}
-
-int
-main()
-{
- constexpr int n = 4;
-
- std::array<double, n> host_x{};
- std::iota(host_x.begin(), host_x.end(), 1);
- std::array<double, n> host_y{};
-
- // Copy input data to device.
- double *device_x;
- double *device_y;
- cudaError_t cuda_error = cudaMalloc(&device_x, n * sizeof(double));
- AssertCuda(cuda_error);
- cuda_error = cudaMalloc(&device_y, n * sizeof(double));
- AssertCuda(cuda_error);
- cuda_error = cudaMemcpy(device_x,
- host_x.data(),
- n * sizeof(double),
- cudaMemcpyHostToDevice);
- AssertCuda(cuda_error);
-
- // Launch the kernel.
- double_value<<<1, n>>>(device_x, device_y);
-
- // Copy output data to host.
- cuda_error = cudaDeviceSynchronize();
- AssertCuda(cuda_error);
- cuda_error = cudaMemcpy(host_y.data(),
- device_y,
- n * sizeof(double),
- cudaMemcpyDeviceToHost);
- AssertCuda(cuda_error);
-
- // Print the results and test
- for (int i = 0; i < n; ++i)
- {
- std::cout << "y[" << i << "] = " << host_y[i] << "\n";
- AssertThrow(std::abs(host_y[i] - 2 * host_x[i]) < 1.e-10,
- ExcInternalError());
- }
-
- cuda_error = cudaDeviceReset();
- AssertCuda(cuda_error);
- return 0;
-}
_var MATCHES "^(DOCUMENTATION|EXAMPLES)" OR
_var MATCHES "^(ADOLC|ARBORX|ARPACK|BOOST|OPENCASCADE|MUPARSER|HDF5|KOKKOS|METIS|MPI)_" OR
_var MATCHES "^(GINKGO|P4EST|PETSC|SCALAPACK|SLEPC|THREADS|TBB|TRILINOS)_" OR
- _var MATCHES "^(UMFPACK|ZLIB|LAPACK|MUPARSER|CUDA)_" OR
+ _var MATCHES "^(UMFPACK|ZLIB|LAPACK|MUPARSER)_" OR
_var MATCHES "^(CMAKE|DEAL_II)_(C|CXX|Fortran|BUILD)_(COMPILER|FLAGS)" OR
_var MATCHES "^CMAKE_BUILD_TYPE$" OR
_var MATCHES "MAKEOPTS" OR
#include <deal.II/base/config.h>
#include <deal.II/base/bounding_box.h>
-#include <deal.II/base/cuda.h>
#include <deal.II/base/exceptions.h>
#include <deal.II/base/job_identifier.h>
#include <deal.II/base/logstream.h>
};
-#ifdef DEAL_II_WITH_CUDA
-// By default, all the ranks will try to access the device 0.
-// If we are running with MPI support it is better to address different graphic
-// cards for different processes even if only one node is used. The choice below
-// is based on the MPI process id.
-// MPI needs to be initialized before using this function.
-void
-init_cuda(const bool use_mpi = false)
-{
-# ifndef DEAL_II_WITH_MPI
- Assert(use_mpi == false, ExcInternalError());
-# endif
- const unsigned int my_id =
- use_mpi ? Utilities::MPI::this_mpi_process(MPI_COMM_WORLD) : 0;
- int n_devices = 0;
- cudaError_t cuda_error_code = cudaGetDeviceCount(&n_devices);
- AssertCuda(cuda_error_code);
- const int device_id = my_id % n_devices;
- cuda_error_code = cudaSetDevice(device_id);
- AssertCuda(cuda_error_code);
-
- // In principle, we should be able to distribute the load better by
- // choosing a random graphics card. For some reason, this produces timeouts
- // on the tester we use mainly for the CUDA tests so we don't use the
- // following optimization by default.
-
- /*
- # ifndef DEAL_II_WITH_MPI
- Assert(use_mpi == false, ExcInternalError());
- # endif
- const unsigned int my_id =
- use_mpi ? Utilities::MPI::this_mpi_process(MPI_COMM_WORLD) : 0;
- int device_id = 0;
- int n_devices = 0;
- cudaError_t cuda_error_code = cudaGetDeviceCount(&n_devices);
- AssertCuda(cuda_error_code);
- if (my_id == 0)
- {
- Testing::srand(std::time(nullptr));
- device_id = Testing::rand() % n_devices;
- }
- # ifdef DEAL_II_WITH_MPI
- if (use_mpi)
- MPI_Bcast(&device_id, 1, MPI_INT, 0, MPI_COMM_WORLD);
- # endif
- device_id = (device_id + my_id) % n_devices;
- cuda_error_code = cudaSetDevice(device_id);
- AssertCuda(cuda_error_code);
- */
-}
-#endif
-
-
-
/* Override the tbb assertion handler in order to print a stacktrace:*/
#ifdef TBB_DO_ASSERT