├── .clang-format ├── .cpack_ignore ├── .gitignore ├── .gitmodules ├── CMake ├── Cache.cmake ├── ClangSupport.cmake ├── CompilerWarnings.cmake ├── DownloadProject.CMakeLists.cmake.in ├── DownloadProject.LICENSE ├── DownloadProject.cmake ├── FindSphinx.cmake ├── FindWayland.cmake ├── FindXCB.cmake ├── Pybind11.cmake ├── Sanitizers.cmake ├── StandardProjectSettings.cmake ├── StaticAnalyzers.cmake ├── Uninstall.cmake ├── Utility.cmake ├── get_cpm.cmake └── zensim-config.cmake.in ├── CMakeLists.txt ├── LICENSE ├── README.md ├── Specification.md ├── docs ├── doxygen.rst ├── index.rst └── overview.rst ├── include └── zensim │ ├── CMakeLists.txt │ ├── Logger.cpp │ ├── Logger.hpp │ ├── Platform.hpp │ ├── Reflection.h │ ├── Singleton.h │ ├── TypeAlias.hpp │ ├── ZensimExport.hpp │ ├── Zpc.hpp │ ├── ZpcBuiltin.hpp │ ├── ZpcFunction.hpp │ ├── ZpcFunctional.hpp │ ├── ZpcImplPattern.cpp │ ├── ZpcImplPattern.hpp │ ├── ZpcInitialization.cpp │ ├── ZpcIntrinsics.hpp │ ├── ZpcIterator.hpp │ ├── ZpcMathUtils.hpp │ ├── ZpcMeta.hpp │ ├── ZpcReflection.hpp │ ├── ZpcResource.hpp │ ├── ZpcTuple.hpp │ ├── container │ ├── Bcht.hpp │ ├── Bht.cpp │ ├── Bht.hpp │ ├── Bvh.hpp │ ├── Bvs.hpp │ ├── Bvtt.hpp │ ├── Callables.hpp │ ├── Container.md │ ├── DenseField.cpp │ ├── DenseField.hpp │ ├── DenseGrid.hpp │ ├── FiniteStateMachine.h │ ├── HashTable.cpp │ ├── HashTable.hpp │ ├── IndexBuckets.hpp │ ├── RBTreeMap.hpp │ ├── RingBuffer.hpp │ ├── SpatialHash.hpp │ ├── TileVector.cpp │ ├── TileVector.hpp │ ├── Vector.cpp │ └── Vector.hpp │ ├── cuda │ ├── Cuda.cu │ ├── Cuda.h │ ├── CudaLaunchConfig.cuh │ ├── DeviceUtils.cuh │ ├── HostUtils.hpp │ ├── algorithm │ │ ├── MappingKernels.cuh │ │ └── SortKernels.cuh │ ├── copy_ptx.cmake │ ├── execution │ │ ├── CudaLibExecutionPolicy.cuh │ │ └── ExecutionPolicy.cuh │ ├── geometry │ │ └── Structurefree.hpp │ ├── math │ │ └── matrix │ │ │ ├── EigenDecomposition.cuh │ │ │ ├── Matrix.cpp │ │ │ ├── Matrix.hpp │ │ │ └── svd.cuh │ ├── memory │ │ ├── Allocator.cpp │ │ ├── Allocator.h │ │ ├── MemOps.cpp │ │ └── MemOps.hpp │ ├── physics │ │ └── ConstitutiveModel.hpp │ ├── profile │ │ ├── CudaTimers.cu │ │ └── CudaTimers.cuh │ └── simulation │ │ ├── sparsity │ │ └── SparsityCompute.cpp │ │ ├── transfer │ │ └── P2G.hpp │ │ └── wrangler │ │ ├── ParticleWrangler.cpp │ │ ├── VolumeWrangler.cpp │ │ ├── Wrangler.cpp │ │ └── Wrangler.hpp │ ├── execution │ ├── Atomics.hpp │ ├── Concurrency.h │ ├── ConcurrencyPrimitive.cpp │ ├── ConcurrencyPrimitive.hpp │ ├── ExecutionPolicy.cpp │ ├── ExecutionPolicy.hpp │ ├── Intrinsics.hpp │ ├── Stacktrace.cpp │ └── Stacktrace.hpp │ ├── geometry │ ├── AdaptiveGrid.cpp │ ├── AdaptiveGrid.hpp │ ├── AdaptiveGridUtils.hpp │ ├── AdaptiveGrid_Conversion.cpp │ ├── AnalyticLevelSet.h │ ├── BoundingVolumeInterface.hpp │ ├── Collider.cpp │ ├── Collider.h │ ├── Distance.hpp │ ├── Friction.hpp │ ├── GenericLevelSet.h │ ├── Geometry.hpp │ ├── LevelSet.h │ ├── LevelSetInterface.h │ ├── LevelSetUtils.hpp │ ├── LevelSetUtils.tpp │ ├── Mesh.cpp │ ├── Mesh.hpp │ ├── OverlayGrid.hpp │ ├── PointDataGrid.hpp │ ├── PoissonDisk.hpp │ ├── Predicates.hpp │ ├── SparseGrid.cpp │ ├── SparseGrid.hpp │ ├── SparseGrid_Conversion.cpp │ ├── SparseLevelSet.hpp │ ├── SpatialQuery.hpp │ ├── Structure.hpp │ ├── Structurefree.hpp │ ├── VdbLevelSet.h │ ├── VdbLevelSet_Conversion.cpp │ ├── VdbLevelSet_LoadPhi.cpp │ ├── VdbLevelSet_LoadPhiVel.cpp │ ├── VdbLevelSet_Point.cpp │ ├── VdbSampler.cpp │ ├── VdbSampler.h │ └── remesh │ │ └── Retile.hpp │ ├── graph │ ├── Coloring.hpp │ ├── ConnectedComponents.hpp │ └── MaximumFlow.hpp │ ├── io │ ├── Filesystem.cpp │ ├── Filesystem.hpp │ ├── IO.cpp │ ├── IO.h │ ├── MeshIO.cpp │ ├── MeshIO.hpp │ ├── ParticleIO.cpp │ └── ParticleIO.hpp │ ├── math │ ├── Complex.hpp │ ├── DihedralAngle.hpp │ ├── Hash.hpp │ ├── MathUtils.h │ ├── RandomNumber.hpp │ ├── Rational.hpp │ ├── Rotation.hpp │ ├── Tensor.hpp │ ├── Vec.h │ ├── VecInterface.hpp │ ├── bit │ │ └── Bits.h │ ├── curve │ │ └── InterpolationKernel.hpp │ ├── linear │ │ ├── ConjugateGradient.hpp │ │ ├── ConjugateResidual.hpp │ │ ├── LinearOperators.hpp │ │ └── MinimumResidual.hpp │ ├── matrix │ │ ├── Eigen.hpp │ │ ├── Givens.hpp │ │ ├── Matrix.cpp │ │ ├── Matrix.hpp │ │ ├── MatrixCtor.hpp │ │ ├── MatrixTransform.cpp │ │ ├── MatrixTransform.hpp │ │ ├── MatrixUtils.h │ │ ├── QRSVD.hpp │ │ ├── SVD.hpp │ │ ├── SparseMatrix.hpp │ │ ├── SparseMatrixOperations.hpp │ │ ├── Transform.hpp │ │ └── Utility.h │ └── probability │ │ ├── Probability.cpp │ │ ├── Probability.h │ │ └── Random.hpp │ ├── memory │ ├── Allocator.cpp │ ├── Allocator.h │ ├── MemOps.cpp │ ├── MemOps.hpp │ └── MemoryResource.h │ ├── meta │ ├── Functional.h │ └── Meta.h │ ├── musa │ ├── Musa.h │ ├── Musa.mu │ ├── MusaLaunchConfig.h │ ├── execution │ │ └── ExecutionPolicy.muh │ ├── memory │ │ ├── Allocator.h │ │ ├── Allocator.mu │ │ ├── MemOps.hpp │ │ └── MemOps.mu │ └── profile │ │ ├── MusaTimers.h │ │ └── MusaTimers.mu │ ├── omp │ ├── Omp.h │ ├── execution │ │ ├── ExecutionPolicy.cpp │ │ └── ExecutionPolicy.hpp │ ├── math │ │ └── matrix │ │ │ ├── MatrixTransform.cpp │ │ │ └── MatrixTransform.hpp │ └── simulation │ │ ├── particle │ │ └── Query.cpp │ │ └── sparsity │ │ └── SparsityCompute.cpp │ ├── physics │ ├── ConstitutiveModel.hpp │ ├── ConstitutiveModel_Vol_dP.hpp │ ├── SoundSpeedCfl.hpp │ ├── constitutive_models │ │ ├── AnisotropicArap.hpp │ │ ├── Bending.hpp │ │ ├── EquationOfState.hpp │ │ ├── FixedCorotated.h │ │ ├── JBasedFluid.h │ │ ├── NeoHookean.hpp │ │ └── StvkWithHencky.hpp │ └── plasticity_models │ │ ├── AssociativePlasticity.hpp │ │ ├── AssociativeVonMises.hpp │ │ ├── NonAssociativeCamClay.hpp │ │ ├── NonAssociativeDruckerPrager.hpp │ │ ├── NonAssociativeVonMises.hpp │ │ ├── SnowPlasticity.hpp │ │ └── VonMisesCapped.hpp │ ├── profile │ ├── CppTimers.cpp │ ├── CppTimers.hpp │ └── TimerBase.hpp │ ├── py_interop │ ├── Allocator.cpp │ ├── BhtInstantiations.cpp │ ├── BhtView.hpp │ ├── BvhView.hpp │ ├── Clang.cpp │ ├── DenseFieldInstantiations.cpp │ ├── DenseFieldView.hpp │ ├── GenericIterator.hpp │ ├── HashUtils.hpp │ ├── SmallVec.hpp │ ├── SmallVecInstantiations.cpp │ ├── SpmatInstantiations.cpp │ ├── SpmatView.hpp │ ├── TileVectorInstantiations.cpp │ ├── TileVectorView.hpp │ ├── VectorInstantiations.cpp │ ├── VectorView.hpp │ ├── cuda │ │ ├── BhtUtility.cpp │ │ ├── ExecutionPolicy.cpp │ │ ├── Nvrtc.cpp │ │ ├── SpmatUtility.cpp │ │ └── TileVectorUtility.cpp │ ├── omp │ │ ├── BhtUtility.cpp │ │ ├── ExecutionPolicy.cpp │ │ ├── SpmatUtility.cpp │ │ └── TileVectorUtility.cpp │ └── serial │ │ ├── BhtUtility.cpp │ │ ├── ExecutionPolicy.cpp │ │ ├── SpmatUtility.cpp │ │ └── TileVectorUtility.cpp │ ├── resource │ ├── ExecutionPolicy.cpp │ ├── Resource.cpp │ ├── Resource.h │ ├── cuda │ │ └── ExecutionPolicy.cu │ ├── musa │ │ └── ExecutionPolicy.mu │ └── omp │ │ └── ExecutionPolicy.cpp │ ├── simulation │ ├── Utils.hpp │ ├── grid │ │ └── GridOp.hpp │ ├── init │ │ ├── Scene.cpp │ │ └── Scene.hpp │ ├── mpm │ │ ├── ImplicitMPM.hpp │ │ ├── Simulator.cpp │ │ └── Simulator.hpp │ ├── particle │ │ ├── ParticleOp.hpp │ │ └── Query.tpp │ ├── sparsity │ │ ├── SparsityCompute.cpp │ │ ├── SparsityCompute.hpp │ │ ├── SparsityCompute.tpp │ │ └── SparsityOp.hpp │ └── transfer │ │ ├── G2C2P.hpp │ │ ├── G2P.hpp │ │ ├── G2P2G.hpp │ │ ├── OldG2C2P.hpp │ │ ├── OldP2C2G.hpp │ │ ├── P2C2G.hpp │ │ ├── P2G.hpp │ │ └── Scheme.hpp │ ├── sycl │ ├── Sycl.cpp │ └── Sycl.hpp │ ├── types │ ├── BuilderBase.hpp │ ├── ImplPattern.hpp │ ├── Iterator.cpp │ ├── Iterator.h │ ├── Mask.hpp │ ├── Optional.h │ ├── Pointers.hpp │ ├── Polymorphism.h │ ├── Property.h │ ├── SmallVector.hpp │ ├── SourceLocation.hpp │ ├── Tuple.h │ └── View.h │ ├── ui │ └── Widget.hpp │ ├── visitors │ ├── ObjectVisitor.cpp │ ├── ObjectVisitor.hpp │ └── Print.hpp │ └── vulkan │ ├── LICENSE.txt │ ├── VkBuffer.hpp │ ├── VkCommand.cpp │ ├── VkCommand.hpp │ ├── VkContext.cpp │ ├── VkContext.hpp │ ├── VkContextQuery.cpp │ ├── VkDescriptor.hpp │ ├── VkImage.hpp │ ├── VkModel.cpp │ ├── VkModel.hpp │ ├── VkPipeline.cpp │ ├── VkPipeline.hpp │ ├── VkQueryPool.hpp │ ├── VkRenderPass.hpp │ ├── VkShader.cpp │ ├── VkShader.hpp │ ├── VkSwapchain.cpp │ ├── VkSwapchain.hpp │ ├── VkTexture.cpp │ ├── VkTexture.hpp │ ├── VkUtils.cpp │ ├── VkUtils.hpp │ ├── Vulkan.cpp │ └── Vulkan.hpp ├── project_info.in └── test ├── CMakeLists.txt ├── binary_search.cpp ├── cuda ├── basic.cu └── main.cu ├── help_parser.cpp ├── map.cpp ├── musa └── basic.cpp ├── ndvec.cpp ├── parallel_primitives.cpp ├── sycl └── main.cpp ├── tuple.cpp └── utils ├── binary_search.hpp ├── initialization.hpp └── parallel_primitives.hpp /.clang-format: -------------------------------------------------------------------------------- 1 | --- 2 | BasedOnStyle: Google 3 | AccessModifierOffset: '-2' 4 | AlignTrailingComments: 'true' 5 | AllowAllParametersOfDeclarationOnNextLine: 'false' 6 | AlwaysBreakTemplateDeclarations: 'No' 7 | BreakBeforeBraces: Attach 8 | ColumnLimit: '100' 9 | ConstructorInitializerAllOnOneLineOrOnePerLine: 'true' 10 | IncludeBlocks: Regroup 11 | IndentPPDirectives: AfterHash 12 | IndentWidth: '2' 13 | NamespaceIndentation: All 14 | BreakBeforeBinaryOperators: All 15 | BreakBeforeTernaryOperators: 'true' 16 | ... 17 | -------------------------------------------------------------------------------- /.cpack_ignore: -------------------------------------------------------------------------------- 1 | **/*.cu 2 | **/*.cpp 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | **/build 2 | **/CMakeFiles/ 3 | .vscode/ 4 | .clangd/ 5 | .cache/ 6 | **/*.exe.manifest 7 | **/*.exe 8 | **/*.bgeo 9 | **/*.avi 10 | **/*.hip 11 | **/*.vtk 12 | **/*.obj 13 | **/*.vdb 14 | **/*.so 15 | **/*.a 16 | cmake-build-** 17 | .idea 18 | /.vs 19 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "include/zensim/tpls"] 2 | path = include/zensim/zpc_tpls 3 | url = https://github.com/zensim-dev/tpls.git 4 | [submodule "zpc_assets"] 5 | path = zpc_assets 6 | url = https://github.com/zensim-dev/assets.git -------------------------------------------------------------------------------- /CMake/Cache.cmake: -------------------------------------------------------------------------------- 1 | option(ENABLE_CACHE "Enable cache if available" ON) 2 | if(NOT ENABLE_CACHE) 3 | return() 4 | endif() 5 | 6 | set(CACHE_OPTION "ccache" CACHE STRING "Compiler cache to be used") 7 | set(CACHE_OPTION_VALUES "ccache" "sccache") 8 | set_property(CACHE CACHE_OPTION PROPERTY STRINGS ${CACHE_OPTION_VALUES}) 9 | list(FIND CACHE_OPTION_VALUES ${CACHE_OPTION} CACHE_OPTION_INDEX) 10 | 11 | if(${CACHE_OPTION_INDEX} EQUAL -1) 12 | message(STATUS "Using custom compiler cache system: '${CACHE_OPTION}', explicitly supported entries are ${CACHE_OPTION_VALUES}") 13 | endif() 14 | 15 | find_program(CACHE_BINARY ${CACHE_OPTION}) 16 | if(CACHE_BINARY) 17 | message(STATUS "${CACHE_OPTION} found and enabled") 18 | set(CMAKE_CXX_COMPILER_LAUNCHER ${CACHE_BINARY}) 19 | else() 20 | message(WARNING "${CACHE_OPTION} is enabled but was not found. Not using it") 21 | endif() -------------------------------------------------------------------------------- /CMake/ClangSupport.cmake: -------------------------------------------------------------------------------- 1 | # Additional targets to perform clang-format/clang-tidy 2 | # Get all project files 3 | file(GLOB_RECURSE 4 | ALL_SOURCE_FILES 5 | *.[chi]pp *.[chi]xx *.cc *.hh *.ii *.[CHI] *.cu *.cuh 6 | ) 7 | list(FILTER ALL_SOURCE_FILES EXCLUDE REGEX "${PROJECT_SOURCE_DIR}/include/zensim/zpc_tpls/.*" ) 8 | 9 | # Adding clang-format target if executable is found 10 | find_program(CLANG_FORMAT "clang-format") 11 | if(CLANG_FORMAT) 12 | add_custom_target( 13 | zs-clang-format 14 | COMMAND /usr/bin/clang-format 15 | -i 16 | -style=file 17 | ${ALL_SOURCE_FILES} 18 | ) 19 | endif() 20 | 21 | # Adding clang-tidy target if executable is found 22 | find_program(CLANG_TIDY "clang-tidy") 23 | if(CLANG_TIDY) 24 | add_custom_target( 25 | zs-clang-tidy 26 | COMMAND /usr/bin/clang-tidy 27 | ${ALL_SOURCE_FILES} 28 | -config='' 29 | -- 30 | -std=c++17 31 | ${INCLUDE_DIRECTORIES} 32 | ) 33 | endif() -------------------------------------------------------------------------------- /CMake/DownloadProject.CMakeLists.cmake.in: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8.2) 2 | 3 | project(${DL_ARGS_PROJ}-download NONE) 4 | 5 | include(ExternalProject) 6 | ExternalProject_Add(${DL_ARGS_PROJ}-download 7 | ${DL_ARGS_UNPARSED_ARGUMENTS} 8 | SOURCE_DIR "${DL_ARGS_SOURCE_DIR}" 9 | BINARY_DIR "${DL_ARGS_BINARY_DIR}" 10 | CONFIGURE_COMMAND "" 11 | BUILD_COMMAND "" 12 | INSTALL_COMMAND "" 13 | TEST_COMMAND "" 14 | ) 15 | -------------------------------------------------------------------------------- /CMake/DownloadProject.LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Crascit 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /CMake/FindWayland.cmake: -------------------------------------------------------------------------------- 1 | # Try to find Wayland on a Unix system 2 | # 3 | # This will define: 4 | # 5 | # WAYLAND_FOUND - True if Wayland is found 6 | # WAYLAND_LIBRARIES - Link these to use Wayland 7 | # WAYLAND_INCLUDE_DIR - Include directory for Wayland 8 | # WAYLAND_DEFINITIONS - Compiler flags for using Wayland 9 | # 10 | # In addition the following more fine grained variables will be defined: 11 | # 12 | # WAYLAND_CLIENT_FOUND WAYLAND_CLIENT_INCLUDE_DIR WAYLAND_CLIENT_LIBRARIES 13 | # WAYLAND_SERVER_FOUND WAYLAND_SERVER_INCLUDE_DIR WAYLAND_SERVER_LIBRARIES 14 | # WAYLAND_EGL_FOUND WAYLAND_EGL_INCLUDE_DIR WAYLAND_EGL_LIBRARIES 15 | # 16 | # Copyright (c) 2013 Martin Gräßlin 17 | # 18 | # Redistribution and use is allowed according to the terms of the BSD license. 19 | # For details see the accompanying COPYING-CMAKE-SCRIPTS file. 20 | 21 | IF (NOT WIN32) 22 | IF (WAYLAND_INCLUDE_DIR AND WAYLAND_LIBRARIES) 23 | # In the cache already 24 | SET(WAYLAND_FIND_QUIETLY TRUE) 25 | ENDIF () 26 | 27 | # Use pkg-config to get the directories and then use these values 28 | # in the FIND_PATH() and FIND_LIBRARY() calls 29 | FIND_PACKAGE(PkgConfig) 30 | PKG_CHECK_MODULES(PKG_WAYLAND QUIET wayland-client wayland-server wayland-egl wayland-cursor) 31 | 32 | SET(WAYLAND_DEFINITIONS ${PKG_WAYLAND_CFLAGS}) 33 | 34 | FIND_PATH(WAYLAND_CLIENT_INCLUDE_DIR NAMES wayland-client.h HINTS ${PKG_WAYLAND_INCLUDE_DIRS}) 35 | FIND_PATH(WAYLAND_SERVER_INCLUDE_DIR NAMES wayland-server.h HINTS ${PKG_WAYLAND_INCLUDE_DIRS}) 36 | FIND_PATH(WAYLAND_EGL_INCLUDE_DIR NAMES wayland-egl.h HINTS ${PKG_WAYLAND_INCLUDE_DIRS}) 37 | FIND_PATH(WAYLAND_CURSOR_INCLUDE_DIR NAMES wayland-cursor.h HINTS ${PKG_WAYLAND_INCLUDE_DIRS}) 38 | 39 | FIND_LIBRARY(WAYLAND_CLIENT_LIBRARIES NAMES wayland-client HINTS ${PKG_WAYLAND_LIBRARY_DIRS}) 40 | FIND_LIBRARY(WAYLAND_SERVER_LIBRARIES NAMES wayland-server HINTS ${PKG_WAYLAND_LIBRARY_DIRS}) 41 | FIND_LIBRARY(WAYLAND_EGL_LIBRARIES NAMES wayland-egl HINTS ${PKG_WAYLAND_LIBRARY_DIRS}) 42 | FIND_LIBRARY(WAYLAND_CURSOR_LIBRARIES NAMES wayland-cursor HINTS ${PKG_WAYLAND_LIBRARY_DIRS}) 43 | 44 | set(WAYLAND_INCLUDE_DIR ${WAYLAND_CLIENT_INCLUDE_DIR} ${WAYLAND_SERVER_INCLUDE_DIR} ${WAYLAND_EGL_INCLUDE_DIR} ${WAYLAND_CURSOR_INCLUDE_DIR}) 45 | 46 | set(WAYLAND_LIBRARIES ${WAYLAND_CLIENT_LIBRARIES} ${WAYLAND_SERVER_LIBRARIES} ${WAYLAND_EGL_LIBRARIES} ${WAYLAND_CURSOR_LIBRARIES}) 47 | 48 | list(REMOVE_DUPLICATES WAYLAND_INCLUDE_DIR) 49 | 50 | include(FindPackageHandleStandardArgs) 51 | 52 | FIND_PACKAGE_HANDLE_STANDARD_ARGS(WAYLAND_CLIENT DEFAULT_MSG WAYLAND_CLIENT_LIBRARIES WAYLAND_CLIENT_INCLUDE_DIR) 53 | FIND_PACKAGE_HANDLE_STANDARD_ARGS(WAYLAND_SERVER DEFAULT_MSG WAYLAND_SERVER_LIBRARIES WAYLAND_SERVER_INCLUDE_DIR) 54 | FIND_PACKAGE_HANDLE_STANDARD_ARGS(WAYLAND_EGL DEFAULT_MSG WAYLAND_EGL_LIBRARIES WAYLAND_EGL_INCLUDE_DIR) 55 | FIND_PACKAGE_HANDLE_STANDARD_ARGS(WAYLAND_CURSOR DEFAULT_MSG WAYLAND_CURSOR_LIBRARIES WAYLAND_CURSOR_INCLUDE_DIR) 56 | FIND_PACKAGE_HANDLE_STANDARD_ARGS(WAYLAND DEFAULT_MSG WAYLAND_LIBRARIES WAYLAND_INCLUDE_DIR) 57 | 58 | MARK_AS_ADVANCED( 59 | WAYLAND_INCLUDE_DIR WAYLAND_LIBRARIES 60 | WAYLAND_CLIENT_INCLUDE_DIR WAYLAND_CLIENT_LIBRARIES 61 | WAYLAND_SERVER_INCLUDE_DIR WAYLAND_SERVER_LIBRARIES 62 | WAYLAND_EGL_INCLUDE_DIR WAYLAND_EGL_LIBRARIES 63 | WAYLAND_CURSOR_INCLUDE_DIR WAYLAND_CURSOR_LIBRARIES 64 | ) 65 | 66 | ENDIF () 67 | -------------------------------------------------------------------------------- /CMake/FindXCB.cmake: -------------------------------------------------------------------------------- 1 | # - FindXCB 2 | # 3 | # Copyright 2015 Valve Coporation 4 | 5 | find_package(PkgConfig) 6 | 7 | if(NOT XCB_FIND_COMPONENTS) 8 | set(XCB_FIND_COMPONENTS xcb) 9 | endif() 10 | 11 | include(FindPackageHandleStandardArgs) 12 | set(XCB_FOUND true) 13 | set(XCB_INCLUDE_DIRS "") 14 | set(XCB_LIBRARIES "") 15 | foreach(comp ${XCB_FIND_COMPONENTS}) 16 | # component name 17 | string(TOUPPER ${comp} compname) 18 | string(REPLACE "-" "_" compname ${compname}) 19 | # header name 20 | string(REPLACE "xcb-" "" headername xcb/${comp}.h) 21 | # library name 22 | set(libname ${comp}) 23 | 24 | pkg_check_modules(PC_${comp} QUIET ${comp}) 25 | 26 | find_path(${compname}_INCLUDE_DIR NAMES ${headername} 27 | HINTS 28 | ${PC_${comp}_INCLUDEDIR} 29 | ${PC_${comp}_INCLUDE_DIRS} 30 | ) 31 | 32 | find_library(${compname}_LIBRARY NAMES ${libname} 33 | HINTS 34 | ${PC_${comp}_LIBDIR} 35 | ${PC_${comp}_LIBRARY_DIRS} 36 | ) 37 | 38 | find_package_handle_standard_args(${comp} 39 | FOUND_VAR ${comp}_FOUND 40 | REQUIRED_VARS ${compname}_INCLUDE_DIR ${compname}_LIBRARY) 41 | mark_as_advanced(${compname}_INCLUDE_DIR ${compname}_LIBRARY) 42 | 43 | list(APPEND XCB_INCLUDE_DIRS ${${compname}_INCLUDE_DIR}) 44 | list(APPEND XCB_LIBRARIES ${${compname}_LIBRARY}) 45 | 46 | if(NOT ${comp}_FOUND) 47 | set(XCB_FOUND false) 48 | endif() 49 | endforeach() 50 | 51 | list(REMOVE_DUPLICATES XCB_INCLUDE_DIRS) -------------------------------------------------------------------------------- /CMake/Pybind11.cmake: -------------------------------------------------------------------------------- 1 | #### Python bindings 2 | 3 | macro(do_python_bindings) 4 | 5 | if (PYTHON_EXECUTABLE) 6 | message("Using ${PYTHON_EXECUTABLE} as python executable.") 7 | else () 8 | if (WIN32) 9 | message("Using 'python' as python interpreter.") 10 | set(PYTHON_EXECUTABLE python) 11 | else () 12 | message("Using 'python3' as python interpreter.") 13 | set(PYTHON_EXECUTABLE python3) 14 | endif() 15 | endif () 16 | if (WIN32) 17 | execute_process(COMMAND where ${PYTHON_EXECUTABLE} 18 | OUTPUT_VARIABLE PYTHON_EXECUTABLE_PATH) 19 | else () 20 | execute_process(COMMAND which ${PYTHON_EXECUTABLE} 21 | OUTPUT_VARIABLE PYTHON_EXECUTABLE_PATH) 22 | endif () 23 | execute_process(COMMAND ${PYTHON_EXECUTABLE} -c 24 | "import sys;\ 25 | from distutils import sysconfig;\ 26 | sys.stdout.write(sysconfig.get_python_version())" 27 | OUTPUT_VARIABLE PYTHON_VERSION) 28 | execute_process(COMMAND ${PYTHON_EXECUTABLE} --version) 29 | execute_process(COMMAND ${PYTHON_EXECUTABLE} -c 30 | "import sys;\ 31 | from distutils import sysconfig;\ 32 | sys.stdout.write(\ 33 | (sysconfig.get_config_var('INCLUDEPY')\ 34 | if sysconfig.get_config_var('INCLUDEDIR') is not None else None)\ 35 | or sysconfig.get_python_inc())" 36 | OUTPUT_VARIABLE PYTHON_INCLUDE_DIRS) 37 | execute_process(COMMAND ${PYTHON_EXECUTABLE} -c 38 | "import sys;\ 39 | from distutils import sysconfig;\ 40 | sys.stdout.write((sysconfig.get_config_var('LIBDIR') or sysconfig.get_python_lib()).replace('\\\\','/'))" 41 | OUTPUT_VARIABLE PYTHON_LIBRARY_DIR) 42 | execute_process(COMMAND ${PYTHON_EXECUTABLE} -c 43 | "import sys;\ 44 | sys.stdout.write(str(sys.version_info[1]))" 45 | OUTPUT_VARIABLE PYTHON_MINOR_VERSION) 46 | if (WIN32) 47 | link_directories(${PYTHON_LIBRARY_DIR}/../../libs) 48 | set(PYTHON_LIBRARIES ${PYTHON_LIBRARY_DIR}/../../libs/python3.lib) 49 | set(PYTHON_LIBRARIES ${PYTHON_LIBRARY_DIR}/../../libs/python3${PYTHON_MINOR_VERSION}.lib) 50 | else() 51 | find_library(PYTHON_LIBRARY NAMES python${PYTHON_VERSION} python${PYTHON_VERSION}m PATHS ${PYTHON_LIBRARY_DIR} 52 | NO_DEFAULT_PATH NO_SYSTEM_ENVIRONMENT_PATH PATH_SUFFIXES x86_64-linux-gnu) 53 | set(PYTHON_LIBRARIES ${PYTHON_LIBRARY}) 54 | endif() 55 | include_directories(${PYTHON_INCLUDE_DIRS}) 56 | message(" version: ${PYTHON_VERSION}") 57 | message(" include: ${PYTHON_INCLUDE_DIRS}") 58 | message(" library: ${PYTHON_LIBRARIES}") 59 | 60 | execute_process(COMMAND ${PYTHON_EXECUTABLE} -c 61 | "import sys; import pybind11; sys.stdout.write(pybind11.get_include() + ';' + pybind11.get_include(True))" 62 | OUTPUT_VARIABLE PYBIND11_INCLUDE_DIR 63 | RESULT_VARIABLE PYBIND11_IMPORT_RET) 64 | if (NOT PYBIND11_IMPORT_RET) 65 | # returns zero if success 66 | message(" pybind11 include: ${PYBIND11_INCLUDE_DIR}") 67 | else () 68 | message(FATAL_ERROR "Cannot import pybind11. Please install. ([sudo] pip3 install --user pybind11)") 69 | endif () 70 | include_directories(${PYBIND11_INCLUDE_DIR}) 71 | 72 | endmacro() 73 | -------------------------------------------------------------------------------- /CMake/Sanitizers.cmake: -------------------------------------------------------------------------------- 1 | function(enable_sanitizers project_name) 2 | 3 | if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR CMAKE_CXX_COMPILER_ID MATCHES 4 | ".*Clang") 5 | option(ENABLE_COVERAGE "Enable coverage reporting for gcc/clang" FALSE) 6 | 7 | if(ENABLE_COVERAGE) 8 | target_compile_options(${project_name} INTERFACE --coverage -O0 -g) 9 | target_link_libraries(${project_name} INTERFACE --coverage) 10 | endif() 11 | 12 | set(SANITIZERS "") 13 | 14 | option(ENABLE_SANITIZER_ADDRESS "Enable address sanitizer" FALSE) 15 | if(ENABLE_SANITIZER_ADDRESS) 16 | list(APPEND SANITIZERS "address") 17 | endif() 18 | 19 | option(ENABLE_SANITIZER_MEMORY "Enable memory sanitizer" FALSE) 20 | if(ENABLE_SANITIZER_MEMORY) 21 | list(APPEND SANITIZERS "memory") 22 | endif() 23 | 24 | option(ENABLE_SANITIZER_UNDEFINED_BEHAVIOR 25 | "Enable undefined behavior sanitizer" FALSE) 26 | if(ENABLE_SANITIZER_UNDEFINED_BEHAVIOR) 27 | list(APPEND SANITIZERS "undefined") 28 | endif() 29 | 30 | option(ENABLE_SANITIZER_THREAD "Enable thread sanitizer" FALSE) 31 | if(ENABLE_SANITIZER_THREAD) 32 | list(APPEND SANITIZERS "thread") 33 | endif() 34 | 35 | list(JOIN SANITIZERS "," LIST_OF_SANITIZERS) 36 | 37 | endif() 38 | 39 | if(LIST_OF_SANITIZERS) 40 | if(NOT "${LIST_OF_SANITIZERS}" STREQUAL "") 41 | target_compile_options(${project_name} 42 | INTERFACE -fsanitize=${LIST_OF_SANITIZERS}) 43 | target_link_libraries(${project_name} 44 | INTERFACE -fsanitize=${LIST_OF_SANITIZERS}) 45 | endif() 46 | endif() 47 | 48 | endfunction() 49 | -------------------------------------------------------------------------------- /CMake/StandardProjectSettings.cmake: -------------------------------------------------------------------------------- 1 | # Set a default build type if none was specified 2 | if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) 3 | message( 4 | STATUS "Setting build type to 'RelWithDebInfo' as none was specified.") 5 | set(CMAKE_BUILD_TYPE 6 | RelWithDebInfo 7 | CACHE STRING "Choose the type of build." FORCE) 8 | # Set the possible values of build type for cmake-gui, ccmake 9 | set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release" 10 | "MinSizeRel" "RelWithDebInfo") 11 | endif() 12 | 13 | # Generate compile_commands.json to make it easier to work with clang based 14 | # tools 15 | set(CMAKE_EXPORT_COMPILE_COMMANDS ON) 16 | 17 | option(ENABLE_IPO 18 | "Enable Interprocedural Optimization, aka Link Time Optimization (LTO)" 19 | OFF) 20 | 21 | if(ENABLE_IPO) 22 | include(CheckIPOSupported) 23 | check_ipo_supported(RESULT result OUTPUT output) 24 | if(result) 25 | set(CMAKE_INTERPROCEDURAL_OPTIMIZATION TRUE) 26 | else() 27 | message(SEND_ERROR "IPO is not supported: ${output}") 28 | endif() 29 | endif() 30 | 31 | 32 | -------------------------------------------------------------------------------- /CMake/StaticAnalyzers.cmake: -------------------------------------------------------------------------------- 1 | option(ENABLE_CPPCHECK "Enable static analysis with cppcheck" OFF) 2 | option(ENABLE_CLANG_TIDY "Enable static analysis with clang-tidy" OFF) 3 | option(ENABLE_INCLUDE_WHAT_YOU_USE "Enable static analysis with include-what-you-use" OFF) 4 | 5 | if(ENABLE_CPPCHECK) 6 | find_program(CPPCHECK cppcheck) 7 | if(CPPCHECK) 8 | set(CMAKE_CXX_CPPCHECK ${CPPCHECK} --suppress=missingInclude --enable=all 9 | --inline-suppr --inconclusive -i ${CMAKE_SOURCE_DIR}/imgui/lib) 10 | else() 11 | message(SEND_ERROR "cppcheck requested but executable not found") 12 | endif() 13 | endif() 14 | 15 | if(ENABLE_CLANG_TIDY) 16 | find_program(CLANGTIDY clang-tidy) 17 | if(CLANGTIDY) 18 | set(CMAKE_CXX_CLANG_TIDY ${CLANGTIDY} -extra-arg=-Wno-unknown-warning-option) 19 | else() 20 | message(SEND_ERROR "clang-tidy requested but executable not found") 21 | endif() 22 | endif() 23 | 24 | if(ENABLE_INCLUDE_WHAT_YOU_USE) 25 | find_program(INCLUDE_WHAT_YOU_USE include-what-you-use) 26 | if(INCLUDE_WHAT_YOU_USE) 27 | set(CMAKE_CXX_INCLUDE_WHAT_YOU_USE ${INCLUDE_WHAT_YOU_USE}) 28 | else() 29 | message(SEND_ERROR "include-what-you-use requested but executable not found") 30 | endif() 31 | endif() 32 | -------------------------------------------------------------------------------- /CMake/Uninstall.cmake: -------------------------------------------------------------------------------- 1 | # Copyright Contributors to the OpenVDB Project 2 | # SPDX-License-Identifier: MPL-2.0 3 | # 4 | #[=======================================================================[.rst: 5 | 6 | Uninstall 7 | --------- 8 | 9 | Adds a custom target to the CMake build generation which allows for 10 | calling:: 11 | 12 | make uninstall 13 | 14 | to remove an installation of OpenVDB. Relies on the install_manifest 15 | existing from a previous run of cmake. 16 | 17 | #]=======================================================================] 18 | 19 | cmake_minimum_required(VERSION 3.12) 20 | 21 | set(MANIFEST "${CMAKE_CURRENT_BINARY_DIR}/install_manifest.txt") 22 | 23 | if(NOT EXISTS ${MANIFEST}) 24 | message(FATAL_ERROR "Cannot find install manifest: '${MANIFEST}'") 25 | endif() 26 | 27 | file(STRINGS ${MANIFEST} INSTALLED_FILES) 28 | foreach(INSTALLED_FILE ${INSTALLED_FILES}) 29 | if(EXISTS ${INSTALLED_FILE}) 30 | message(STATUS "Uninstalling: ${INSTALLED_FILE}") 31 | exec_program( 32 | ${CMAKE_COMMAND} ARGS "-E remove ${INSTALLED_FILE}" 33 | OUTPUT_VARIABLE stdout 34 | RETURN_VALUE RESULT 35 | ) 36 | 37 | if(NOT "${RESULT}" STREQUAL 0) 38 | message(FATAL_ERROR "Failed to remove file: '${INSTALLED_FILE}'.") 39 | endif() 40 | endif() 41 | endforeach(INSTALLED_FILE) 42 | -------------------------------------------------------------------------------- /CMake/Utility.cmake: -------------------------------------------------------------------------------- 1 | # https://stackoverflow.com/questions/4346412/how-to-prepend-all-filenames-on-the-list-with-common-path/31726284 2 | function(list_transform_prepend var prefix) 3 | set(temp "") 4 | foreach(f ${${var}}) 5 | list(APPEND temp "${prefix}${f}") 6 | endforeach() 7 | set(${var} "${temp}" PARENT_SCOPE) 8 | endfunction() 9 | 10 | -------------------------------------------------------------------------------- /CMake/get_cpm.cmake: -------------------------------------------------------------------------------- 1 | set(CPM_DOWNLOAD_VERSION 0.31.1) 2 | 3 | if(CPM_SOURCE_CACHE) 4 | # Expand relative path. This is important if the provided path contains a tilde (~) 5 | get_filename_component(CPM_SOURCE_CACHE ${CPM_SOURCE_CACHE} ABSOLUTE) 6 | set(CPM_DOWNLOAD_LOCATION "${CPM_SOURCE_CACHE}/cpm/CPM_${CPM_DOWNLOAD_VERSION}.cmake") 7 | elseif(DEFINED ENV{CPM_SOURCE_CACHE}) 8 | set(CPM_DOWNLOAD_LOCATION "$ENV{CPM_SOURCE_CACHE}/cpm/CPM_${CPM_DOWNLOAD_VERSION}.cmake") 9 | else() 10 | set(CPM_DOWNLOAD_LOCATION "${CMAKE_BINARY_DIR}/cmake/CPM_${CPM_DOWNLOAD_VERSION}.cmake") 11 | endif() 12 | 13 | if(NOT (EXISTS ${CPM_DOWNLOAD_LOCATION})) 14 | message(STATUS "Downloading CPM.cmake to ${CPM_DOWNLOAD_LOCATION}") 15 | file(DOWNLOAD 16 | https://github.com/cpm-cmake/CPM.cmake/releases/download/v${CPM_DOWNLOAD_VERSION}/CPM.cmake 17 | ${CPM_DOWNLOAD_LOCATION} 18 | ) 19 | endif() 20 | 21 | include(${CPM_DOWNLOAD_LOCATION}) 22 | -------------------------------------------------------------------------------- /CMake/zensim-config.cmake.in: -------------------------------------------------------------------------------- 1 | # 2 | # build option variables 3 | # 4 | # https://cmake.org/cmake/help/latest/module/CMakePackageConfigHelpers.html 5 | set(ZECOMP_DIR "@CMAKE_INSTALL_PREFIX@/@CMAKE_INSTALL_LIBDIR@/@project_name@") 6 | set(ZS_ENABLE_OPENMP @ZS_ENABLE_OPENMP@) 7 | set(ZS_ENABLE_CUDA @ZS_ENABLE_CUDA@) 8 | set(ZS_ENABLE_OPENVDB @ZS_ENABLE_OPENVDB@) 9 | set(ZS_BUILD_SHARED_LIBS @ZS_BUILD_SHARED_LIBS@) 10 | set(ZECOMP_LINK_DIRECTORY @CMAKE_INSTALL_PREFIX@/@CMAKE_INSTALL_LIBDIR@/@PROJECT_NAME@) 11 | 12 | message("[Option:ZS_ENABLE_CUDA] = @ZS_ENABLE_CUDA@") 13 | message("[Option:ZS_ENABLE_OPENVDB] = @ZS_ENABLE_OPENVDB@") 14 | message("[Option:LIB_INSTALL_PREFIX] = @CMAKE_INSTALL_PREFIX@/@CMAKE_INSTALL_LIBDIR@/@PROJECT_NAME@") 15 | 16 | # 17 | # dependency 18 | # 19 | include(CMakeFindDependencyMacro) 20 | 21 | find_dependency(Threads REQUIRED) 22 | find_dependency(OpenMP REQUIRED) 23 | if (ZS_ENABLE_OPENGL) 24 | find_dependency(OpenGL) 25 | endif() 26 | if (ZS_ENABLE_OPENVDB) 27 | list(APPEND CMAKE_MODULE_PATH /usr/local/lib/cmake/OpenVDB/) # openvdb's default linux install location 28 | find_package(OpenVDB) 29 | endif() 30 | if (ZS_ENABLE_CUDA) 31 | find_package(CUDAToolkit) 32 | endif() 33 | find_dependency(ZLIB) 34 | 35 | # 36 | # zensim 37 | # 38 | @PACKAGE_INIT@ 39 | list(APPEND CMAKE_MODULE_PATH "@PACKAGE_cmakeModulesDir@") 40 | include("${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@-targets.cmake") 41 | 42 | # setup _IMPORT_PREFIX! 43 | set(_IMPORT_PREFIX "${CMAKE_CURRENT_LIST_DIR}") 44 | foreach(i RANGE 1 3) 45 | get_filename_component(_IMPORT_PREFIX "${_IMPORT_PREFIX}" PATH) 46 | if(_IMPORT_PREFIX STREQUAL "/") 47 | set(_IMPORT_PREFIX "") 48 | break() 49 | endif() 50 | endforeach() 51 | 52 | message("import prefix is: ${_IMPORT_PREFIX}") 53 | get_filename_component(_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH) 54 | file(GLOB CONFIG_FILES "${_DIR}/@PROJECT_NAME@-targets-*.cmake") 55 | foreach(f ${CONFIG_FILES}) 56 | message("iterating config file ${f}") 57 | include(${f}) 58 | endforeach() 59 | 60 | # for non-cmake library import 61 | # message(${_IMPORT_PREFIX}/@CMAKE_INSTALL_LIBDIR@/@PROJECT_NAME@/) 62 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Zenus Simulation 2 | *Zenus Simulation* is the codebase **zensim** maintained by **Zenus Tech**, which delivers great parallel computing efficiency for physics-based simulations within a shared-memory heterogeneous architecture through a unified programming interface on multiple compute backends. 3 | 4 | This repo is going through rapid changes, and we do not promise ABI compatibility from commit to commit for the moment. 5 | 6 | ## **Document** 7 | See [git wiki](https://github.com/zensim-dev/zpc/wiki) page for more build details. 8 | See [Specification](Specification.md) for more usage info. 9 | 10 | ## **Compilation** 11 | This is a cross-platform C++/CUDA cmake project. The minimum version requirement of cmake is 3.18, yet the latest version is generally recommended. Please install cmake through official website or python3-pip, since the cmake version in apt repo is behind. 12 | 13 | When CUDA is enabled, the required CUDA version is 11.4+ (for c++17 and latest cuda utilities). 14 | 15 | Currently, *supported OS* are Ubuntu 20.04+ and Windows 10, and *tested compilers* includes gcc10.0+, clang-11+, vs2019+. 16 | 17 | ### **Build** 18 | 19 | Before building this framework, please first manually configure these external dependencies, i.e. [**openvdb**](https://github.com/AcademySoftwareFoundation/openvdb) if ZS_ENABLE_OPENVDB is set to TRUE. Then pull all dependencies by 20 | 21 | ``` 22 | git submodule init 23 | git submodule update 24 | ``` 25 | 26 | If CUDA (>=11.4) is installed and required, be sure to set *ZS_ENABLE_CUDA=On* first. 27 | 28 | Configure the project using the *CMake Tools* extension in *Visual Studio Code* (recommended), or follow the build instructions in [git wiki](https://github.com/zensim-dev/zpc/wiki). 29 | 30 | In addition, make sure to install *zlib* for building *partio* when building on linux. 31 | ``` 32 | sudo apt install zlib1g 33 | ``` 34 | 35 | ## **Integration** 36 | 37 | Directly include the codebase as a submodule. Or install this repo then use *find_package(zensim)*. 38 | If the installed package is no longer needed, build the *uninstall* target as with the *install* target. 39 | 40 | ## **Credits** 41 | This framework draws inspirations from [Taichi](https://github.com/taichi-dev/taichi), [kokkos](https://github.com/kokkos/kokkos), [raja](https://github.com/LLNL/RAJA), [MGMPM](https://github.com/penn-graphics-research/claymore), [GPU LBVH](https://github.com/littlemine/BVH-based-Collision-Detection-Scheme). 42 | 43 | ### **Dependencies** 44 | The following libraries are adopted and made fully localized in our project development: 45 | - [fmt](https://fmt.dev/latest/index.html) 46 | - [loguru](https://github.com/emilk/loguru). (pro: "chrono" is not exposed in its header) 47 | - [magic_enum](https://github.com/Neargye/magic_enum) 48 | - [catch2](https://github.com/catchorg/Catch2) 49 | 50 | For spatial data IO and generation, we use these libraries in addition: 51 | 52 | - [partio](http://partio.us/) 53 | - [openvdb](https://github.com/AcademySoftwareFoundation/openvdb) 54 | 55 | We import these (less-frequently used) libraries as well: 56 | 57 | - [function_ref](https://github.com/TartanLlama/function_ref) 58 | - [rapidjson](https://github.com/Tencent/rapidjson) 59 | - [cxxopts](https://github.com/jarro2783/cxxopts) 60 | - [jitify](https://github.com/NVIDIA/jitify) 61 | -------------------------------------------------------------------------------- /docs/doxygen.rst: -------------------------------------------------------------------------------- 1 | Documentation by Doxygen + Breathe 2 | ============================================ 3 | 4 | .. doxygenindex:: 5 | :project: zpc_docs_doxygen -------------------------------------------------------------------------------- /docs/index.rst: -------------------------------------------------------------------------------- 1 | .. toctree:: 2 | :caption: Overview 3 | :maxdepth: 2 4 | 5 | overview 6 | 7 | .. toctree:: 8 | :caption: APIs 9 | :maxdepth: 3 10 | 11 | doxygen -------------------------------------------------------------------------------- /docs/overview.rst: -------------------------------------------------------------------------------- 1 | Overview 2 | ============= 3 | 4 | Zensim is short for Zenus Simulation, which is an open-source C++ library designed for high-performance physics-based simulations. It is built upon a highly efficient parallel computing framework called ZPC, i.e. Zenus Parallel Compute, that offers a c++stl-like and consistent programming interface for multiple compute back-ends including OpenMP, Cuda, etc., and a series of efficient, highly-customizable and commonly used data structures. 5 | 6 | Currently, ZPC mainly handles computations within a shared-memory heterogeneous architecture. Hopefully it may extend to a distributed system in the near future. 7 | 8 | Zensim is and will be continuously developed and maintained by Zenus Tech Co. Ltd. to provide better support for simulation-related research and development, especially for practical real-world problems. And we welcome more people to take part in the growth and improvement of this project. Please contact us (wxlwxl1993@zju.edu.cn, zhangshinshin@gmail.com) if you are interested. 9 | 10 | This repo is currently going through rapid changes, and we do not promise ABI compatibility from commit to commit for the moment. -------------------------------------------------------------------------------- /include/zensim/Logger.cpp: -------------------------------------------------------------------------------- 1 | #include "Logger.hpp" 2 | #include "zensim/execution/ConcurrencyPrimitive.hpp" 3 | 4 | namespace { 5 | static zs::Mutex g_loggerMutex; 6 | static std::atomic g_isLoggerInitialized = false; 7 | static zs::Logger *g_loggerInstance = nullptr; 8 | } 9 | 10 | namespace zs { 11 | 12 | Logger &Logger::instance() { 13 | if (g_isLoggerInitialized.load(std::memory_order_acquire)) return *g_loggerInstance; 14 | g_loggerMutex.lock(); 15 | if (g_isLoggerInitialized.load(std::memory_order_acquire)) return *g_loggerInstance; 16 | 17 | if (!g_loggerInstance) g_loggerInstance = new Logger; 18 | 19 | g_isLoggerInitialized.store(true, std::memory_order_release); 20 | g_loggerMutex.unlock(); 21 | return *g_loggerInstance; 22 | } 23 | 24 | } // namespace zs -------------------------------------------------------------------------------- /include/zensim/Logger.hpp: -------------------------------------------------------------------------------- 1 | /// reference: taichi/common/core.h 2 | #pragma once 3 | 4 | #include "Platform.hpp" 5 | #include "plog/Initializers/RollingFileInitializer.h" 6 | #include "zensim/zpc_tpls/fmt/format.h" 7 | #include "zensim/zpc_tpls/plog/Log.h" 8 | 9 | namespace zs { 10 | 11 | // Reference: 12 | // https://blog.kowalczyk.info/article/j/guide-to-predefined-macros-in-c-compilers-gcc-clang-msvc-etc..html 13 | 14 | struct Logger { 15 | void log(const int level, const char* fileName, const char* funcName, int line, 16 | std::string_view msg) { 17 | PLOG(static_cast(level)) 18 | << fmt::format("{}:{}{} {}\n", fileName, funcName, line, msg); 19 | } 20 | ZPC_BACKEND_API static Logger& instance(); 21 | 22 | private: 23 | Logger() { plog::init(plog::info, "zensim_logs.log"); } 24 | }; 25 | 26 | /// 27 | 28 | #define ZS_LOG(option, ...) \ 29 | ::zs::Logger::instance().log(plog::Severity::option, __FILE__, __FUNCTION__, (int)__LINE__, \ 30 | __VA_ARGS__); 31 | 32 | #define ZS_FATAL(...) ZS_LOG(fatal, __VA_ARGS__) 33 | #define ZS_INFO(...) ZS_LOG(info, __VA_ARGS__) 34 | #define ZS_WARN(...) ZS_LOG(warning, __VA_ARGS__) 35 | #define ZS_ERROR(...) \ 36 | { \ 37 | ZS_LOG(error, __VA_ARGS__); \ 38 | ZS_UNREACHABLE; \ 39 | } 40 | 41 | #define ZS_ERROR_IF(condition, ...) \ 42 | if (condition) { \ 43 | ZS_ERROR(__VA_ARGS__); \ 44 | } 45 | #define ZS_WARN_IF(condition, ...) \ 46 | if (condition) { \ 47 | ZS_WARN(__VA_ARGS__); \ 48 | } 49 | 50 | } // namespace zs 51 | -------------------------------------------------------------------------------- /include/zensim/Reflection.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "zensim/ZpcReflection.hpp" 3 | 4 | /* 5 | 6 | Copyright(c) 2018 Robert Osfield 7 | 8 | Permission is hereby granted, free of charge, to any person obtaining a copy of 9 | this software and associated documentation files (the "Software"), to deal in 10 | the Software without restriction, including without limitation the rights to 11 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 12 | the Software, and to permit persons to whom the Software is furnished to do so, 13 | subject to the following conditions: 14 | 15 | The above copyright notice and this permission notice shall be included in all 16 | copies or substantial portions of the Software. 17 | 18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 20 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 21 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 22 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 23 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | 25 | */ 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | #include "zensim/execution/Stacktrace.hpp" 33 | namespace zs { 34 | 35 | template constexpr const char *type_name() noexcept { return typeid(T).name(); } 36 | template std::string demangle() { return Kokkos::Impl::demangle(type_name()); } 37 | 38 | template constexpr const char *type_name(const T &) noexcept { 39 | return type_name(); 40 | } 41 | template std::string demangle(const T &) { 42 | return Kokkos::Impl::demangle(type_name()); 43 | } 44 | 45 | template <> constexpr const char *type_name() noexcept { return "string"; } 46 | template <> constexpr const char *type_name() noexcept { return "char"; } 47 | template <> constexpr const char *type_name() noexcept { return "char"; } 48 | template <> constexpr const char *type_name() noexcept { return "uchar"; } 49 | template <> constexpr const char *type_name() noexcept { return "short"; } 50 | template <> constexpr const char *type_name() noexcept { return "ushort"; } 51 | template <> constexpr const char *type_name() noexcept { return "int"; } 52 | template <> constexpr const char *type_name() noexcept { return "uint"; } 53 | template <> constexpr const char *type_name() noexcept { return "float"; } 54 | template <> constexpr const char *type_name() noexcept { return "double"; } 55 | 56 | } // namespace zs 57 | -------------------------------------------------------------------------------- /include/zensim/Singleton.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | namespace zs { 5 | 6 | /* 7 | * @note Singleton 8 | */ 9 | enum singleton_op_e { init = 0, reinit, deinit, query }; 10 | template struct Singleton { 11 | /// @brief allow early deinitialization, recreation, initialization with params, etc. 12 | static T *maintain(singleton_op_e op) { 13 | /// ref: CppCon 2018: Greg Falcon “Initialization, Shutdown, and constexpr” 14 | // avoid destruction issues 15 | static T *p_instance = new T(); 16 | // create if instance is absent 17 | if (op == singleton_op_e::init) { 18 | if (p_instance == nullptr) p_instance = new T(); 19 | } else if (op == singleton_op_e::reinit) { 20 | if (p_instance) delete p_instance; 21 | p_instance = new T(); 22 | } else if (op == singleton_op_e::deinit) { 23 | if (p_instance) delete p_instance; 24 | p_instance = nullptr; 25 | } else if (op == singleton_op_e::query) { 26 | // return p_instance; 27 | } else { 28 | throw std::runtime_error("Please use a valid op index for maintenance!"); 29 | } 30 | return p_instance; 31 | } 32 | 33 | static T &instance() { return *maintain(singleton_op_e::init); } 34 | static bool initialized() { return maintain(singleton_op_e::query) != nullptr ? true : false; } 35 | }; 36 | 37 | } // namespace zs 38 | -------------------------------------------------------------------------------- /include/zensim/ZensimExport.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // https://abseil.io/docs/cpp/platforms/macros 4 | 5 | #ifndef ZENSIM_EXPORT 6 | # if defined(_MSC_VER) || defined(__CYGWIN__) 7 | # ifdef Zensim_EXPORT 8 | # define ZENSIM_EXPORT __declspec(dllexport) 9 | # else 10 | # define ZENSIM_EXPORT __declspec(dllimport) 11 | # endif 12 | # elif defined(__clang__) || defined(__GNUC__) 13 | # define ZENSIM_EXPORT __attribute__((visibility("default"))) 14 | # endif 15 | #endif 16 | -------------------------------------------------------------------------------- /include/zensim/Zpc.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "zensim/Platform.hpp" 3 | 4 | namespace zs { 5 | 6 | ZPC_API void initialize(); 7 | 8 | } -------------------------------------------------------------------------------- /include/zensim/ZpcImplPattern.cpp: -------------------------------------------------------------------------------- 1 | #include "ZpcImplPattern.hpp" 2 | 3 | #include "zensim/visitors/ObjectVisitor.hpp" 4 | 5 | namespace zs { 6 | 7 | // void VisitableObjectConcept::accept(ObjectVisitor& visitor) { visitor.visit(*this); } 8 | 9 | } // namespace zs -------------------------------------------------------------------------------- /include/zensim/ZpcInitialization.cpp: -------------------------------------------------------------------------------- 1 | #include "zensim/Zpc.hpp" 2 | #include "zensim/execution/ConcurrencyPrimitive.hpp" 3 | 4 | #include "zensim/io/IO.h" 5 | #if ZS_ENABLE_CUDA 6 | # include "zensim/cuda/Cuda.h" 7 | #endif 8 | #if ZS_ENABLE_VULKAN 9 | # include "zensim/vulkan/Vulkan.hpp" 10 | #endif 11 | #include "zensim/Logger.hpp" 12 | 13 | namespace { 14 | static zs::Mutex g_zpcInitMutex; 15 | static std::atomic g_isZpcInitialized = false; 16 | } // namespace 17 | 18 | namespace zs { 19 | 20 | void initialize() { 21 | if (g_isZpcInitialized.load(std::memory_order_acquire)) return; 22 | g_zpcInitMutex.lock(); 23 | if (g_isZpcInitialized.load(std::memory_order_acquire)) return; 24 | 25 | (void)IO::instance(); 26 | 27 | #if ZS_ENABLE_CUDA 28 | (void)Cuda::instance(); 29 | #endif 30 | 31 | #if ZS_ENABLE_VULKAN 32 | (void)Vulkan::instance(); 33 | #endif 34 | 35 | g_isZpcInitialized.store(true, std::memory_order_release); 36 | g_zpcInitMutex.unlock(); 37 | } 38 | 39 | } // namespace zs -------------------------------------------------------------------------------- /include/zensim/container/Bht.cpp: -------------------------------------------------------------------------------- 1 | #include "Bht.hpp" 2 | 3 | namespace zs { 4 | 5 | #define INSTANTIATE_BHT(CoordIndexType, IndexType, B) \ 6 | ZPC_INSTANTIATE_STRUCT bht>; \ 7 | ZPC_INSTANTIATE_STRUCT bht>; \ 8 | ZPC_INSTANTIATE_STRUCT bht>; \ 9 | ZPC_INSTANTIATE_STRUCT bht>; \ 10 | ZPC_INSTANTIATE_STRUCT bht>; \ 11 | ZPC_INSTANTIATE_STRUCT bht>; \ 12 | ZPC_INSTANTIATE_STRUCT bht>; \ 13 | ZPC_INSTANTIATE_STRUCT bht>; 14 | 15 | INSTANTIATE_BHT(i32, i32, 16) 16 | INSTANTIATE_BHT(i32, i64, 16) 17 | 18 | } // namespace zs -------------------------------------------------------------------------------- /include/zensim/container/Callables.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | #include "zensim/ZpcFunction.hpp" 5 | 6 | namespace zs { 7 | 8 | namespace detail { 9 | struct DummyMutex { 10 | static constexpr void lock() noexcept { return; } 11 | static constexpr void unlock() noexcept { return; } 12 | static constexpr bool try_lock() noexcept { return true; } 13 | }; 14 | } // namespace detail 15 | 16 | template struct callbacks; 17 | 18 | template 19 | 20 | struct callbacks : M { 21 | static_assert((!is_rvalue_reference_v && ...), "callbacks do not allow rvalue arguments"); 22 | using Id = i32; 23 | using F = function; 24 | 25 | callbacks() = default; 26 | ~callbacks() = default; 27 | callbacks(callbacks&& o) noexcept : _funcs{zs::move(o._funcs)}, _n{o._n} { o._n = 0; } 28 | callbacks& operator=(callbacks&& o) noexcept { 29 | _funcs = zs::move(o._funcs); 30 | _n = o._n; 31 | o._n = 0; 32 | return *this; 33 | } 34 | callbacks(const callbacks& o) noexcept : _funcs{o._funcs}, _n{o._n} {} 35 | callbacks& operator=(const callbacks& o) noexcept { 36 | _funcs = o._funcs; 37 | _n = o._n; 38 | return *this; 39 | } 40 | 41 | template > = 0> Id insert(F&& f) { 42 | Id ret; 43 | M::lock(); 44 | ret = _n++; 45 | _funcs.emplace(ret, FWD(f)); 46 | M::unlock(); 47 | return ret; 48 | } 49 | template > = 0> 50 | callbacks& operator=(F&& f) { 51 | clear(); 52 | insert(FWD(f)); 53 | return *this; 54 | } 55 | template > = 0> 56 | void assign(Id id, F&& f) { 57 | M::lock(); 58 | _funcs.insert_or_assign(id, FWD(f)); 59 | M::unlock(); 60 | } 61 | 62 | void erase(Id i) { 63 | M::lock(); 64 | _funcs.erase(i); 65 | M::unlock(); 66 | } 67 | void clear() { 68 | M::lock(); 69 | _funcs.clear(); 70 | M::unlock(); 71 | } 72 | 73 | explicit operator bool() const noexcept { return _funcs.size() != 0; } 74 | void operator()(Args... args) const { 75 | M::lock(); 76 | for (const auto& [id, f] : _funcs) f(forward(args)...); 77 | M::unlock(); 78 | } 79 | 80 | private: 81 | std::map _funcs{}; 82 | Id _n = 0; 83 | }; 84 | 85 | } // namespace zs -------------------------------------------------------------------------------- /include/zensim/container/Container.md: -------------------------------------------------------------------------------- 1 | **Vector** 2 | ============== 3 | Similar to *std::vector*, *zs::Vector* is a container which stores elements contiguously in memory. Both adopt similar implementation guidelines, including rule of 5, RAII, etc.. But they are fundamentally different by design. 4 | 5 | It (currently) adopts **umpire::strategy::MixedPool** as the go-to allocator for the memory management. There is no allocator handle within *Vector* object, and the underlying allocator is opaque to user. However, users can specify the **memory space** (CPU or GPU) and **processor id** (-1 for CPU and 0+ for GPU indices) during construction, and they should be careful about which **execution space** the vector object is accessed, e.g. access a vector element stored in GPU locally should not be accessed on the host side, unless it is unified memory. 6 | 7 | The requirement of the element type is relatively more strict than std::vector, i.e. std::is_trivial should hold true, to be able to complete memory operations on the host side, even though the underlying memory space is not. Only when std::is_trivially_copyable holds true can one safely copy the vector elements around, even among different memory spaces and processors, no need to call elements' ctors or assignment operators. 8 | 9 | # Type specification 10 | ```cpp 11 | #include "zensim/container/Vector.hpp" 12 | Vector var{...}; //< T is the element type 13 | ``` 14 | 15 | # Construct 16 | See Library/resource/Resource.h for info regarding memory space. 17 | See Library/execution/ExecutionPolicy.h for info regarding processor id. 18 | Copy constructors are exception safe. 19 | Move constructors follow the guidelines. 20 | See Library/container/Vector.hpp for more details. 21 | 22 | ```cpp 23 | Vector a{memsrc_e::um, -1}; ///< "default" ctor, stored on host 24 | Vector b{10, memsrc_e::um, 0}; ///< allocate an array of 10 elements within unified memory, preferred storage location is 0-th GPU 25 | Vector c{b}; ///< a copy from b 26 | Vector d{std::move(b)}; ///< moved from b 27 | ``` 28 | 29 | # Iterator 30 | ```cpp 31 | /// ranged-for way 32 | for (auto &e : a) 33 | e...; 34 | /// indexed-way 35 | for (auto iter = a.begin(), ed = a.end(); iter != ed; ++iter) 36 | *iter...; 37 | ``` 38 | 39 | # Access 40 | ```cpp 41 | a(3); ///< access 3-th element (valid on both host side and device side) 42 | a[4]; ///< access 4-th element (only valid on host side) 43 | ``` 44 | 45 | # resize, assignment, ... 46 | ```cpp 47 | d.resize(20); 48 | b = a; 49 | c = std::move(a); 50 | b.capacity(); 51 | b.size(); 52 | b.empty(); 53 | ``` 54 | 55 | # insert, push_back, emplace_back 56 | todo 57 | 58 | **TileVector** 59 | ============== 60 | TileVector resembles *Cabana* in that both adopt an aosoa-style layout. For particle and grid structure build. 61 | 62 | 63 | **Hash Table** 64 | ============== 65 | Unlike std::unordered_map, HashTable is a lot more . There are basically three types of hash tables. 66 | 1. for sparse matrix (small hash tables for rows/columns) 67 | 2. integer hash table 68 | 3. tuple hash table 69 | 70 | Maintenance operations can only be called one at a time, e.g. there should not be more than one type of these opertions (insert, query or delete) under execution at the same time. 71 | -------------------------------------------------------------------------------- /include/zensim/container/DenseField.cpp: -------------------------------------------------------------------------------- 1 | #include "DenseField.hpp" 2 | 3 | namespace zs { 4 | 5 | ZPC_INSTANTIATE_STRUCT DenseField>; 6 | ZPC_INSTANTIATE_STRUCT DenseField>; 7 | ZPC_INSTANTIATE_STRUCT DenseField>; 8 | ZPC_INSTANTIATE_STRUCT DenseField>; 9 | ZPC_INSTANTIATE_STRUCT DenseField>; 10 | ZPC_INSTANTIATE_STRUCT DenseField>; 11 | ZPC_INSTANTIATE_STRUCT DenseField>; 12 | ZPC_INSTANTIATE_STRUCT DenseField>; 13 | 14 | ZPC_INSTANTIATE_STRUCT DenseField>; 15 | ZPC_INSTANTIATE_STRUCT DenseField>; 16 | ZPC_INSTANTIATE_STRUCT DenseField>; 17 | ZPC_INSTANTIATE_STRUCT DenseField>; 18 | ZPC_INSTANTIATE_STRUCT DenseField>; 19 | ZPC_INSTANTIATE_STRUCT DenseField>; 20 | ZPC_INSTANTIATE_STRUCT DenseField>; 21 | ZPC_INSTANTIATE_STRUCT DenseField>; 22 | 23 | } // namespace zs -------------------------------------------------------------------------------- /include/zensim/container/DenseGrid.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | #include "zensim/math/Vec.h" 5 | 6 | namespace zs { 7 | 8 | template vec excl_suffix_prod(const vec &dims) { 9 | vec ret{}; 10 | ret[dim - 1] = (Tn)1; 11 | for (int d = dim - 2; d >= 0; --d) ret[d] = ret[d + 1] * dims[d + 1]; 12 | return ret; 13 | } 14 | 15 | template struct DenseGrid { 16 | using IV = vec; 17 | 18 | Tn offset(const vec &indices) const noexcept { 19 | Tn ret{0}; 20 | for (int d = 0; d < dim; ++d) ret += indices[d] * weights[d]; 21 | return ret; 22 | } 23 | 24 | DenseGrid(const IV &dimsIn, T val) noexcept 25 | : weights{excl_suffix_prod(dimsIn)}, dims{dimsIn}, grid(weights.prod(), val) {} 26 | DenseGrid(IV &&dimsIn, T val) noexcept 27 | : weights{excl_suffix_prod(dimsIn)}, dims{dimsIn}, grid(weights.prod(), val) {} 28 | 29 | T operator()(const IV &indices) const { return grid[offset(indices)]; } 30 | T &operator()(const IV &indices) { return grid[offset(indices)]; } 31 | 32 | Tn domain(size_t d) const noexcept { return dims(d); } 33 | 34 | IV weights{}; 35 | IV dims{}; 36 | std::vector grid{}; 37 | }; 38 | 39 | } // namespace zs 40 | -------------------------------------------------------------------------------- /include/zensim/container/FiniteStateMachine.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "zensim/types/Optional.h" 3 | #include "zensim/types/Polymorphism.h" 4 | 5 | namespace zs { 6 | 7 | template class FSM { 8 | public: 9 | FSM(StateVariant&& state) : _state(state) {} 10 | template void dispatch(Event&& event) { 11 | Derived& self = static_cast(*this); 12 | auto newState = match(_state)([&](auto& s) -> optional { 13 | return self.onEvent(s, forward(event)); 14 | }); 15 | //[&](auto & s) ->optional { return self.onEvent(s, (event)); }); 16 | if (newState) _state = *std::move(newState); 17 | } 18 | 19 | private: 20 | StateVariant _state; 21 | }; 22 | 23 | } // namespace zs 24 | -------------------------------------------------------------------------------- /include/zensim/container/HashTable.cpp: -------------------------------------------------------------------------------- 1 | #include "HashTable.hpp" 2 | 3 | namespace zs { 4 | 5 | #define INSTANTIATE_HASHTABLE(CoordIndexType, IndexType) \ 6 | ZPC_INSTANTIATE_STRUCT HashTable>; \ 7 | ZPC_INSTANTIATE_STRUCT HashTable>; \ 8 | ZPC_INSTANTIATE_STRUCT HashTable>; \ 9 | ZPC_INSTANTIATE_STRUCT HashTable>; \ 10 | ZPC_INSTANTIATE_STRUCT HashTable>; \ 11 | ZPC_INSTANTIATE_STRUCT HashTable>; \ 12 | ZPC_INSTANTIATE_STRUCT HashTable>; \ 13 | ZPC_INSTANTIATE_STRUCT HashTable>; 14 | 15 | INSTANTIATE_HASHTABLE(i32, i32) 16 | INSTANTIATE_HASHTABLE(i32, i64) 17 | // INSTANTIATE_HASHTABLE(i64, i64) 18 | 19 | } // namespace zs -------------------------------------------------------------------------------- /include/zensim/container/RingBuffer.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "zensim/math/Vec.h" 3 | 4 | namespace zs { 5 | 6 | template struct RingBuffer { 7 | constexpr RingBuffer() : _head{1}, _tail{0}, _size{0} {} 8 | 9 | /// maintainence operation 10 | constexpr void push_back() noexcept { 11 | incTail(); 12 | if (_size > Size) incHead(); 13 | } 14 | constexpr void push_back(const T &element) noexcept { 15 | incTail(); 16 | if (_size > Size) incHead(); 17 | back() = element; 18 | } 19 | constexpr void push_back(T &&element) noexcept { 20 | incTail(); 21 | if (_size > Size) incHead(); 22 | back() = zs::move(element); 23 | } 24 | constexpr void pop() { decTail(); } 25 | 26 | /// element access 27 | constexpr T &back() noexcept { return _buf(_tail); } 28 | constexpr T const &back() const noexcept { return _buf(_tail); } 29 | constexpr T &operator[](int index) noexcept { 30 | index += _head; 31 | index %= Size; 32 | return _buf[index]; 33 | } 34 | constexpr T const &operator[](int index) const noexcept { 35 | index += _head; 36 | index %= Size; 37 | return _buf[index]; 38 | } 39 | constexpr int size() { return _size; } 40 | 41 | protected: 42 | constexpr void incTail() noexcept { 43 | ++_tail, ++_size; 44 | if (_tail == Size) _tail = 0; 45 | } 46 | constexpr void decTail() noexcept { 47 | if (_size == 0) return; 48 | --_tail, --_size; 49 | if (_tail < 0) _tail = Size - 1; 50 | } 51 | constexpr void incHead() noexcept { 52 | if (_size == 0) return; 53 | ++_head, --_size; 54 | if (_head == Size) _head = 0; 55 | } 56 | 57 | vec _buf; 58 | int _head, _tail, _size; 59 | }; 60 | 61 | } // namespace zs 62 | -------------------------------------------------------------------------------- /include/zensim/container/TileVector.cpp: -------------------------------------------------------------------------------- 1 | #include "TileVector.hpp" 2 | 3 | namespace zs { 4 | 5 | #define INSTANTIATE_TILEVECTOR(LENGTH) \ 6 | ZPC_INSTANTIATE_STRUCT TileVector>; \ 7 | ZPC_INSTANTIATE_STRUCT TileVector>; \ 8 | ZPC_INSTANTIATE_STRUCT TileVector>; \ 9 | ZPC_INSTANTIATE_STRUCT TileVector>; \ 10 | ZPC_INSTANTIATE_STRUCT TileVector>; \ 11 | ZPC_INSTANTIATE_STRUCT TileVector>; \ 12 | ZPC_INSTANTIATE_STRUCT TileVector>; \ 13 | ZPC_INSTANTIATE_STRUCT TileVector>; \ 14 | ZPC_INSTANTIATE_STRUCT TileVector>; \ 15 | ZPC_INSTANTIATE_STRUCT TileVector>; \ 16 | ZPC_INSTANTIATE_STRUCT TileVector>; \ 17 | ZPC_INSTANTIATE_STRUCT TileVector>; 18 | 19 | /// 8, 32, 64, 512 20 | INSTANTIATE_TILEVECTOR(8) 21 | INSTANTIATE_TILEVECTOR(32) 22 | INSTANTIATE_TILEVECTOR(64) 23 | INSTANTIATE_TILEVECTOR(512) 24 | 25 | } // namespace zs -------------------------------------------------------------------------------- /include/zensim/container/Vector.cpp: -------------------------------------------------------------------------------- 1 | #include "Vector.hpp" 2 | 3 | namespace zs { 4 | 5 | ZPC_INSTANTIATE_STRUCT Vector>; 6 | ZPC_INSTANTIATE_STRUCT Vector>; 7 | ZPC_INSTANTIATE_STRUCT Vector>; 8 | ZPC_INSTANTIATE_STRUCT Vector>; 9 | ZPC_INSTANTIATE_STRUCT Vector>; 10 | ZPC_INSTANTIATE_STRUCT Vector>; 11 | ZPC_INSTANTIATE_STRUCT Vector>; 12 | ZPC_INSTANTIATE_STRUCT Vector>; 13 | 14 | ZPC_INSTANTIATE_STRUCT Vector>; 15 | ZPC_INSTANTIATE_STRUCT Vector>; 16 | ZPC_INSTANTIATE_STRUCT Vector>; 17 | ZPC_INSTANTIATE_STRUCT Vector>; 18 | ZPC_INSTANTIATE_STRUCT Vector>; 19 | ZPC_INSTANTIATE_STRUCT Vector>; 20 | ZPC_INSTANTIATE_STRUCT Vector>; 21 | ZPC_INSTANTIATE_STRUCT Vector>; 22 | 23 | } // namespace zs -------------------------------------------------------------------------------- /include/zensim/cuda/CudaLaunchConfig.cuh: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | #include 5 | 6 | #include "zensim/ZpcMeta.hpp" 7 | 8 | namespace zs { 9 | 10 | struct LaunchConfig { 11 | LaunchConfig() = default; 12 | template LaunchConfig(IndexType0 gs, IndexType1 bs) 13 | : dg{static_cast(gs)}, 14 | db{static_cast(bs)}, 15 | shmem{0}, 16 | sid{cudaStreamDefault}, 17 | autoConfig{false} {} 18 | template 19 | LaunchConfig(IndexType0 gs, IndexType1 bs, IndexType2 mem) 20 | : dg{static_cast(gs)}, 21 | db{static_cast(bs)}, 22 | shmem{static_cast(mem)}, 23 | sid{cudaStreamDefault}, 24 | autoConfig{false} {} 25 | template 26 | LaunchConfig(IndexType0 gs, IndexType1 bs, IndexType2 mem, cudaStream_t stream) 27 | : dg{static_cast(gs)}, 28 | db{static_cast(bs)}, 29 | shmem{static_cast(mem)}, 30 | sid{stream}, 31 | autoConfig{false} {} 32 | 33 | template LaunchConfig(true_type, IndexType0 nwork) 34 | : dg{}, 35 | db{static_cast(nwork)}, 36 | shmem{0}, 37 | sid{cudaStreamDefault}, 38 | autoConfig{true} {} 39 | template 40 | LaunchConfig(true_type, IndexType0 nwork, IndexType1 mem) 41 | : dg{}, 42 | db{static_cast(nwork)}, 43 | shmem{static_cast(mem)}, 44 | sid{cudaStreamDefault}, 45 | autoConfig{true} {} 46 | template 47 | LaunchConfig(true_type, IndexType0 nwork, IndexType1 mem, cudaStream_t stream) 48 | : dg{}, 49 | db{static_cast(nwork)}, 50 | shmem{static_cast(mem)}, 51 | sid{stream}, 52 | autoConfig{true} {} 53 | 54 | constexpr bool valid() const noexcept { 55 | if (autoConfig) 56 | return db.x > 0; 57 | else 58 | return dg.x && dg.y && dg.z && db.x && db.y && db.z; 59 | } 60 | constexpr bool autoConfigEnabled() const noexcept { return autoConfig; } 61 | dim3 dg{}; 62 | dim3 db{}; 63 | unsigned int shmem{0}; 64 | cudaStream_t sid{cudaStreamDefault}; 65 | bool autoConfig{false}; 66 | }; 67 | 68 | } // namespace zs 69 | -------------------------------------------------------------------------------- /include/zensim/cuda/DeviceUtils.cuh: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | namespace zs { 8 | 9 | namespace cg = cooperative_groups; 10 | 11 | template __forceinline__ __device__ bool atomicMin(T* address, T val); 12 | template __forceinline__ __device__ bool atomicMax(T* address, T val); 13 | template __forceinline__ __device__ T atomicAddFloat(T* address, T val); 14 | 15 | template <> 16 | __forceinline__ __device__ double atomicAddFloat(double* address, double val) { 17 | unsigned long long* address_as_ull = (unsigned long long*)address; 18 | unsigned long long old = *address_as_ull, assumed; 19 | do { 20 | assumed = old; 21 | old = atomicCAS(address_as_ull, assumed, 22 | __double_as_longlong(val + __longlong_as_double(assumed))); 23 | } while (assumed != old); 24 | return __longlong_as_double(old); 25 | } 26 | 27 | __device__ uint64_t Packed_Add(const uint64_t* masks, const uint64_t i, const uint64_t j); 28 | template 29 | __device__ uint64_t Packed_Add_Father_Neighbor(const uint64_t* masks, const uint64_t childOffset, 30 | const int fatherLevel, 31 | const uint64_t fatherNeighborOffset); 32 | template 33 | __device__ int Retrieve_Block_Local_Offset(int level, uint64_t blockOffset); 34 | __forceinline__ __device__ uint64_t bit_spread_cuda(const uint64_t mask, int data) { 35 | uint64_t rmask = __brevll(mask); 36 | uint64_t result = 0; 37 | unsigned char lz, offset = __clzll(rmask); 38 | while (rmask) { 39 | lz = __clzll(rmask) + 1; 40 | result = result << lz | (data & 1); 41 | data >>= 1, rmask <<= lz; 42 | } 43 | result = __brevll(result) >> __clzll(mask); 44 | return result; 45 | } 46 | __forceinline__ __device__ int bit_pack_cuda(const uint64_t mask, uint64_t data) { 47 | union { 48 | uint64_t slresult; 49 | uint64_t ulresult; 50 | }; 51 | int count = 0; 52 | ulresult = 0; 53 | 54 | uint64_t rmask = __brevll(mask); 55 | unsigned char lz; 56 | 57 | while (rmask) { 58 | lz = __clzll(rmask); 59 | data >>= lz; 60 | ulresult <<= 1; 61 | count++; 62 | ulresult |= (data & 1); 63 | data >>= 1; 64 | rmask <<= lz + 1; 65 | } 66 | ulresult <<= 64 - count; // 64 means 64 bits ... maybe not use a constant 64 ... 67 | ulresult = __brevll(ulresult); 68 | return (int)slresult; 69 | } 70 | 71 | template __forceinline__ __device__ T atomicAggInc(T* p) { 72 | cg::coalesced_group g = cg::coalesced_threads(); 73 | T prev; 74 | if (g.thread_rank() == 0) { 75 | prev = atomicAdd(p, g.size()); 76 | } 77 | prev = g.thread_rank() + g.shfl(prev, 0); 78 | return prev; 79 | } 80 | 81 | } // namespace zs 82 | -------------------------------------------------------------------------------- /include/zensim/cuda/algorithm/MappingKernels.cuh: -------------------------------------------------------------------------------- 1 | #ifndef __MAPPING_KERNELS_CUH_ 2 | #define __MAPPING_KERNELS_CUH_ 3 | #include 4 | 5 | namespace zs { 6 | 7 | template 8 | __global__ void mark_boundary(int num, const EntryType *_entries, MarkerType *_marks, 9 | BinaryOp op) { 10 | int idx = blockIdx.x * blockDim.x + threadIdx.x; 11 | if (idx >= num) return; 12 | /// mark the tails of all segments 13 | _marks[idx] = idx != num - 1 ? op(_entries[idx], _entries[idx + 1]) : 1; 14 | } 15 | 16 | template 17 | __global__ void set_inverse(int num, const IndexType *_map, IndexType *_mapInv) { 18 | int idx = blockIdx.x * blockDim.x + threadIdx.x; 19 | if (idx >= num) return; 20 | auto mapIdx = _map[idx]; 21 | if (idx == 0 || mapIdx != _map[idx - 1]) { 22 | _mapInv[mapIdx] = idx; 23 | #if 0 24 | if (mapIdx < 5) 25 | printf("%d-th block starts at %d\n", mapIdx, _mapInv[mapIdx]); 26 | #endif 27 | } 28 | if (idx == num - 1) { 29 | _mapInv[mapIdx + 1] = num; 30 | } 31 | #if 0 32 | if (idx < 5) 33 | printf("%d-th particle belongs to block %d\n", idx, mapIdx); 34 | #endif 35 | } 36 | 37 | template 38 | __global__ void exclusive_scan_inverse(CounterType num, const IndexType *_map, 39 | IndexType *_mapInv) { 40 | int idx = blockIdx.x * blockDim.x + threadIdx.x; 41 | if (idx >= num) return; 42 | auto mapIdx = _map[idx]; 43 | if (mapIdx != _map[idx + 1]) _mapInv[mapIdx] = idx; 44 | } 45 | 46 | template 47 | __global__ void map_inverse(int num, const IndexType *_map, IndexType *_mapInv) { 48 | int idx = blockIdx.x * blockDim.x + threadIdx.x; 49 | if (idx >= num) return; 50 | _mapInv[_map[idx]] = idx; 51 | } 52 | 53 | template 54 | __global__ void set_range_inverse(int count, const MappingType *_toPackedRangeMap, 55 | const MappingType *_toRangeMap, CounterType *_numPackedRange, 56 | MappingType *_rangeIds, MappingType *_rangeLeftBound, 57 | MappingType *_rangeRightBound) { 58 | int idx = blockIdx.x * blockDim.x + threadIdx.x; 59 | if (idx >= count) return; 60 | auto packedRangeIdx = _toPackedRangeMap[idx]; 61 | auto rangeIdx = _toRangeMap[idx]; 62 | bool lTag = idx == 0 || rangeIdx != _toRangeMap[idx - 1]; 63 | bool rTag = idx == count - 1 || rangeIdx != _toRangeMap[idx + 1]; 64 | /// left bound 65 | if (lTag) { 66 | _rangeLeftBound[packedRangeIdx] = idx; 67 | _rangeIds[packedRangeIdx] = rangeIdx; 68 | #if 0 69 | if (packedRangeIdx == 0) 70 | printf("%d-th block st (%d): %d\n", packedRangeIdx, rangeIdx, _rangeLeftBound[packedRangeIdx]); 71 | #endif 72 | } 73 | /// right bound 74 | if (rTag) { 75 | _rangeRightBound[packedRangeIdx] = idx + 1; 76 | #if 0 77 | if (packedRangeIdx == 0) 78 | printf("%d-th block ed: %d\n", packedRangeIdx, _rangeRightBound[packedRangeIdx]); 79 | #endif 80 | } 81 | if (idx == count - 1) *_numPackedRange = packedRangeIdx + 1; 82 | } 83 | 84 | } // namespace zs 85 | 86 | #endif -------------------------------------------------------------------------------- /include/zensim/cuda/algorithm/SortKernels.cuh: -------------------------------------------------------------------------------- 1 | #ifndef __SORT_KERNELS_CUH_ 2 | #define __SORT_KERNELS_CUH_ 3 | #include 4 | 5 | namespace zs { 6 | 7 | template 8 | __global__ void gather_entry(int num, const AttribPort _from, 9 | AttribPort _to, const IndexType* _prev) { 10 | int idx = blockIdx.x * blockDim.x + threadIdx.x; 11 | if (idx >= num) return; 12 | for (int i = 0; i < Size; ++i) _to[i][idx] = _from[i][_prev[idx]]; 13 | } 14 | 15 | template 16 | __global__ void scatter_entry(int num, const AttribPort _from, 17 | AttribPort _to, const IndexType* _next) { 18 | int idx = blockIdx.x * blockDim.x + threadIdx.x; 19 | if (idx >= num) return; 20 | for (int i = 0; i < Size; ++i) _to[i][_next[idx]] = _from[i][idx]; 21 | } 22 | 23 | } // namespace zs 24 | 25 | #endif -------------------------------------------------------------------------------- /include/zensim/cuda/copy_ptx.cmake: -------------------------------------------------------------------------------- 1 | 2 | if (EXISTS ${OUTPUT}) 3 | foreach(obj ${OBJECTS}) 4 | if (EXISTS ${obj}) 5 | execute_process(COMMAND ${CMAKE_COMMAND} -E copy_if_different ${obj} ${OUTPUT}) 6 | message("copied [${obj}] to [${OUTPUT}]") 7 | endif() 8 | endforeach() 9 | endif() -------------------------------------------------------------------------------- /include/zensim/cuda/math/matrix/Matrix.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include "zensim/cuda/execution/CudaLibExecutionPolicy.cuh" 10 | #include "zensim/math/matrix/Matrix.hpp" 11 | 12 | namespace zs { 13 | 14 | template struct CudaYaleSparseMatrix 15 | : YaleSparseMatrix, 16 | MatrixAccessor> { 17 | using base_t = YaleSparseMatrix; 18 | using value_type = ValueType; 19 | using index_type = IndexType; 20 | 21 | template 22 | CudaYaleSparseMatrix(ExecPol &pol, memsrc_e mre, ProcID pid, 23 | matrix_order_e order = matrix_order_e::rowMajor, index_type nrows = 1, 24 | index_type ncols = 1) noexcept 25 | : YaleSparseMatrix{mre, pid, order, nrows, ncols, 512}, 26 | auxCholBuffer{mre, pid} { 27 | pol.template call(cusparseCreateMatDescr, &descr); 28 | pol.template call(cusparseSetMatType, descr, CUSPARSE_MATRIX_TYPE_GENERAL); 29 | pol.template call(cusparseSetMatIndexBase, descr, CUSPARSE_INDEX_BASE_ZERO); 30 | pol.template call(cusolverSpCreateCsrcholInfo, &cholInfo); 31 | // 32 | #if 0 33 | pol.addListener( 34 | dtorEvent.createListener([&pol](cusparseMatDescr_t descr, csrcholInfo_t cholInfo) { 35 | pol.template call(cusparseDestroyMatDescr, descr); 36 | pol.template call(cusolverSpDestroyCsrcholInfo, cholInfo); 37 | })); 38 | #endif 39 | } 40 | ~CudaYaleSparseMatrix() noexcept; 41 | 42 | cusparseMatDescr_t descr{0}; 43 | cusparseSpMatDescr_t spmDescr{0}; 44 | csrcholInfo_t cholInfo{nullptr}; 45 | 46 | void analyze_pattern(const CudaLibComponentExecutionPolicy &pol); 47 | void factorize(const CudaLibComponentExecutionPolicy &pol); 48 | void solve(Vector &, const CudaLibComponentExecutionPolicy &pol, 49 | const Vector &); 50 | void cgsolve(Vector &, 51 | const CudaLibExecutionPolicy &pol, 52 | const Vector &); 53 | void pcgsolve(const Vector &, Vector &, 54 | const CudaLibExecutionPolicy &pol, 55 | const Vector &); 56 | 57 | // Vector auxSpmBuffer{}; 58 | Vector auxCholBuffer{}; 59 | }; 60 | 61 | } // namespace zs -------------------------------------------------------------------------------- /include/zensim/cuda/memory/MemOps.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "zensim/memory/MemoryResource.h" 3 | #include "zensim/types/SourceLocation.hpp" 4 | 5 | namespace zs { 6 | 7 | ZPC_BACKEND_API bool prepare_context(device_mem_tag, ProcID devid, 8 | const source_location &loc = source_location::current()); 9 | ZPC_BACKEND_API void *allocate(device_mem_tag, size_t size, size_t alignment, 10 | const source_location &loc = source_location::current()); 11 | ZPC_BACKEND_API void deallocate(device_mem_tag, void *ptr, size_t size, size_t alignment, 12 | const source_location &loc = source_location::current()); 13 | ZPC_BACKEND_API void memset(device_mem_tag, void *addr, int chval, size_t size, 14 | const source_location &loc = source_location::current()); 15 | ZPC_BACKEND_API void copy(device_mem_tag, void *dst, void *src, size_t size, 16 | const source_location &loc = source_location::current()); 17 | ZPC_BACKEND_API void copyHtoD(device_mem_tag, void *dst, void *src, size_t size, 18 | const source_location &loc = source_location::current()); 19 | ZPC_BACKEND_API void copyDtoH(device_mem_tag, void *dst, void *src, size_t size, 20 | const source_location &loc = source_location::current()); 21 | ZPC_BACKEND_API void copyDtoD(device_mem_tag, void *dst, void *src, size_t size, 22 | const source_location &loc = source_location::current()); 23 | 24 | ZPC_BACKEND_API bool prepare_context(um_mem_tag, ProcID devid, 25 | const source_location &loc = source_location::current()); 26 | ZPC_BACKEND_API void *allocate(um_mem_tag, size_t size, size_t alignment, 27 | const source_location &loc = source_location::current()); 28 | ZPC_BACKEND_API void deallocate(um_mem_tag, void *ptr, size_t size, size_t alignment, 29 | const source_location &loc = source_location::current()); 30 | ZPC_BACKEND_API void memset(um_mem_tag, void *addr, int chval, size_t size, 31 | const source_location &loc = source_location::current()); 32 | ZPC_BACKEND_API void copy(um_mem_tag, void *dst, void *src, size_t size, 33 | const source_location &loc = source_location::current()); 34 | ZPC_BACKEND_API void copyHtoD(um_mem_tag, void *dst, void *src, size_t size, 35 | const source_location &loc = source_location::current()); 36 | ZPC_BACKEND_API void copyDtoH(um_mem_tag, void *dst, void *src, size_t size, 37 | const source_location &loc = source_location::current()); 38 | ZPC_BACKEND_API void copyDtoD(um_mem_tag, void *dst, void *src, size_t size, 39 | const source_location &loc = source_location::current()); 40 | ZPC_BACKEND_API void advise(um_mem_tag, std::string advice, void *addr, size_t bytes, ProcID did, 41 | const source_location &loc = source_location::current()); 42 | 43 | } // namespace zs -------------------------------------------------------------------------------- /include/zensim/cuda/profile/CudaTimers.cu: -------------------------------------------------------------------------------- 1 | #include "CudaTimers.cuh" 2 | #include "zensim/zpc_tpls/fmt/color.h" 3 | #include "zensim/zpc_tpls/fmt/core.h" 4 | 5 | namespace zs { 6 | 7 | CudaTimer::CudaTimer(stream_t sid) : streamId{sid} { 8 | cudaEventCreateWithFlags((cudaEvent_t *)&last, cudaEventBlockingSync); 9 | cudaEventCreateWithFlags((cudaEvent_t *)&cur, cudaEventBlockingSync); 10 | } 11 | CudaTimer::~CudaTimer() { 12 | cudaEventDestroy((cudaEvent_t)last); 13 | cudaEventDestroy((cudaEvent_t)cur); 14 | } 15 | float CudaTimer::elapsed() { 16 | float duration; 17 | cudaEventSynchronize((cudaEvent_t)cur); 18 | cudaEventElapsedTime(&duration, (cudaEvent_t)last, (cudaEvent_t)cur); 19 | return duration; 20 | } 21 | void CudaTimer::tick() { cudaEventRecord((cudaEvent_t)last, (cudaStream_t)streamId); } 22 | void CudaTimer::tock() { cudaEventRecord((cudaEvent_t)cur, (cudaStream_t)streamId); } 23 | void CudaTimer::tock(std::string_view tag) { 24 | tock(); 25 | fmt::print(fg(fmt::color::cyan), "{}: {} ms\n", tag, elapsed()); 26 | } 27 | 28 | } // namespace zs -------------------------------------------------------------------------------- /include/zensim/cuda/profile/CudaTimers.cuh: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include "zensim/profile/TimerBase.hpp" 6 | 7 | namespace zs { 8 | 9 | struct CudaTimer { 10 | using event_t = void *; 11 | using stream_t = void *; 12 | explicit CudaTimer(stream_t sid); 13 | ~CudaTimer(); 14 | void tick(); 15 | void tock(); 16 | float elapsed(); 17 | void tock(std::string_view tag); 18 | 19 | private: 20 | stream_t streamId; 21 | event_t last, cur; 22 | }; 23 | 24 | } // namespace zs 25 | -------------------------------------------------------------------------------- /include/zensim/cuda/simulation/sparsity/SparsityCompute.cpp: -------------------------------------------------------------------------------- 1 | #include "zensim/simulation/sparsity/SparsityCompute.tpp" 2 | 3 | #include "zensim/container/HashTable.hpp" 4 | #include "zensim/cuda/execution/ExecutionPolicy.cuh" 5 | #include "zensim/geometry/Structurefree.hpp" 6 | 7 | namespace zs { 8 | 9 | template GeneralHashTable partition_for_particles(GeneralParticles&, float, 10 | int); 11 | 12 | } // namespace zs -------------------------------------------------------------------------------- /include/zensim/cuda/simulation/wrangler/VolumeWrangler.cpp: -------------------------------------------------------------------------------- 1 | #include "zensim/execution/ExecutionPolicy.hpp" 2 | #include "zensim/geometry/Structure.hpp" 3 | #include "zensim/types/Tuple.h" 4 | 5 | #if 0 6 | extern __device__ float user_script(int n); 7 | 8 | extern "C" __global__ void zpc_prebuilt_kernel() { 9 | auto id = zs::make_tuple(blockIdx.x, threadIdx.x); 10 | printf("what the heck, indeed called successfully at (%d, %d), user specified result: %f!\n", 11 | (int)id.template get<0>(), (int)id.template get<1>(), user_script(threadIdx.x)); 12 | } 13 | #endif 14 | -------------------------------------------------------------------------------- /include/zensim/cuda/simulation/wrangler/Wrangler.cpp: -------------------------------------------------------------------------------- 1 | #include "Wrangler.hpp" 2 | 3 | #include 4 | #include 5 | 6 | #include 7 | 8 | #include "zensim/cuda/Cuda.h" 9 | #include "zensim/io/Filesystem.hpp" 10 | #include "zensim/types/Tuple.h" 11 | #include "zensim/zpc_tpls/fmt/format.h" 12 | #include "zensim/zpc_tpls/jitify/jitify2.hpp" 13 | 14 | namespace fs = std::filesystem; 15 | 16 | namespace zs::cudri { 17 | 18 | /// ref: pyb zeno POC 19 | std::vector load_all_ptx_files_at(const std::string &localPath) { 20 | #if RESOURCE_AT_RELATIVE_PATH 21 | auto dirpath = abs_exe_directory() + "/" + localPath; 22 | #else 23 | auto dirpath = std::string{AssetDirPath} + "/" + localPath; 24 | #endif 25 | std::vector res; 26 | 27 | if (!std::filesystem::exists(dirpath)) 28 | throw std::runtime_error( 29 | fmt::format("cannot find directory [{}] for loading ptx files.\n", dirpath)); 30 | for (auto const &entry : fs::directory_iterator(dirpath)) { 31 | auto path = entry.path(); 32 | if (fs::path(path).extension() == ".ptx") { 33 | fmt::print("reading ptx file: {}\n", path.string()); 34 | std::ifstream fin(path, std::ios::in | std::ios::binary | std::ios::ate); 35 | if (!fin.is_open()) { 36 | std::cerr << "\nerror: unable to open " << path << " for reading!\n"; 37 | abort(); 38 | } 39 | 40 | size_t inputSize = (size_t)fin.tellg(); 41 | char *memBlock = new char[inputSize + 1]; 42 | 43 | fin.seekg(0, std::ios::beg); 44 | fin.read(memBlock, inputSize); 45 | fin.close(); 46 | 47 | memBlock[inputSize] = '\0'; 48 | res.emplace_back(memBlock); 49 | delete memBlock; 50 | } 51 | } 52 | return res; 53 | } 54 | std::string compile_cuda_source_to_ptx(std::string_view code, std::string_view name, 55 | std::vector additionalOptions) { 56 | int major, minor; 57 | cuDeviceGetAttribute(&major, CU_DEVICE_ATTRIBUTE_COMPUTE_CAPABILITY_MAJOR, 0); 58 | cuDeviceGetAttribute(&minor, CU_DEVICE_ATTRIBUTE_COMPUTE_CAPABILITY_MINOR, 0); 59 | 60 | std::vector fixedOpts{ 61 | fmt::format("--include-path={}", ZS_INCLUDE_DIR), "--device-as-default-execution-space", 62 | fmt::format("--gpu-architecture=sm_{}{}", major, minor), "-dc", "-std=c++17"}; 63 | std::vector opts(fixedOpts.size() + additionalOptions.size()); 64 | size_t loc = 0; 65 | for (auto &&opt : fixedOpts) opts[loc++] = opt.data(); 66 | for (auto &&opt : additionalOptions) opts[loc++] = opt.data(); 67 | 68 | const char *userScript = code.data(); 69 | 70 | nvrtcProgram prog; 71 | #if 0 72 | const char *headers[] = {"type_traits", "initializer_list"}; 73 | nvrtcCreateProgram(&prog, userScript, name.data(), 2, headers, NULL); 74 | #else 75 | nvrtcCreateProgram(&prog, userScript, name.data(), 0, nullptr, NULL); 76 | #endif 77 | nvrtcResult res = nvrtcCompileProgram(prog, opts.size(), opts.data()); 78 | 79 | size_t strSize{0}; 80 | std::string str{}; 81 | nvrtcGetProgramLogSize(prog, &strSize); 82 | str.resize(strSize + 1); 83 | nvrtcGetProgramLog(prog, str.data()); 84 | str[strSize] = '\0'; 85 | if (str.size() >= 3) fmt::print("\n compilation log ---\n{}\n end log ---\n", str); 86 | 87 | nvrtcGetPTXSize(prog, &strSize); 88 | str.resize(strSize + 1); 89 | nvrtcGetPTX(prog, str.data()); 90 | str[strSize] = '\0'; 91 | return str; 92 | } 93 | 94 | } // namespace zs::cudri -------------------------------------------------------------------------------- /include/zensim/execution/ConcurrencyPrimitive.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | #include "zensim/TypeAlias.hpp" 5 | #include "zensim/ZpcFunctional.hpp" 6 | 7 | namespace zs { 8 | 9 | namespace detail { 10 | enum UnparkControl { RetainContinue, RemoveContinue, RetainBreak, RemoveBreak }; 11 | enum ParkResult { Skip, Unpark, Timeout }; 12 | } // namespace detail 13 | enum ZPC_CORE_API FutexResult { 14 | value_changed, // when expected != atomic value 15 | awoken, // awoken from 'wake' (success state) 16 | interrupted, // interrupted by certain signal 17 | timedout // not applicable to wait, applicable to wait until 18 | }; 19 | enum class ZPC_CORE_API CvStatus { // identical to std cpp 20 | no_timeout, 21 | timeout 22 | }; 23 | 24 | /// @note ref: Multithreading 101 concurrency primitive from scratch 25 | /// shared within a single process 26 | /// blocking construct in the context of shared-memory synchronization 27 | struct Futex { 28 | // put the current thread to sleep if the expected value matches the value in the atomic 29 | // waitmask will be saved and compared to the wakemask later in the wake call 30 | // to check if you wanna wake up this thread or keep it sleeping 31 | ZPC_CORE_API static FutexResult wait(std::atomic *v, u32 expected, 32 | u32 waitMask = 0xffffffff); 33 | /// @note duration in milli-seconds 34 | ZPC_CORE_API static FutexResult wait_for(std::atomic *v, u32 expected, i64 duration = -1, 35 | u32 waitMask = 0xffffffff); 36 | // wake up the thread if (wakeMask & waitMask == true) 37 | ZPC_CORE_API static int wake(std::atomic *v, int count = detail::deduce_numeric_max(), 38 | u32 wakeMask = 0xffffffff); 39 | }; 40 | 41 | ZPC_CORE_API void await_change(std::atomic &v, u32 cur); 42 | ZPC_CORE_API void await_equal(std::atomic &v, u32 desired); 43 | 44 | // process-local mutex 45 | struct Mutex : std::atomic { 46 | // 0: unlocked 47 | // 1: locked 48 | // 257: locked and contended (...0001 | 00000001) 49 | // Mutex(u32 offset = 0) noexcept : _kMask{(u32)1 << (offset & (u32)31)} {} 50 | // ~Mutex() = default; 51 | ZPC_CORE_API void lock() noexcept; 52 | ZPC_CORE_API void unlock() noexcept; 53 | ZPC_CORE_API bool try_lock() noexcept; 54 | static constexpr u32 _kMask{1}; 55 | }; 56 | 57 | // 8 bytes alignment for rollover issue 58 | // https://docs.ntpsec.org/latest/rollover.html 59 | struct ConditionVariable { 60 | ZPC_CORE_API void notify_one() noexcept; 61 | ZPC_CORE_API void notify_all() noexcept; 62 | 63 | ZPC_CORE_API void wait(Mutex &lk) noexcept; 64 | template void wait(Mutex &lk, Pred p) { 65 | while (!p()) wait(lk); 66 | } 67 | 68 | ZPC_CORE_API CvStatus wait_for(Mutex &lk, i64 duration) noexcept; 69 | template bool wait_for(Mutex &lk, i64 duration, Pred p) { 70 | while (!p()) 71 | if (wait_for(lk, duration) == CvStatus::timeout) return p(); 72 | return true; 73 | } 74 | 75 | std::atomic seq{0}; 76 | }; 77 | 78 | } // namespace zs -------------------------------------------------------------------------------- /include/zensim/execution/ExecutionPolicy.cpp: -------------------------------------------------------------------------------- 1 | #include "ExecutionPolicy.hpp" 2 | 3 | namespace zs { 4 | ; 5 | ; 6 | } // namespace zs -------------------------------------------------------------------------------- /include/zensim/execution/Stacktrace.hpp: -------------------------------------------------------------------------------- 1 | /// reference: https://github.com/kokkos/kokkos.git 2 | #pragma once 3 | #include 4 | #include 5 | 6 | #include "zensim/Platform.hpp" 7 | #include "zensim/ZpcFunction.hpp" 8 | 9 | namespace Kokkos { 10 | namespace Impl { 11 | 12 | /// \brief Return the demangled version of the input symbol, or the 13 | /// original input if demangling is not possible. 14 | ZPC_CORE_API std::string demangle(const std::string &name); 15 | 16 | /// \brief Save the current stacktrace. 17 | /// 18 | /// You may only save one stacktrace at a time. If you call this 19 | /// twice, the second call will overwrite the result of the first 20 | /// call. 21 | void save_stacktrace(); 22 | 23 | /// \brief Print the raw form of the currently saved stacktrace, if 24 | /// any, to the given output stream. 25 | void print_saved_stacktrace(std::ostream &out); 26 | 27 | /// \brief Print the currently saved, demangled stacktrace, if any, to 28 | /// the given output stream. 29 | /// 30 | /// Demangling is best effort only. 31 | void print_demangled_saved_stacktrace(std::ostream &out); 32 | 33 | /// \brief Set the std::terminate handler so that it prints the 34 | /// currently saved stack trace, then calls user_post. 35 | /// 36 | /// This is useful if you want to call, say, MPI_Abort instead of 37 | /// std::abort. The MPI Standard frowns upon calling MPI functions 38 | /// without including their header file, and Kokkos does not depend on 39 | /// MPI, so there's no way for Kokkos to depend on MPI_Abort in a 40 | /// portable way. 41 | void set_kokkos_terminate_handler(zs::function user_post = {}); 42 | 43 | } // namespace Impl 44 | } // namespace Kokkos 45 | -------------------------------------------------------------------------------- /include/zensim/geometry/AdaptiveGrid.cpp: -------------------------------------------------------------------------------- 1 | #include "AdaptiveGrid.hpp" 2 | 3 | namespace zs { 4 | 5 | // openvdb float grid 6 | ZPC_INSTANTIATE_STRUCT 7 | AdaptiveGridImpl<3, f32, index_sequence<3, 4, 5>, index_sequence<3, 4, 5>, 8 | index_sequence<0, 1, 2>, ZSPmrAllocator<>>; 9 | ZPC_INSTANTIATE_STRUCT VdbGrid<3, f32, index_sequence<3, 4, 5>, ZSPmrAllocator<>>; 10 | // bifrost adaptive tile tree 11 | ZPC_INSTANTIATE_STRUCT 12 | AdaptiveGridImpl<3, f32, index_sequence<2, 2, 2>, index_sequence<1, 1, 1>, 13 | index_sequence<0, 1, 2>, ZSPmrAllocator<>>; 14 | ZPC_INSTANTIATE_STRUCT AdaptiveTileTree<3, f32, 3, 2, ZSPmrAllocator<>>; 15 | 16 | } // namespace zs -------------------------------------------------------------------------------- /include/zensim/geometry/AdaptiveGridUtils.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "AdaptiveGrid.hpp" 3 | #include "zensim/execution/ExecutionPolicy.hpp" 4 | 5 | namespace zs {} // namespace zs -------------------------------------------------------------------------------- /include/zensim/geometry/BoundingVolumeInterface.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "zensim/math/Vec.h" 3 | 4 | namespace zs { 5 | 6 | // enum struct bv_e : char { aabb, obb, sphere, convex }; 7 | template struct BoundingVolumeInterface { 8 | template using TV = vec; 9 | constexpr auto getBoundingBox() const noexcept { 10 | return static_cast(this)->do_getBoundingBox(); 11 | } 12 | constexpr auto getBoxCenter() const noexcept { 13 | const auto &[lo, hi] = getBoundingBox(); 14 | return (lo + hi) / 2; 15 | } 16 | constexpr auto getBoxSideLengths() const noexcept { 17 | const auto &[lo, hi] = getBoundingBox(); 18 | return hi - lo; 19 | } 20 | template > 23 | = 0> 24 | constexpr auto getUniformCoord(const VecInterface &pos) const noexcept { 25 | auto [lo, offset] = getBoundingBox(); 26 | const auto lengths = offset - lo; 27 | offset = pos - lo; 28 | for (int d = 0; d != Self::dim; ++d) 29 | offset[d] = math::clamp(offset[d], (typename Self::value_type)0, lengths[d]) / lengths[d]; 30 | return offset; 31 | } 32 | 33 | template > 34 | constexpr zs::tuple do_getBoundingBox() const noexcept { 35 | return zs::make_tuple(TV::zeros(), TV::zeros()); 36 | } 37 | }; 38 | 39 | template >, 42 | is_same_v> 43 | = 0> 44 | constexpr auto get_bounding_box(const VecInterface &bva, const VecInterface &bvb) { 45 | using ValueT = math::op_result_t; 46 | using TV = typename VecTA::template variant_vec; 47 | return zs::make_tuple(TV::init([&bva, &bvb](typename VecTA::index_type i) noexcept -> ValueT { 48 | return bva(i) < bvb(i) ? (ValueT)bva(i) : (ValueT)bvb(i); 49 | }), 50 | TV::init([&bva, &bvb](typename VecTA::index_type i) noexcept -> ValueT { 51 | return bva(i) > bvb(i) ? (ValueT)bva(i) : (ValueT)bvb(i); 52 | })); 53 | } 54 | 55 | } // namespace zs -------------------------------------------------------------------------------- /include/zensim/geometry/Collider.cpp: -------------------------------------------------------------------------------- 1 | #include "Collider.h" 2 | 3 | namespace zs { 4 | 5 | // template struct ZPC_TEMPLATE_EXPORT LevelSetBoundary>; 6 | 7 | } -------------------------------------------------------------------------------- /include/zensim/geometry/GenericLevelSet.h: -------------------------------------------------------------------------------- 1 | 2 | #pragma once 3 | #include "AnalyticLevelSet.h" 4 | #include "LevelSet.h" 5 | #include "LevelSetInterface.h" 6 | #include "zensim/types/Polymorphism.h" 7 | 8 | namespace zs { 9 | 10 | template using GenericLevelSet 11 | = variant, 12 | AnalyticLevelSet, 13 | AnalyticLevelSet>; 14 | 15 | } 16 | -------------------------------------------------------------------------------- /include/zensim/geometry/LevelSetInterface.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "zensim/geometry/BoundingVolumeInterface.hpp" 3 | 4 | namespace zs { 5 | 6 | template struct LevelSetInterface : BoundingVolumeInterface { 7 | template = 0> 9 | constexpr auto getSignedDistance(const VecInterface &x) const noexcept -> 10 | typename LS::value_type { 11 | return static_cast(this)->do_getSignedDistance(x); 12 | } 13 | template = 0> 15 | constexpr auto getNormal(const VecInterface &x) const noexcept { 16 | return static_cast(this)->do_getNormal(x); 17 | } 18 | template = 0> 20 | constexpr auto getMaterialVelocity(const VecInterface &x) const noexcept { 21 | return static_cast(this)->do_getMaterialVelocity(x); 22 | } 23 | 24 | protected: 25 | template = 0> 27 | constexpr auto do_getSignedDistance(const VecInterface &x) const noexcept { 28 | return detail::deduce_numeric_max(); 29 | } 30 | template = 0> 32 | constexpr auto do_getNormal(const VecInterface &x) const noexcept { 33 | return VecInterface::constant(0); 34 | } 35 | template = 0> 37 | constexpr auto do_getMaterialVelocity(const VecInterface &x) const noexcept { 38 | return VecInterface::constant(0); 39 | } 40 | }; 41 | 42 | template struct is_ag : false_type {}; 43 | template struct is_spg : false_type {}; 44 | template constexpr bool is_spg_v = is_spg::value; 45 | template constexpr bool is_ag_v = is_ag::value; 46 | 47 | } // namespace zs 48 | -------------------------------------------------------------------------------- /include/zensim/geometry/Mesh.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | // 6 | #include "zensim/container/Vector.hpp" 7 | #include "zensim/math/Vec.h" 8 | 9 | namespace zs { 10 | 11 | template struct Mesh { 12 | using value_type = T; 13 | static constexpr int dim = dim_; 14 | using index_type = Tn; 15 | static constexpr int dim_elem = dimE; 16 | 17 | using Node = std::array; 18 | using Elem = std::array; 19 | using UV = std::array; 20 | using Norm = std::array; 21 | using Tan = std::array; 22 | using Color = std::array; 23 | using TexId = std::array; // 24 | std::vector nodes; 25 | std::vector vids; // splitted-point-id to vertex-id 26 | std::vector elems; 27 | std::vector uvs; 28 | std::vector norms; 29 | std::vector tans; 30 | std::vector colors; 31 | std::vector texids; 32 | std::string texturePath; 33 | 34 | inline void clear() { 35 | nodes.clear(); 36 | vids.clear(); 37 | elems.clear(); 38 | uvs.clear(); 39 | norms.clear(); 40 | tans.clear(); 41 | colors.clear(); 42 | texids.clear(); 43 | texturePath.clear(); 44 | } 45 | }; 46 | 47 | ZPC_API void compute_mesh_normal(const Mesh &, float, 48 | std::vector> &); 49 | ZPC_API void compute_mesh_normal(const Mesh &, float, 50 | std::vector> &); 51 | ZPC_API void compute_mesh_normal(const Mesh &, float, Vector> &); 52 | ZPC_API void compute_mesh_normal(const Mesh &, float, Vector> &); 53 | ZPC_API void compute_mesh_normal(const std::vector> &nodes, 54 | size_t nodeOffset, size_t nodeNum, 55 | const std::vector> &tris, size_t triOffset, 56 | size_t triNum, std::array *nrms); 57 | 58 | #if 0 59 | template class VectorT, typename ValueT> 60 | void compute_mesh_normal(const Mesh &surfs, float scale, 61 | VectorT &nrms); 62 | 63 | extern template void compute_mesh_normal>( 64 | const Mesh &, float, std::vector> &); 65 | extern template void compute_mesh_normal>( 66 | const Mesh &, float, std::vector> &); 67 | extern template void compute_mesh_normal>( 68 | const Mesh &, float, Vector> &); 69 | extern template void compute_mesh_normal>( 70 | const Mesh &, float, Vector> &); 71 | #endif 72 | 73 | } // namespace zs 74 | -------------------------------------------------------------------------------- /include/zensim/geometry/OverlayGrid.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "AdaptiveGrid.hpp" 3 | 4 | namespace zs {} -------------------------------------------------------------------------------- /include/zensim/geometry/PointDataGrid.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "zensim/container/HashTable.hpp" 3 | #include "zensim/container/TileVector.hpp" 4 | #include "zensim/container/Vector.hpp" 5 | 6 | namespace zs { 7 | 8 | ; 9 | 10 | } -------------------------------------------------------------------------------- /include/zensim/geometry/SparseGrid.cpp: -------------------------------------------------------------------------------- 1 | #include "SparseGrid.hpp" 2 | 3 | namespace zs { 4 | 5 | // ZPC_INSTANTIATE_STRUCT SparseGrid<3, f32, 8, ZSPmrAllocator<>, i32>; 6 | 7 | } -------------------------------------------------------------------------------- /include/zensim/geometry/VdbSampler.cpp: -------------------------------------------------------------------------------- 1 | #include "VdbSampler.h" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #include 14 | #include 15 | 16 | #include "PoissonDisk.hpp" 17 | #include "zensim/Logger.hpp" 18 | #include "zensim/types/Iterator.h" 19 | #include "zensim/types/Property.h" 20 | 21 | namespace zs { 22 | 23 | std::vector> sample_from_floatgrid(const OpenVDBStruct &grid, float dx, 24 | float ppc) { 25 | auto spls = convert_floatgrid_to_sparse_grid(grid); 26 | auto lsv = proxy(spls); 27 | 28 | PoissonDisk pd{}; 29 | zs::tie(pd.minCorner, pd.maxCorner) = lsv.getBoundingBox(); 30 | pd.setDistanceByPpc(dx, ppc); 31 | 32 | auto sample = [&lsv](const auto &x) -> float { return lsv.getSignedDistance(x); }; 33 | return pd.sample([&](const auto &x) { return sample(x) <= 0.f; }); 34 | } 35 | 36 | std::vector> sample_from_vdb_file(const std::string &filename, float dx, 37 | float ppc) { 38 | return sample_from_floatgrid(load_floatgrid_from_vdb_file(filename), dx, ppc); 39 | } 40 | 41 | std::vector> sample_from_obj_file(const std::string &filename, float dx, 42 | float ppc) { 43 | return sample_from_floatgrid(load_floatgrid_from_mesh_file(filename, dx), dx, ppc); 44 | } 45 | 46 | std::vector> sample_from_levelset(const OpenVDBStruct &ls, float dx, 47 | float ppc) { 48 | const auto &gridPtr = ls.as(); 49 | vec minCorner{}, maxCorner{}; 50 | { 51 | openvdb::CoordBBox box = gridPtr->evalActiveVoxelBoundingBox(); 52 | auto corner = box.min(); 53 | auto length = box.max() - box.min(); 54 | auto world_min = gridPtr->indexToWorld(box.min()); 55 | auto world_max = gridPtr->indexToWorld(box.max()); 56 | for (size_t d = 0; d != 3; d++) { 57 | minCorner(d) = world_min[d]; 58 | maxCorner(d) = world_max[d]; 59 | } 60 | for (auto &&[dx, dy, dz] : ndrange<3>(2)) { 61 | auto coord 62 | = corner + decltype(length){dx ? length[0] : 0, dy ? length[1] : 0, dz ? length[2] : 0}; 63 | auto pos = gridPtr->indexToWorld(coord); 64 | for (int d = 0; d != 3; d++) { 65 | minCorner(d) = pos[d] < minCorner(d) ? pos[d] : minCorner(d); 66 | maxCorner(d) = pos[d] > maxCorner(d) ? pos[d] : maxCorner(d); 67 | } 68 | } 69 | } 70 | PoissonDisk pd{}; 71 | pd.minCorner = minCorner; 72 | pd.maxCorner = maxCorner; 73 | pd.setDistanceByPpc(dx, ppc); 74 | auto sample = [gridPtr](const auto &x) -> float { 75 | return openvdb::tools::BoxSampler::sample( 76 | gridPtr->tree(), gridPtr->worldToIndex(openvdb::Vec3R{x[0], x[1], x[2]})); 77 | }; 78 | // auto sample = [&lsv](const auto &x) -> float { return lsv.getSignedDistance(x); }; 79 | return pd.sample([&](const auto &x) { return sample(x) <= 0.f; }); 80 | } 81 | 82 | } // namespace zs -------------------------------------------------------------------------------- /include/zensim/geometry/VdbSampler.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | 6 | #include "VdbLevelSet.h" 7 | 8 | namespace zs { 9 | 10 | ZPC_EXTENSION_API std::vector> sample_from_floatgrid( 11 | const OpenVDBStruct &grid, float dx, float ppc); 12 | ZPC_EXTENSION_API std::vector> sample_from_vdb_file( 13 | const std::string &filename, float dx, float ppc); 14 | ZPC_EXTENSION_API std::vector> sample_from_obj_file( 15 | const std::string &filename, float dx, float ppc); 16 | ZPC_EXTENSION_API std::vector> sample_from_levelset(const OpenVDBStruct &ls, 17 | float dx, float ppc); 18 | 19 | } // namespace zs 20 | -------------------------------------------------------------------------------- /include/zensim/geometry/remesh/Retile.hpp: -------------------------------------------------------------------------------- 1 | #include "zensim/container/TileVector.hpp" 2 | 3 | namespace zs { 4 | 5 | template 6 | void spray_points(Pol &&pol, const TileVector &verts, const TileVector &eles, std::size_t numSamples, TileVector &pts) { 7 | constexpr execspace_e space = RM_REF_T(pol)::exec_tag::value; 8 | 9 | using Ti = conditional_t>>; 10 | static_assert(sizeof(Ti) == sizeof(TEle), "(reinterpreted) integer type should have the same size as element type."); 11 | 12 | ; 13 | } 14 | 15 | } -------------------------------------------------------------------------------- /include/zensim/io/Filesystem.cpp: -------------------------------------------------------------------------------- 1 | #include "Filesystem.hpp" 2 | 3 | #include "zensim/zpc_tpls/whereami/whereami.h" 4 | 5 | namespace zs { 6 | 7 | /// ref: 8 | /// https://stackoverflow.com/questions/1023306/finding-current-executables-path-without-proc-self-exe/1024937#1024937 9 | /// ref: https://gist.github.com/Jacob-Tate/7b326a086cf3f9d46e32315841101109 10 | 11 | std::string abs_exe_path() { 12 | char *s{}; 13 | int length, dirname_length; 14 | length = wai_getExecutablePath(NULL, 0, &dirname_length); 15 | s = (char *)malloc(length + 1); 16 | wai_getExecutablePath(s, length, &dirname_length); 17 | s[length] = '\0'; 18 | auto ret = std::string(s); 19 | free(s); 20 | return ret; 21 | } 22 | 23 | std::string abs_exe_directory() { 24 | char *s{}; 25 | int length, dirname_length; 26 | length = wai_getExecutablePath(NULL, 0, &dirname_length); 27 | s = (char *)malloc(length + 1); 28 | wai_getExecutablePath(s, length, &dirname_length); 29 | s[dirname_length] = '\0'; 30 | auto ret = std::string(s); 31 | free(s); 32 | return ret; 33 | } 34 | 35 | std::string abs_module_path() { 36 | char *s{}; 37 | int length, dirname_length; 38 | length = wai_getModulePath(NULL, 0, &dirname_length); 39 | s = (char *)malloc(length + 1); 40 | wai_getModulePath(s, length, &dirname_length); 41 | s[length] = '\0'; 42 | auto ret = std::string(s); 43 | free(s); 44 | return ret; 45 | } 46 | 47 | std::string abs_module_directory() { 48 | char *s{}; 49 | int length, dirname_length; 50 | length = wai_getModulePath(NULL, 0, &dirname_length); 51 | s = (char *)malloc(length + 1); 52 | wai_getModulePath(s, length, &dirname_length); 53 | s[dirname_length] = '\0'; 54 | auto ret = std::string(s); 55 | free(s); 56 | return ret; 57 | } 58 | 59 | } // namespace zs -------------------------------------------------------------------------------- /include/zensim/io/Filesystem.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include "zensim/Platform.hpp" 4 | 5 | namespace zs { 6 | 7 | /// ref: 8 | /// https://stackoverflow.com/questions/1023306/finding-current-executables-path-without-proc-self-exe/1024937#1024937 9 | /// ref: https://gist.github.com/Jacob-Tate/7b326a086cf3f9d46e32315841101109 10 | /// ref: https://github.com/gpakosz/whereami 11 | 12 | ZPC_BACKEND_API std::string abs_exe_path(); 13 | ZPC_BACKEND_API std::string abs_exe_directory(); 14 | ZPC_BACKEND_API std::string abs_module_path(); 15 | ZPC_BACKEND_API std::string abs_module_directory(); 16 | 17 | } // namespace zs -------------------------------------------------------------------------------- /include/zensim/io/IO.cpp: -------------------------------------------------------------------------------- 1 | #include "IO.h" 2 | 3 | #include 4 | // #include 5 | #include 6 | #include 7 | #include 8 | 9 | #if 0 10 | namespace { 11 | static zs::IO *g_ioInstance = nullptr; 12 | } 13 | #endif 14 | 15 | namespace zs { 16 | 17 | #if 0 18 | IO &IO::instance() { 19 | if (!g_ioInstance) g_ioInstance = new IO; 20 | return *g_ioInstance; 21 | } 22 | #endif 23 | 24 | std::string file_get_content(std::string const &path) { 25 | std::ifstream fin(path); 26 | std::string content; 27 | std::istreambuf_iterator iit(fin), eiit; 28 | std::back_insert_iterator sit(content); 29 | std::copy(iit, eiit, sit); 30 | return content; 31 | } 32 | 33 | void *load_raw_file(char const *filename, size_t size) { 34 | FILE *fp = fopen(filename, "rb"); 35 | 36 | if (!fp) { 37 | fprintf(stderr, "Error opening file '%s'\n", filename); 38 | return 0; 39 | } 40 | void *data = malloc(size); 41 | size_t read = fread(data, 1, size, fp); 42 | fclose(fp); 43 | 44 | #if defined(_MSC_VER_) 45 | printf("Read '%s', %Iu bytes\n", filename, read); 46 | #else 47 | printf("Read '%s', %zu bytes\n", filename, read); 48 | #endif 49 | return data; 50 | } 51 | 52 | } // namespace zs 53 | -------------------------------------------------------------------------------- /include/zensim/io/IO.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "zensim/ZpcFunction.hpp" 3 | #include "zensim/execution/Concurrency.h" 4 | 5 | namespace zs { 6 | 7 | struct IO { 8 | private: 9 | void wait() { 10 | std::unique_lock lk{mut}; 11 | cv.wait(lk, [this]() { return !this->bRunning || !this->jobs.empty(); }); 12 | }; 13 | void worker() { 14 | while (bRunning) { 15 | wait(); 16 | auto job = jobs.try_pop(); 17 | if (job) (*job)(); 18 | } 19 | } 20 | IO() : bRunning{true} { 21 | th = std::thread([this]() { this->worker(); }); 22 | } 23 | 24 | public: 25 | ZPC_BACKEND_API static IO &instance() { 26 | static IO s_instance{}; 27 | return s_instance; 28 | } 29 | ~IO() { 30 | while (!jobs.empty()) cv.notify_all(); 31 | bRunning = false; 32 | th.join(); 33 | } 34 | 35 | static void flush() { 36 | while (!instance().jobs.empty()) instance().cv.notify_all(); 37 | } 38 | static void insert_job(zs::function job) { 39 | std::unique_lock lk{instance().mut}; 40 | instance().jobs.push(job); 41 | lk.unlock(); 42 | instance().cv.notify_all(); 43 | } 44 | 45 | private: 46 | bool bRunning; 47 | std::mutex mut; 48 | std::condition_variable cv; 49 | threadsafe_queue> jobs; 50 | std::thread th; 51 | }; 52 | 53 | std::string file_get_content(std::string const &path); 54 | void *load_raw_file(char const *filename, size_t size); 55 | 56 | } // namespace zs 57 | -------------------------------------------------------------------------------- /include/zensim/io/ParticleIO.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | 6 | #include "zensim/math/Vec.h" 7 | 8 | namespace zs { 9 | 10 | template 11 | void write_partio(std::string filename, const std::vector> &data, 12 | std::string tag = std::string{"position"}); 13 | 14 | template 15 | void write_partio_with_stress(std::string filename, const std::vector> &data, 16 | const std::vector &stressData); 17 | 18 | template 19 | void write_partio_with_grid(std::string filename, const std::vector> &pos, 20 | const std::vector> &force); 21 | 22 | extern template ZPC_BACKEND_TEMPLATE_IMPORT void write_partio(std::string, const std::vector> &, 23 | std::string); 24 | extern template ZPC_BACKEND_TEMPLATE_IMPORT void write_partio(std::string, const std::vector> &, 25 | std::string); 26 | 27 | extern template ZPC_BACKEND_TEMPLATE_IMPORT void write_partio_with_stress(std::string, const std::vector> &, 28 | const std::vector &); 29 | extern template ZPC_BACKEND_TEMPLATE_IMPORT void write_partio_with_stress(std::string, const std::vector> &, 30 | const std::vector &); 31 | 32 | extern template ZPC_BACKEND_TEMPLATE_IMPORT void write_partio_with_grid(std::string, const std::vector> &, 33 | const std::vector> &); 34 | extern template ZPC_BACKEND_TEMPLATE_IMPORT void write_partio_with_grid(std::string, const std::vector> &, 35 | const std::vector> &); 36 | 37 | } // namespace zs 38 | -------------------------------------------------------------------------------- /include/zensim/math/Hash.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "zensim/meta/Meta.h" 3 | 4 | namespace zs { 5 | 6 | /* 7 | // on why XOR is not a good choice for hash-combining: 8 | // https://stackoverflow.com/questions/5889238/why-is-xor-the-default-way-to-combine-hashes 9 | // 10 | // this is from boost 11 | // 12 | template constexpr void hash_combine(size_t &seed, const T &val) { 13 | seed ^= (val + 0x9e3779b9 + (seed << 6) + (seed >> 2)); 14 | } 15 | */ 16 | // ref: https://github.com/HowardHinnant/hash_append/issues/7 17 | template , is_integral_v> = 0> 19 | constexpr void hash_combine(Tn &seed, const T &val) { 20 | static_assert(sizeof(Tn) >= 2 && sizeof(Tn) <= 8, "Tn should contain at least 16 bits"); 21 | if constexpr (sizeof(Tn) == 2) 22 | seed ^= (val + 0x9e37U + (seed << 3) + (seed >> 1)); 23 | else if constexpr (sizeof(Tn) == 4) 24 | seed ^= (val + 0x9e3779b9U + (seed << 6) + (seed >> 2)); 25 | else if constexpr (sizeof(Tn) == 8) 26 | seed ^= (val + 0x9e3779b97f4a7c15LLU + (seed << 12) + (seed >> 4)); 27 | } 28 | 29 | /// https://stackoverflow.com/questions/664014/what-integer-hash-function-are-good-that-accepts-an-integer-hash-key 30 | #if 0 31 | constexpr uint32_t hash(uint32_t x) noexcept { 32 | x += (x << 10u); 33 | x ^= (x >> 6u); 34 | x += (x << 3u); 35 | x ^= (x >> 11u); 36 | x += (x << 15u); 37 | return x; 38 | } 39 | #endif 40 | template constexpr T hash(T x) noexcept { 41 | if constexpr (sizeof(T) == 4) { 42 | x = ((x >> 16) ^ x) * 0x45d9f3b; 43 | x = ((x >> 16) ^ x) * 0x45d9f3b; 44 | x = (x >> 16) ^ x; 45 | } else if constexpr (sizeof(T) == 8) { 46 | x = (x ^ (x >> 30)) * uint64_t(0xbf58476d1ce4e5b9); 47 | x = (x ^ (x >> 27)) * uint64_t(0x94d049bb133111eb); 48 | x = x ^ (x >> 31); 49 | } 50 | return x; 51 | } 52 | template constexpr T unhash(T x) noexcept { 53 | if constexpr (sizeof(T) == 4) { 54 | x = ((x >> 16) ^ x) * 0x119de1f3; 55 | x = ((x >> 16) ^ x) * 0x119de1f3; 56 | x = (x >> 16) ^ x; 57 | } else if constexpr (sizeof(T) == 8) { 58 | x = (x ^ (x >> 31) ^ (x >> 62)) * uint64_t(0x319642b2d24d8ec3); 59 | x = (x ^ (x >> 27) ^ (x >> 54)) * uint64_t(0x96de1b173f119089); 60 | x = x ^ (x >> 30) ^ (x >> 60); 61 | } 62 | return x; 63 | } 64 | 65 | } // namespace zs 66 | -------------------------------------------------------------------------------- /include/zensim/math/matrix/Matrix.cpp: -------------------------------------------------------------------------------- 1 | #include "Matrix.hpp" 2 | 3 | #include 4 | 5 | #include "zensim/Logger.hpp" 6 | 7 | namespace zs { 8 | 9 | template struct YaleSparseMatrix; 10 | template struct YaleSparseMatrix; 11 | } // namespace zs -------------------------------------------------------------------------------- /include/zensim/math/matrix/MatrixCtor.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "Matrix.hpp" 3 | 4 | namespace zs { 5 | 6 | template 7 | void spm_set_pattern(Pol &&pol, YaleSparseMatrix &mat, const Vector &rs, 8 | const Vector &cs); 9 | template 10 | void spm_from_triplets(Pol &&pol, YaleSparseMatrix &mat, const Vector &rs, 11 | const Vector &cs, const Vector &vs); 12 | 13 | } // namespace zs -------------------------------------------------------------------------------- /include/zensim/math/matrix/MatrixTransform.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zenustech/zpc/a9bbc73d31e317fba6e0e4c95cef1796a039e467/include/zensim/math/matrix/MatrixTransform.cpp -------------------------------------------------------------------------------- /include/zensim/math/matrix/MatrixTransform.hpp: -------------------------------------------------------------------------------- 1 | 2 | #pragma once 3 | #include "Matrix.hpp" 4 | 5 | namespace zs {} -------------------------------------------------------------------------------- /include/zensim/math/matrix/Utility.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace zs { 4 | 5 | namespace math { 6 | template constexpr int sgn(const T n) noexcept { 7 | return n < -1e-10 ? -1 : n > 1e-10; 8 | // return n < 0.0 ? -1 : n > 0.0; 9 | // return n == 0 ? 0 : 1; 10 | } 11 | 12 | template constexpr void orthogonalVector(const T *input, T *output) noexcept { 13 | T abs_x = abs(input[0]), abs_y = abs(input[1]), abs_z = abs(input[2]); 14 | if (abs_x < abs_y) { 15 | if (abs_x < abs_z) 16 | output[0] = 0, output[1] = input[2], output[2] = -input[1]; 17 | else 18 | output[0] = input[1], output[1] = -input[0], output[2] = 0; 19 | } else { 20 | if (abs_y < abs_z) 21 | output[0] = -input[2], output[1] = 0, output[2] = input[0]; 22 | else 23 | output[0] = input[1], output[1] = -input[0], output[2] = 0; 24 | } 25 | } 26 | 27 | template constexpr void cross(const T *operand1, const T *operand2, T *output) { 28 | const T &x1 = operand1[0]; 29 | const T &y1 = operand1[1]; 30 | const T &z1 = operand1[2]; 31 | const T &x2 = operand2[0]; 32 | const T &y2 = operand2[1]; 33 | const T &z2 = operand2[2]; 34 | output[0] = y1 * z2 - y2 * z1; 35 | output[1] = x2 * z1 - x1 * z2; 36 | output[2] = x1 * y2 - x2 * y1; 37 | } 38 | 39 | template 40 | constexpr void vectorCopy(const T scale, const T *v, TT *res) { 41 | res[0] = v[0] * scale; 42 | res[1] = v[1] * scale; 43 | res[2] = v[2] * scale; 44 | } 45 | 46 | } // namespace math 47 | 48 | } // namespace zs 49 | -------------------------------------------------------------------------------- /include/zensim/math/probability/Probability.cpp: -------------------------------------------------------------------------------- 1 | #include "Probability.h" 2 | 3 | #include 4 | 5 | #include "zensim/math/MathUtils.h" 6 | #include "zensim/math/Rotation.hpp" 7 | 8 | namespace zs { 9 | 10 | double PDF(int lambda, int k) { 11 | double pdf = 1; 12 | for (int i = 1; i <= k; ++i) pdf *= (double)lambda / i; 13 | return pdf * zs::exp(-1.0 * lambda); 14 | } 15 | 16 | double PDF(double u, double o, int x) { 17 | const double co = 1. / zs::sqrt(2. * g_pi); 18 | double index = -(x - u) * (x - u) / 2. / o / o; 19 | return co / o * zs::exp(index); 20 | } 21 | double anti_normal_PDF(double u, double o, int x) { 22 | const double co = 1. / zs::sqrt(2. * g_pi); 23 | double index = -(x - u) * (x - u) / 2. / o / o; 24 | return 1 - co / o * zs::exp(index); 25 | } 26 | 27 | int rand_p(double lambda) { 28 | double u = (double)rand() / RAND_MAX; 29 | int x = 0; 30 | double cdf = zs::exp(-1.0 * lambda); 31 | while (u >= cdf) { 32 | x++; 33 | cdf += PDF(lambda, x); 34 | } 35 | return x; 36 | } 37 | int rand_normal(double u, double o) { 38 | double val = (double)rand() / RAND_MAX; 39 | int x = 0; 40 | double cdf = 0; // PDF(u, o, x) 41 | while (val >= cdf) { 42 | x++; 43 | cdf += PDF(u, o, x); 44 | } 45 | return x; 46 | } 47 | int rand_anti_normal(double u, double o) { 48 | double val = (double)rand() / RAND_MAX; 49 | int x = 0; 50 | double cdf = 0; // PDF(u, o, x) 51 | while (val >= cdf) { 52 | x++; 53 | cdf += anti_normal_PDF(u, o, x); 54 | } 55 | return x; 56 | } 57 | } // namespace zs -------------------------------------------------------------------------------- /include/zensim/math/probability/Probability.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | namespace zs { 6 | 7 | double PDF(int lambda, int k); 8 | int rand_p(double lambda); 9 | double anti_normal_PDF(double u, double o, int x); 10 | 11 | double PDF(double u, double o, int x); 12 | int rand_normal(double u, double o); 13 | int rand_anti_normal(double u, double o); 14 | } // namespace zs 15 | -------------------------------------------------------------------------------- /include/zensim/math/probability/Random.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "zensim/TypeAlias.hpp" 3 | 4 | /// ref: C++ Weekly With Jason Turner - Episode 44 : constexpr Compile Time Random 5 | namespace zs { 6 | 7 | constexpr u64 seed() noexcept { 8 | u64 shifted = 0; 9 | for (const auto c : __TIME__) { 10 | shifted <<= 8; 11 | shifted |= c; 12 | } 13 | return shifted; 14 | } 15 | 16 | struct PCG { 17 | struct pcg32_random_t { 18 | u64 state = 0; 19 | u64 inc = seed(); 20 | } rng{}; 21 | 22 | using result_type = u32; 23 | 24 | constexpr result_type pcg32_random_r() noexcept { 25 | u64 oldstate = rng.state; 26 | rng.state = oldstate * 6364136223846793005ULL + (rng.inc | 1); 27 | u32 xorshifted = ((oldstate >> 18u) ^ oldstate) >> 27u; 28 | u32 rot = oldstate >> 59u; 29 | return (xorshifted >> rot) | (xorshifted << ((-rot) & 31)); 30 | } 31 | static constexpr result_type pcg32_random_r(u64 &state, 32 | u64 inc = 1442695040888963407ull) noexcept { 33 | u64 oldstate = state; 34 | state = oldstate * 6364136223846793005ULL + (inc | 1); 35 | u32 xorshifted = ((oldstate >> 18u) ^ oldstate) >> 27u; 36 | u32 rot = oldstate >> 59u; 37 | return (xorshifted >> rot) | (xorshifted << ((-rot) & 31)); 38 | } 39 | // TODO: https://en.wikipedia.org/wiki/Linear_congruential_generator 40 | 41 | constexpr result_type operator()() noexcept { return pcg32_random_r(); } 42 | }; 43 | 44 | constexpr auto call_random(int i = 0) noexcept { 45 | PCG pcg{}; 46 | while (i > 0) { 47 | pcg(); 48 | --i; 49 | } 50 | return pcg(); 51 | } 52 | 53 | } // namespace zs -------------------------------------------------------------------------------- /include/zensim/memory/MemOps.cpp: -------------------------------------------------------------------------------- 1 | #include "MemOps.hpp" 2 | #include 3 | 4 | namespace zs { 5 | 6 | void *allocate(host_mem_tag, size_t size, size_t alignment, const source_location &loc) { 7 | void *ret{nullptr}; 8 | #ifdef _MSC_VER 9 | ret = _aligned_malloc(size, alignment); 10 | #else 11 | // ret = std::aligned_alloc(alignment, size); 12 | ret = std::malloc(size); 13 | #endif 14 | #if ZS_ENABLE_OFB_ACCESS_CHECK 15 | if (ret == nullptr) { 16 | const auto fileInfo = fmt::format("# File: \"{:<50}\"", loc.file_name()); 17 | const auto locInfo = fmt::format("# Ln {}, Col {}", loc.line(), loc.column()); 18 | const auto funcInfo = fmt::format("# Func: \"{}\"", loc.function_name()); 19 | std::cerr << fmt::format( 20 | "\nHost Side Error: allocattion failed (size: {} bytes, alignment: {} " 21 | "bytes)\n{:=^60}\n{}\n{}\n{}\n{:=^60}\n\n", 22 | size, alignment, " api error location ", fileInfo, locInfo, funcInfo, "="); 23 | } 24 | #endif 25 | return ret; 26 | } 27 | void deallocate(host_mem_tag, void *ptr, size_t size, size_t alignment, 28 | const source_location &loc) { 29 | #ifdef _MSC_VER 30 | _aligned_free(ptr); 31 | #else 32 | std::free(ptr); 33 | #endif 34 | } 35 | void memset(host_mem_tag, void *addr, int chval, size_t size, const source_location &loc) { 36 | std::memset(addr, chval, size); 37 | } 38 | void copy(host_mem_tag, void *dst, void *src, size_t size, const source_location &loc) { 39 | std::memcpy(dst, src, size); 40 | } 41 | 42 | } // namespace zs -------------------------------------------------------------------------------- /include/zensim/meta/Functional.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include "../ZpcFunctional.hpp" 6 | #include "Meta.h" 7 | 8 | namespace zs { 9 | 10 | // gcem alike, shorter alias for std::numeric_limits 11 | template using limits = std::numeric_limits; 12 | 13 | } // namespace zs 14 | -------------------------------------------------------------------------------- /include/zensim/meta/Meta.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #include "../TypeAlias.hpp" 7 | #include "../ZpcMeta.hpp" 8 | 9 | namespace zs { 10 | 11 | /// underlying_type 12 | /// common_type 13 | 14 | /// 15 | /// type decorato 16 | /// 17 | 18 | /// https://zh.cppreference.com/w/cpp/utility/tuple/make_tuple 19 | /// decay+unref 20 | template struct unwrap_refwrapper> { 21 | using type = T &; 22 | }; 23 | template struct is_refwrapper> : std::true_type {}; 24 | // specialization for std::integral_constant 25 | template struct is_value_wrapper> : true_type {}; 26 | 27 | /// 28 | /// detection 29 | /// 30 | namespace detail { 31 | template class Op, class... Args> 32 | struct detector { 33 | using value_t = false_type; 34 | using type = Default; 35 | }; 36 | 37 | template class Op, class... Args> 38 | struct detector>, Op, Args...> { 39 | using value_t = true_type; 40 | using type = Op; 41 | }; 42 | 43 | } // namespace detail 44 | 45 | struct nonesuch { 46 | nonesuch() = delete; 47 | template nonesuch(std::initializer_list) = delete; 48 | ~nonesuch() = delete; 49 | nonesuch(const nonesuch &) = delete; 50 | void operator=(nonesuch const &) = delete; 51 | }; 52 | 53 | template