merge master into branch, resolve conflicts

This commit is contained in:
Bryn Lloyd 2025-05-23 08:47:58 +02:00
commit 31d55962cf
350 changed files with 21221 additions and 23781 deletions

64
.clang-format Normal file
View File

@ -0,0 +1,64 @@
Language: Cpp
BasedOnStyle: LLVM
AlignAfterOpenBracket: Align
AlignConsecutiveAssignments: false
AlignConsecutiveDeclarations: false
AlignEscapedNewlines: Left
AlignOperands: true
AlignTrailingComments: true
AllowAllParametersOfDeclarationOnNextLine: false
AllowShortBlocksOnASingleLine: false
AllowShortCaseLabelsOnASingleLine: true
AllowShortFunctionsOnASingleLine: InlineOnly
AllowShortIfStatementsOnASingleLine: false
AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakTemplateDeclarations: Yes
BinPackArguments: false
BinPackParameters: false
BreakBeforeBinaryOperators: NonAssignment
BreakBeforeBraces: Custom
BraceWrapping:
AfterClass: true
AfterControlStatement: true
AfterEnum: true
AfterFunction: true
AfterNamespace: true
AfterStruct: true
AfterUnion: true
BeforeCatch: true
BeforeElse: true
IndentBraces: true
BreakBeforeTernaryOperators: true
BreakConstructorInitializersBeforeComma: false
BreakInheritanceList: AfterColon
ColumnLimit: 0
ConstructorInitializerAllOnOneLineOrOnePerLine: true
ConstructorInitializerIndentWidth: 2
ContinuationIndentWidth: 2
Cpp11BracedListStyle: true
EmptyLineBeforeAccessModifier: Never
IndentCaseLabels: false
IndentPPDirectives: None
IndentWidth: 2
KeepEmptyLinesAtTheStartOfBlocks: false
MaxEmptyLinesToKeep: 1
NamespaceIndentation: None
PointerAlignment: Left
ReflowComments: true
SortIncludes: false
SpaceAfterCStyleCast: false
SpaceAfterLogicalNot: false
SpaceBeforeParens: Custom
SpaceBeforeParensOptions:
AfterControlStatements: true
AfterFunctionDefinitionName: true
AfterFunctionDeclarationName: true
SpacesInAngles: false
SpacesInContainerLiterals: false
SpacesInCStyleCastParentheses: false
SpacesInSquareBrackets: false
Standard: Latest
TabWidth: 2
UseTab: Never

11
.gitignore vendored Normal file
View File

@ -0,0 +1,11 @@
*.whl
dist
build
*.vol.gz
*.vol
*.ini
__pycache__
*.json
*.zip
.cache
*.patch

View File

@ -32,13 +32,23 @@ push_github:
- "echo off"
- call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvars64"
- set CI_DIR=C:\ci\%CI_PIPELINE_ID%
- set CLCACHE_BASEDIR=C:\ci\%CI_PIPELINE_ID%
- set CCACHE_BASEDIR=C:\ci\%CI_PIPELINE_ID%
- set NETGEN_BUILD_DIR=%CI_DIR%\build
- set INSTALL_DIR=%CI_DIR%\install
- set SRC_DIR=%CI_DIR%\src
- set NETGENDIR=%INSTALL_DIR%\bin
- set PYTHONPATH=%INSTALL_DIR%\lib\site-packages
- set PATH=%NETGENDIR%;%PATH%
- echo %PATH%
- set PATH=%INSTALL_DIR%\bin;C:\python312;C:\python312\bin;C:\python312\Scripts;C:\tools\;%PATH%
- echo %PATH%
- set CCACHE_HARDLINK=1
- set CCACHE_NOHASHDIR=1
- C:\tools\ccache -s
- C:\tools\ccache -M 20G
- dir C:\python312
- python.exe --version
- python.exe -m pip install -U netgen-occt netgen-occt-devel
- cmake --version
build_win:
<<: *win
@ -54,12 +64,14 @@ build_win:
- >-
cmake %SRC_DIR%
-G Ninja
-DCMAKE_PREFIX=C:/python312
-DPython3_ROOT_DIR=C:/python312
-DCMAKE_INSTALL_PREFIX=%INSTALL_DIR%
-DCHECK_RANGE=ON
-DUSE_CGNS=ON
-DUSE_OCC=ON
-DUSE_CCACHE=ON
-DENABLE_UNIT_TESTS=ON
-DENABLE_UNIT_TESTS=OFF
-DCMAKE_BUILD_TYPE=Release
- cmake --build . --target install --config Release
@ -74,6 +86,21 @@ test_win:
- cd ..
needs: ["build_win"]
generate_results:
<<: *win
stage: test
script:
- pip install pytest-check
- cd tests\pytest
- python test_tutorials.py new_results.json
needs: ["build_win"]
when: manual
artifacts:
paths:
- tests/pytest/new_results.json
when: always
expire_in: 1 week
cleanup_win:
<<: *win
stage: cleanup
@ -99,6 +126,7 @@ cleanup_win:
- pwd
- ls
- docker info
- export PYTHONPATH=/opt/netgen/`python3 -c "import os.path, sysconfig;print(os.path.relpath(sysconfig.get_path('platlib'), sysconfig.get_path('data')))"`
variables:
UBUNTU_VERSION: "22.04"
@ -112,6 +140,7 @@ build_ubuntu_debug:
docker run
--cidfile netgen_${CI_PIPELINE_ID}_${UBUNTU_VERSION}.id
-e CCACHE_DIR=/ccache
-e PYTHONPATH=$PYTHONPATH
-v /mnt/ccache:/ccache
netgen_${CI_PIPELINE_ID}:${UBUNTU_VERSION}
bash /root/src/netgen/tests/build_debug.sh
@ -128,6 +157,7 @@ build_ubuntu_mpi:
docker run>-
--cidfile netgen_mpi_${CI_PIPELINE_ID}_${UBUNTU_VERSION}.id>-
-e CCACHE_DIR=/ccache
-e PYTHONPATH=$PYTHONPATH
-e RUN_SLOW_TESTS=${RUN_SLOW_TESTS}
-v /mnt/ccache:/ccache
netgen_mpi_${CI_PIPELINE_ID}:${UBUNTU_VERSION}
@ -141,8 +171,7 @@ test_ubuntu_debug:
script:
- >-
docker run
-e NETGENDIR=/opt/netgen/bin
-e PYTHONPATH=/opt/netgen/lib/python3/dist-packages
-e PYTHONPATH=$PYTHONPATH
netgen_${CI_PIPELINE_ID}_installed:${UBUNTU_VERSION}
bash -c 'cd /root/build/netgen && make test_netgen ARGS="-V --output-on-failure"'
needs: ["build_ubuntu_debug"]
@ -154,8 +183,7 @@ test_ubuntu_mpi:
- >-
docker run
-e RUN_SLOW_TESTS=${RUN_SLOW_TESTS}
-e NETGENDIR=/opt/netgen/bin
-e PYTHONPATH=/opt/netgen/lib/python3/dist-packages
-e PYTHONPATH=$PYTHONPATH
netgen_mpi_${CI_PIPELINE_ID}_installed:${UBUNTU_VERSION}
bash -c 'cd /root/build/netgen && make test_netgen ARGS="-V --output-on-failure"'
needs: ["build_ubuntu_mpi"]
@ -168,7 +196,7 @@ test_build_ngsolve:
- >-
docker run
-e NETGENDIR=/opt/netgen/bin
-e PYTHONPATH=/opt/netgen/lib/python3/dist-packages
-e PYTHONPATH=$PYTHONPATH
-e MKLROOT=/opt/intel/mkl
-v /opt/intel:/opt/intel
-e CCACHE_DIR=/ccache
@ -176,22 +204,6 @@ test_build_ngsolve:
netgen_${CI_PIPELINE_ID}_installed:${UBUNTU_VERSION}
bash -c 'cd /root/src/netgen/tests/ && ./build_ngsolve.sh'
# cpp guideline checks
# test_guidelines:
# <<: *ubuntu
# stage: test
# script:
# - docker run -e CCACHE_DIR=/ccache -v /mnt/ccache:/ccache netgen_${CI_PIPELINE_ID}:${UBUNTU_VERSION} bash /root/src/netgen/tests/build_guidelines.sh
# when: always
# allow_failure: true
# check if it compiles without spdlog
test_noSpdlog:
<<: *ubuntu
stage: test
script:
- docker run -e CCACHE_DIR=/ccache -v /mnt/ccache:/ccache netgen_${CI_PIPELINE_ID}:${UBUNTU_VERSION} bash /root/src/netgen/tests/build_nospdlog.sh
cleanup_ubuntu:
stage: cleanup
tags:
@ -222,7 +234,7 @@ cleanup_ubuntu:
- export SRC_DIR=$ROOT_DIR/src
- export BUILD_DIR=$ROOT_DIR/build
- export CMAKE_INSTALL_PREFIX=/tmp/$CI_PIPELINE_ID/install/Netgen.app
- export PYTHONPATH=$CMAKE_INSTALL_PREFIX/Contents/Resources/`python3 -c "from distutils.sysconfig import get_python_lib; print(get_python_lib(1,0,''))"`:.
- export PYTHONPATH=$CMAKE_INSTALL_PREFIX/Contents/Resources/`python3 -c "import os.path, sysconfig;print(os.path.relpath(sysconfig.get_path('platlib'), sysconfig.get_path('data')))"`:.
- export PATH=$CMAKE_INSTALL_PREFIX/Contents/MacOS:$PATH
build_mac:
@ -248,6 +260,7 @@ build_mac:
-DCMAKE_OSX_SYSROOT=/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk
-DUSE_CGNS=ON
-DUSE_OCC=ON
-DPython3_ROOT_DIR=/Library/Frameworks/Python.framework/Versions/3.8/
- make -j5 install
test_mac:
@ -268,7 +281,7 @@ cleanup_mac:
needs: ["test_mac"]
pip_linux:
image: quay.io/pypa/manylinux2014_x86_64
image: quay.io/pypa/manylinux_2_28_x86_64
stage: build
tags:
- pip
@ -284,10 +297,11 @@ pip_windows:
- pip
- windows
script:
- .\tests\build_pip.ps1 C:\Python38
- .\tests\build_pip.ps1 C:\Python39
- .\tests\build_pip.ps1 C:\Python310
- .\tests\build_pip.ps1 C:\Python313
- .\tests\build_pip.ps1 C:\Python312
- .\tests\build_pip.ps1 C:\Python311
- .\tests\build_pip.ps1 C:\Python310
- .\tests\build_pip.ps1 C:\Python39
when: manual
pip_macos:
@ -297,8 +311,9 @@ pip_macos:
- macosx
- m1
script:
- ./tests/build_pip_mac.sh 3.8
- ./tests/build_pip_mac.sh 3.9
- ./tests/build_pip_mac.sh 3.10
- ./tests/build_pip_mac.sh 3.13
- ./tests/build_pip_mac.sh 3.12
- ./tests/build_pip_mac.sh 3.11
- ./tests/build_pip_mac.sh 3.10
- ./tests/build_pip_mac.sh 3.9
when: manual

View File

@ -2,8 +2,12 @@ if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE "RelWithDebInfo" CACHE STRING INTERNAL)
endif(NOT CMAKE_BUILD_TYPE)
cmake_minimum_required(VERSION 3.13)
cmake_policy(VERSION 3.13)
cmake_minimum_required(VERSION 3.16)
cmake_policy(VERSION 3.16)
if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.24.0")
cmake_policy(SET CMP0135 NEW)
endif()
include (CMakeDependentOption)
option( USE_NATIVE_ARCH "build for native cpu architecture" ON)
@ -12,8 +16,8 @@ option( USE_GUI "build with GUI" ON )
option( USE_PYTHON "build with python interface" ON )
cmake_dependent_option( PREFER_SYSTEM_PYBIND11 "Use system wide PyBind11" OFF "USE_PYTHON" OFF)
option( USE_MPI "enable mpi parallelization" OFF )
option( USE_MPI4PY "enable mpi4py interface" ON )
option( USE_OCC "build with OpenCascade geometry kernel interface" OFF)
option( USE_MPI_WRAPPER "enable mpi wrapper (run-time dispatch of MPI library calls)" OFF )
option( USE_OCC "build with OpenCascade geometry kernel interface" ON)
option( USE_STLGEOM "build with STL geometry support" ON)
option( USE_CSG "build with CSG kernel" ON)
option( USE_INTERFACE "build nginterface" ON)
@ -28,7 +32,6 @@ option( USE_CCACHE "use ccache")
option( USE_INTERNAL_TCL "Compile tcl files into the code and don't install them" ON)
option( ENABLE_UNIT_TESTS "Enable Catch unit tests")
option( ENABLE_CPP_CORE_GUIDELINES_CHECK "Enable cpp core guideline checks on ngcore" OFF)
option( USE_SPDLOG "Enable spd log logging" OFF)
option( DEBUG_LOG "Enable more debug output (may increase computation time) - only works with USE_SPDLOG=ON" OFF)
option( CHECK_RANGE "Check array range access, automatically enabled if built in debug mode" OFF)
option( BUILD_STUB_FILES "Build stub files for better autocompletion" ON)
@ -71,19 +74,83 @@ endif(UNIX AND USE_SUPERBUILD)
if (USE_SUPERBUILD)
project (SUPERBUILD)
if (CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
set(CMAKE_INSTALL_PREFIX "${INSTALL_DIR_DEFAULT}" CACHE PATH "Install directory" FORCE)
else()
project(Netgen)
endif()
if (CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
set(CMAKE_INSTALL_PREFIX "${INSTALL_DIR_DEFAULT}" CACHE PATH "Install directory" FORCE)
endif()
set(NG_INSTALL_SUFFIX netgen CACHE STRING "Suffix appended to install directories (project name)")
if(USE_PYTHON)
if(${CMAKE_VERSION} VERSION_GREATER_EQUAL 3.18)
find_package(Python3 REQUIRED COMPONENTS Development.Module)
if(NOT EMSCRIPTEN)
find_package(Python3 COMPONENTS Interpreter Development.Embed)
endif()
else()
find_package(Python3 REQUIRED COMPONENTS Interpreter Development)
endif()
if(NOT CMAKE_CROSSCOMPILING)
find_package(Python3 REQUIRED COMPONENTS Interpreter)
execute_process(COMMAND ${Python3_EXECUTABLE} -c "import os.path, sysconfig;print(os.path.relpath(sysconfig.get_path('platlib'), sysconfig.get_path('data')))" OUTPUT_VARIABLE PYTHON_PACKAGES_INSTALL_DIR OUTPUT_STRIP_TRAILING_WHITESPACE)
file(TO_CMAKE_PATH ${PYTHON_PACKAGES_INSTALL_DIR} PYTHON_PACKAGES_INSTALL_DIR)
endif(NOT CMAKE_CROSSCOMPILING)
endif(USE_PYTHON)
if(APPLE AND NOT EMSCRIPTEN)
set(NG_INSTALL_DIR_BIN_DEFAULT Contents/MacOS)
set(NG_INSTALL_DIR_LIB_DEFAULT Contents/MacOS)
set(NG_INSTALL_DIR_CMAKE_DEFAULT Contents/Resources/CMake)
set(NG_INSTALL_DIR_PYTHON_DEFAULT Contents/Resources/${PYTHON_PACKAGES_INSTALL_DIR})
set(NG_INSTALL_DIR_RES_DEFAULT Contents/Resources/share)
set(NG_INSTALL_DIR_INCLUDE_DEFAULT Contents/Resources/include)
set(NG_RPATH_TOKEN "@loader_path")
else(APPLE AND NOT EMSCRIPTEN)
set(NG_INSTALL_DIR_BIN_DEFAULT bin)
set(NG_INSTALL_DIR_LIB_DEFAULT lib)
if(WIN32)
set(NG_INSTALL_DIR_CMAKE_DEFAULT cmake)
else(WIN32)
set(NG_INSTALL_DIR_CMAKE_DEFAULT lib/cmake/${NG_INSTALL_SUFFIX})
endif(WIN32)
set(NG_INSTALL_DIR_PYTHON_DEFAULT ${PYTHON_PACKAGES_INSTALL_DIR})
set(NG_INSTALL_DIR_RES_DEFAULT share)
set(NG_INSTALL_DIR_INCLUDE_DEFAULT include)
set(NG_RPATH_TOKEN "\$ORIGIN")
endif(APPLE AND NOT EMSCRIPTEN)
set(NG_INSTALL_DIR_PYTHON ${NG_INSTALL_DIR_PYTHON_DEFAULT} CACHE STRING "Install directory for Python files")
set(NG_INSTALL_DIR_BIN ${NG_INSTALL_DIR_BIN_DEFAULT} CACHE STRING "Install directory for executables")
set(NG_INSTALL_DIR_LIB ${NG_INSTALL_DIR_LIB_DEFAULT} CACHE STRING "Install directory for libraries")
set(NG_INSTALL_DIR_INCLUDE ${NG_INSTALL_DIR_INCLUDE_DEFAULT} CACHE STRING "Install directory for header files")
set(NG_INSTALL_DIR_CMAKE ${NG_INSTALL_DIR_CMAKE_DEFAULT} CACHE STRING "Install directory for CMake files")
set(NG_INSTALL_DIR_RES ${NG_INSTALL_DIR_RES_DEFAULT} CACHE STRING "Install directory for resources")
get_filename_component(NETGEN_CMAKE_DIR_ABSOLUTE ${NG_INSTALL_DIR_CMAKE} ABSOLUTE BASE_DIR ${CMAKE_INSTALL_PREFIX})
get_filename_component(NETGEN_BINARY_DIR_ABSOLUTE ${NG_INSTALL_DIR_BIN} ABSOLUTE BASE_DIR ${CMAKE_INSTALL_PREFIX})
get_filename_component(NETGEN_LIBRARY_DIR_ABSOLUTE ${NG_INSTALL_DIR_LIB} ABSOLUTE BASE_DIR ${CMAKE_INSTALL_PREFIX})
get_filename_component(NETGEN_INCLUDE_DIR_ABSOLUTE ${NG_INSTALL_DIR_INCLUDE} ABSOLUTE BASE_DIR ${CMAKE_INSTALL_PREFIX})
get_filename_component(NETGEN_RESOURCE_DIR_ABSOLUTE ${NG_INSTALL_DIR_RES} ABSOLUTE BASE_DIR ${CMAKE_INSTALL_PREFIX})
file(RELATIVE_PATH NETGEN_DIR ${NETGEN_CMAKE_DIR_ABSOLUTE} ${CMAKE_INSTALL_PREFIX})
file(RELATIVE_PATH NETGEN_BINARY_DIR ${NETGEN_CMAKE_DIR_ABSOLUTE} ${NETGEN_BINARY_DIR_ABSOLUTE})
file(RELATIVE_PATH NETGEN_LIBRARY_DIR ${NETGEN_CMAKE_DIR_ABSOLUTE} ${NETGEN_LIBRARY_DIR_ABSOLUTE})
file(RELATIVE_PATH NETGEN_INCLUDE_DIR ${NETGEN_CMAKE_DIR_ABSOLUTE} ${NETGEN_INCLUDE_DIR_ABSOLUTE})
file(RELATIVE_PATH NETGEN_RESOURCE_DIR ${NETGEN_CMAKE_DIR_ABSOLUTE} ${NETGEN_RESOURCE_DIR_ABSOLUTE})
file(RELATIVE_PATH NETGEN_RPATH ${NETGEN_BINARY_DIR_ABSOLUTE} ${NETGEN_LIBRARY_DIR_ABSOLUTE})
if (USE_SUPERBUILD)
# execute the superbuild (this script will be invoked again without the
# USE_SUPERBUILD option this time)
include (cmake/SuperBuild.cmake)
return() # stop processing this file further
else()
project(Netgen)
if (CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
set(CMAKE_INSTALL_PREFIX "${INSTALL_DIR_DEFAULT}" CACHE PATH "Install directory" FORCE)
endif()
endif()
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
@ -97,6 +164,7 @@ if(USE_CCACHE)
find_program(CCACHE_FOUND NAMES ccache ccache.bat)
if(CCACHE_FOUND)
set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE ${CCACHE_FOUND})
message(STATUS "Using ccache ${CCACHE_FOUND}")
endif(CCACHE_FOUND)
endif(USE_CCACHE)
@ -125,63 +193,6 @@ include_directories ("${PROJECT_BINARY_DIR}")
set(CMAKE_INCLUDE_CURRENT_DIR ON)
if(USE_PYTHON)
find_package(PythonInterp 3 REQUIRED)
if(NOT BUILD_FOR_CONDA)
find_package(PythonLibs 3 REQUIRED)
endif()
execute_process(COMMAND ${PYTHON_EXECUTABLE} -c "from distutils.sysconfig import get_python_lib; print(get_python_lib(1,0,''))" OUTPUT_VARIABLE PYTHON_PACKAGES_INSTALL_DIR OUTPUT_STRIP_TRAILING_WHITESPACE)
file(TO_CMAKE_PATH ${PYTHON_PACKAGES_INSTALL_DIR} PYTHON_PACKAGES_INSTALL_DIR)
endif(USE_PYTHON)
set(NG_INSTALL_SUFFIX netgen CACHE STRING "Suffix appended to install directories (project name)")
if(APPLE)
set(NG_INSTALL_DIR_BIN_DEFAULT Contents/MacOS)
set(NG_INSTALL_DIR_LIB_DEFAULT Contents/MacOS)
set(NG_INSTALL_DIR_CMAKE_DEFAULT Contents/Resources/CMake)
set(NG_INSTALL_DIR_PYTHON_DEFAULT Contents/Resources/${PYTHON_PACKAGES_INSTALL_DIR})
set(NG_INSTALL_DIR_RES_DEFAULT Contents/Resources/share)
set(NG_INSTALL_DIR_INCLUDE_DEFAULT Contents/Resources/include)
set(NG_RPATH_TOKEN "@loader_path")
else(APPLE)
set(NG_INSTALL_DIR_BIN_DEFAULT bin)
set(NG_INSTALL_DIR_LIB_DEFAULT lib)
if(WIN32)
set(NG_INSTALL_DIR_CMAKE_DEFAULT cmake)
else(WIN32)
set(NG_INSTALL_DIR_CMAKE_DEFAULT lib/cmake/${NG_INSTALL_SUFFIX})
endif(WIN32)
set(NG_INSTALL_DIR_PYTHON_DEFAULT ${PYTHON_PACKAGES_INSTALL_DIR})
set(NG_INSTALL_DIR_RES_DEFAULT share)
set(NG_INSTALL_DIR_INCLUDE_DEFAULT include)
set(NG_RPATH_TOKEN "\$ORIGIN")
endif(APPLE)
set(NG_INSTALL_DIR_PYTHON ${NG_INSTALL_DIR_PYTHON_DEFAULT} CACHE STRING "Install directory for Python files")
set(NG_INSTALL_DIR_BIN ${NG_INSTALL_DIR_BIN_DEFAULT} CACHE STRING "Install directory for executables")
set(NG_INSTALL_DIR_LIB ${NG_INSTALL_DIR_LIB_DEFAULT} CACHE STRING "Install directory for libraries")
set(NG_INSTALL_DIR_INCLUDE ${NG_INSTALL_DIR_INCLUDE_DEFAULT} CACHE STRING "Install directory for header files")
set(NG_INSTALL_DIR_CMAKE ${NG_INSTALL_DIR_CMAKE_DEFAULT} CACHE STRING "Install directory for CMake files")
set(NG_INSTALL_DIR_RES ${NG_INSTALL_DIR_RES_DEFAULT} CACHE STRING "Install directory for resources")
get_filename_component(NETGEN_CMAKE_DIR_ABSOLUTE ${NG_INSTALL_DIR_CMAKE} ABSOLUTE BASE_DIR ${CMAKE_INSTALL_PREFIX})
get_filename_component(NETGEN_BINARY_DIR_ABSOLUTE ${NG_INSTALL_DIR_BIN} ABSOLUTE BASE_DIR ${CMAKE_INSTALL_PREFIX})
get_filename_component(NETGEN_LIBRARY_DIR_ABSOLUTE ${NG_INSTALL_DIR_LIB} ABSOLUTE BASE_DIR ${CMAKE_INSTALL_PREFIX})
get_filename_component(NETGEN_INCLUDE_DIR_ABSOLUTE ${NG_INSTALL_DIR_INCLUDE} ABSOLUTE BASE_DIR ${CMAKE_INSTALL_PREFIX})
get_filename_component(NETGEN_RESOURCE_DIR_ABSOLUTE ${NG_INSTALL_DIR_RES} ABSOLUTE BASE_DIR ${CMAKE_INSTALL_PREFIX})
file(RELATIVE_PATH NETGEN_DIR ${NETGEN_CMAKE_DIR_ABSOLUTE} ${CMAKE_INSTALL_PREFIX})
file(RELATIVE_PATH NETGEN_BINARY_DIR ${NETGEN_CMAKE_DIR_ABSOLUTE} ${NETGEN_BINARY_DIR_ABSOLUTE})
file(RELATIVE_PATH NETGEN_LIBRARY_DIR ${NETGEN_CMAKE_DIR_ABSOLUTE} ${NETGEN_LIBRARY_DIR_ABSOLUTE})
file(RELATIVE_PATH NETGEN_INCLUDE_DIR ${NETGEN_CMAKE_DIR_ABSOLUTE} ${NETGEN_INCLUDE_DIR_ABSOLUTE})
file(RELATIVE_PATH NETGEN_RESOURCE_DIR ${NETGEN_CMAKE_DIR_ABSOLUTE} ${NETGEN_RESOURCE_DIR_ABSOLUTE})
file(RELATIVE_PATH NETGEN_RPATH ${NETGEN_BINARY_DIR_ABSOLUTE} ${NETGEN_LIBRARY_DIR_ABSOLUTE})
if(USE_PYTHON)
get_filename_component(NETGEN_PYTHON_DIR_ABSOLUTE ${NG_INSTALL_DIR_PYTHON} ABSOLUTE BASE_DIR ${CMAKE_INSTALL_PREFIX})
file(RELATIVE_PATH NETGEN_PYTHON_DIR ${NETGEN_CMAKE_DIR_ABSOLUTE} ${NETGEN_PYTHON_DIR_ABSOLUTE})
@ -252,7 +263,6 @@ target_include_directories(nglib PRIVATE ${ZLIB_INCLUDE_DIRS})
if(USE_GUI)
target_include_directories(nggui PRIVATE ${ZLIB_INCLUDE_DIRS})
endif(USE_GUI)
target_link_libraries(nglib PRIVATE ${ZLIB_LIBRARIES})
#######################################################################
if(WIN32)
@ -313,11 +323,11 @@ if (USE_PYTHON)
add_subdirectory(external_dependencies/pybind11)
endif()
target_include_directories(netgen_python INTERFACE ${pybind11_INCLUDE_DIR} ${PYTHON_INCLUDE_DIRS})
target_include_directories(nglib PRIVATE ${pybind11_INCLUDE_DIR} ${PYTHON_INCLUDE_DIRS})
if(NOT ${BUILD_FOR_CONDA} OR WIN32)
# Don't link python libraries in conda environments
target_link_libraries(netgen_python INTERFACE ${PYTHON_LIBRARIES})
target_compile_definitions(netgen_python INTERFACE NG_PYTHON NETGEN_PYTHON)
target_include_directories(netgen_python INTERFACE ${pybind11_INCLUDE_DIR} ${Python3_INCLUDE_DIRS})
target_include_directories(nglib PRIVATE ${pybind11_INCLUDE_DIR} ${Python3_INCLUDE_DIRS})
if(Python3_LIBRARIES AND (WIN32 OR NOT BUILD_FOR_CONDA))
target_link_libraries(netgen_python INTERFACE ${Python3_LIBRARIES})
endif()
if(NG_INSTALL_PYBIND)
@ -327,30 +337,19 @@ if (USE_PYTHON)
endif (USE_PYTHON)
#######################################################################
add_library(netgen_mpi INTERFACE)
add_library(netgen_metis INTERFACE)
if (USE_MPI)
find_package(MPI REQUIRED)
target_include_directories(netgen_mpi INTERFACE ${MPI_CXX_INCLUDE_PATH})
target_link_libraries(netgen_mpi INTERFACE ${MPI_mpi_LIBRARY} ${MPI_CXX_LIBRARIES} )
target_compile_definitions(netgen_mpi INTERFACE PARALLEL )
set(MPI_DETERMINE_LIBRARY_VERSION TRUE)
find_package(MPI)
find_package(METIS REQUIRED)
target_include_directories(netgen_metis INTERFACE ${METIS_INCLUDE_DIR})
target_link_libraries(netgen_metis INTERFACE ${METIS_LIBRARY} )
target_compile_definitions(netgen_metis INTERFACE METIS )
if(USE_MPI4PY AND USE_PYTHON)
execute_process(COMMAND ${PYTHON_EXECUTABLE} -c "import mpi4py;print(mpi4py.get_include())" OUTPUT_VARIABLE mpi4py_path OUTPUT_STRIP_TRAILING_WHITESPACE)
find_path(MPI4PY_INCLUDE_DIR mpi4py.h HINTS ${mpi4py_path}/mpi4py NO_DEFAULT_PATH REQUIRED)
target_include_directories(netgen_metis INTERFACE ${MPI4PY_INCLUDE_DIR})
target_compile_definitions(netgen_metis INTERFACE NG_MPI4PY )
message(STATUS "Found mpi4py: ${MPI4PY_INCLUDE_DIR}")
endif(USE_MPI4PY AND USE_PYTHON)
endif (USE_MPI)
install(TARGETS netgen_mpi netgen_metis ${NG_INSTALL_DIR})
#######################################################################
add_library(occ_libs INTERFACE IMPORTED)
if (USE_OCC)
find_package(OpenCascade NAMES OpenCASCADE opencascade REQUIRED CMAKE_FIND_ROOT_PATH_BOTH)
add_definitions(-DOCCGEOMETRY)
@ -366,53 +365,66 @@ if (USE_OCC)
TKGeomAlgo
TKGeomBase
TKHLR
TKIGES
TKLCAF
TKMath
TKMesh
TKOffset
TKPrim
TKSTEP
TKSTEP209
TKSTEPAttr
TKSTEPBase
TKSTL
TKService
TKShHealing
TKTopAlgo
TKV3d
TKVCAF
TKXCAF
TKXDEIGES
TKXDESTEP
TKXSBase
TKernel
)
include_directories(${OpenCASCADE_INCLUDE_DIR})
if(${OpenCASCADE_MAJOR_VERSION}.${OpenCASCADE_MINOR_VERSION} VERSION_GREATER_EQUAL 7.8)
list(APPEND OCC_LIBRARIES TKDEIGES TKDESTEP TKDESTL)
else()
list(APPEND OCC_LIBRARIES
TKIGES
TKSTEP
TKSTL
TKXDEIGES
TKXDESTEP
TKSTEP209
TKSTEPAttr
TKSTEPBase
)
endif()
if(UNIX AND NOT APPLE)
list(PREPEND OCC_LIBRARIES -Wl,--start-group)
list(APPEND OCC_LIBRARIES -Wl,--end-group)
endif()
target_link_libraries(occ_libs INTERFACE ${OCC_LIBRARIES})
get_target_property(occ_include_dir TKernel INTERFACE_INCLUDE_DIRECTORIES)
if(NOT occ_include_dir)
set(occ_include_dir ${OpenCASCADE_INCLUDE_DIR})
endif()
target_include_directories(occ_libs INTERFACE ${occ_include_dir})
message(STATUS "OpenCasCade include dirs: ${occ_include_dir}")
if(NOT OpenCASCADE_BUILD_SHARED_LIBS)
if(OpenCASCADE_WITH_FREETYPE)
find_library( FREETYPE NAMES freetype HINTS ${OpenCASCADE_INSTALL_PREFIX}/lib)
find_library( FREETYPE NAMES freetype HINTS ${OpenCASCADE_LIBRARY_DIR})
list(APPEND OCC_LIBRARIES ${FREETYPE})
target_link_libraries(occ_libs INTERFACE ${FREETYPE})
if(UNIX AND NOT APPLE)
find_package(Fontconfig REQUIRED)
list(APPEND OCC_LIBRARIES ${Fontconfig_LIBRARIES})
target_link_libraries(occ_libs INTERFACE ${Fontconfig_LIBRARIES})
endif()
endif(OpenCASCADE_WITH_FREETYPE)
if(UNIX AND NOT APPLE)
set(THREADS_PREFER_PTHREAD_FLAG ON)
find_package(Threads REQUIRED)
list(APPEND OCC_LIBRARIES Threads::Threads)
list(PREPEND OCC_LIBRARIES -Wl,--start-group)
list(APPEND OCC_LIBRARIES -Wl,--end-group)
endif()
if(WIN32)
list(APPEND OCC_LIBRARIES Ws2_32.lib)
endif()
set(THREADS_PREFER_PTHREAD_FLAG ON)
find_package(Threads REQUIRED)
target_link_libraries(occ_libs INTERFACE Threads::Threads)
endif()
message(STATUS "OCC DIRS ${OpenCASCADE_INCLUDE_DIR}")
if(WIN32 AND USE_GUI)
target_link_libraries(nggui PRIVATE ${OCC_LIBRARIES})
target_link_libraries(nggui PRIVATE Ws2_32.lib)
endif(WIN32 AND USE_GUI)
if(USE_GUI)
target_link_libraries(nggui PRIVATE occ_libs)
endif(USE_GUI)
endif (USE_OCC)
#######################################################################
@ -621,6 +633,16 @@ if(UNIX)
endif(temp)
endif(UNIX)
if(USE_PYTHON AND NOT SKBUILD)
# install egg file to let python/pip know that Netgen ist installed
file( WRITE "netgen_mesher-py3.egg-info"
"Metadata-Version: 2.1
Name: netgen-mesher
Version: ${NETGEN_VERSION_MAJOR}.${NETGEN_VERSION_MINOR}.${NETGEN_VERSION_PATCH}.post${NETGEN_VERSION_TWEAK}
")
install(FILES netgen_mesher-py3.egg-info DESTINATION ${NG_INSTALL_DIR_PYTHON} COMPONENT netgen)
endif()
if(APPLE AND NOT SKBUILD)
# create some auxiliary files
set(mac_startup ${CMAKE_CURRENT_BINARY_DIR}/startup.sh)

View File

@ -4,3 +4,4 @@ NETGEN is an automatic 3d tetrahedral mesh generator. It accepts input from cons
Find the Open Source Community on https://ngsolve.org
Support & Services: https://cerbsim.com

View File

@ -38,9 +38,9 @@ set(NETGEN_OCC_LIBRARIES_BIN "@OpenCASCADE_BINARY_DIR@")
set(NETGEN_OCC_LIBRARIES "@OCC_LIBRARIES@")
set(NETGEN_OCC_LIBRARY_DIR "@OpenCASCADE_LIBRARY_DIR@")
set(NETGEN_OPENGL_LIBRARIES "@OPENGL_LIBRARIES@")
set(NETGEN_PYTHON_EXECUTABLE "@PYTHON_EXECUTABLE@")
set(NETGEN_PYTHON_INCLUDE_DIRS "@PYTHON_INCLUDE_DIRS@")
set(NETGEN_PYTHON_LIBRARIES "@PYTHON_LIBRARIES@")
set(NETGEN_PYTHON_EXECUTABLE "@Python3_EXECUTABLE@")
set(NETGEN_PYTHON_INCLUDE_DIRS "@Python3_INCLUDE_DIRS@")
set(NETGEN_PYTHON_LIBRARIES "@Python3_LIBRARIES@")
set(NETGEN_TCL_INCLUDE_PATH "@TCL_INCLUDE_PATH@")
set(NETGEN_TCL_LIBRARY "@TCL_STUB_LIBRARY@")
set(NETGEN_TK_DND_LIBRARY "@TK_DND_LIBRARY@")

View File

@ -14,9 +14,16 @@ set (SUBPROJECT_ARGS
PREFIX ${CMAKE_CURRENT_BINARY_DIR}/dependencies
)
if (EMSCRIPTEN)
set (SUBPROJECT_ARGS
${SUBPROJECT_ARGS}
CMAKE_COMMAND emcmake ${CMAKE_COMMAND})
endif()
# only show output on failure in ci-builds
if(DEFINED ENV{CI})
set (SUBPROJECT_ARGS
${SUBPROJECT_ARGS}
LOG_DOWNLOAD ON
LOG_BUILD ON
LOG_INSTALL ON
@ -50,7 +57,7 @@ set_vars(SUBPROJECT_CMAKE_ARGS CMAKE_C_COMPILER)
set_vars(SUBPROJECT_CMAKE_ARGS CMAKE_CXX_COMPILER)
set_vars(SUBPROJECT_CMAKE_ARGS CMAKE_BUILD_TYPE)
set(SUBPROJECT_CMAKE_ARGS "${SUBPROJECT_CMAKE_ARGS};-DCMAKE_POSITION_INDEPENDENT_CODE=ON" CACHE INTERNAL "")
set(SUBPROJECT_CMAKE_ARGS "${SUBPROJECT_CMAKE_ARGS};-DCMAKE_POSITION_INDEPENDENT_CODE=ON;-DCMAKE_POLICY_VERSION_MINIMUM=3.5" CACHE INTERNAL "")
if(USE_CCACHE)
find_program(CCACHE_FOUND NAMES ccache ccache.bat)
@ -82,8 +89,12 @@ if(BUILD_OCC)
set(OCC_DIR ${CMAKE_CURRENT_BINARY_DIR}/dependencies/occ)
ExternalProject_Add(project_occ
URL https://github.com/Open-Cascade-SAS/OCCT/archive/refs/tags/V7_6_1.zip
URL_MD5 e891d85cad61c5cc7ccba3d0110f0c8c
# URL https://github.com/Open-Cascade-SAS/OCCT/archive/refs/tags/V7_6_3.zip
# URL_MD5 2426e373903faabbd4f96a01a934b66d
# URL https://github.com/Open-Cascade-SAS/OCCT/archive/refs/tags/V7_7_2.zip
# URL_MD5 533eb4f18af0f77ae321b158caeaee79
URL https://github.com/Open-Cascade-SAS/OCCT/archive/refs/tags/V7_8_1.zip
URL_MD5 bf62952a03696dab9e4272aa8efacb1a
DOWNLOAD_DIR ${CMAKE_CURRENT_SOURCE_DIR}/external_dependencies
${SUBPROJECT_ARGS}
CMAKE_ARGS
@ -97,6 +108,7 @@ if(BUILD_OCC)
-DBUILD_MODULE_Visualization:BOOL=OFF
-DBUILD_MODULE_ApplicationFramework:BOOL=OFF
-DBUILD_MODULE_Draw:BOOL=OFF
-DBUILD_MODULE_DETools:BOOL=OFF
-DUSE_FREETYPE:BOOL=OFF
-DUSE_OPENGL:BOOL=OFF
-DUSE_XLIB:BOOL=OFF
@ -108,44 +120,42 @@ if(BUILD_OCC)
list(APPEND NETGEN_DEPENDENCIES project_occ)
set(OpenCascade_ROOT ${OCC_DIR})
else(BUILD_OCC)
if(WIN32 AND NOT OCC_INCLUDE_DIR AND NOT OpenCASCADE_DIR)
# we can download prebuilt occ binaries for windows
ExternalProject_Add(win_download_occ
${SUBPROJECT_ARGS}
URL ${OCC_DOWNLOAD_URL_WIN}
UPDATE_COMMAND "" # Disable update
BUILD_IN_SOURCE 1
CONFIGURE_COMMAND ""
BUILD_COMMAND ""
INSTALL_COMMAND ${CMAKE_COMMAND} -E copy_directory . ${CMAKE_INSTALL_PREFIX}
)
list(APPEND NETGEN_DEPENDENCIES win_download_occ)
else()
find_package(OpenCascade NAMES OpenCasCade OpenCASCADE opencascade REQUIRED)
find_package(OpenCascade NAMES OpenCasCade OpenCASCADE opencascade)
if(NOT OpenCascade_FOUND)
message(FATAL_ERROR "Opencascade not found, either\n\
- install pip packages netgen-occt-devel netgen-occ\n\
- set OpenCascade_DIR to a directory containting opencascadeConfig.cmake\n\
- build OpenCascade automatically by passing -DBUILD_OCC=ON\n\
- disable OpenCascade by passing -DUSE_OCC=OFF\n\
")
endif()
endif(BUILD_OCC)
endif(USE_OCC)
if(BUILD_ZLIB)
set(ZLIB_DIR ${CMAKE_CURRENT_BINARY_DIR}/dependencies/zlib)
set(ZLIB_ROOT ${CMAKE_CURRENT_BINARY_DIR}/dependencies/zlib)
ExternalProject_Add(project_zlib
${SUBPROJECT_ARGS}
URL https://github.com/madler/zlib/archive/refs/tags/v1.2.11.zip
URL_MD5 9d6a627693163bbbf3f26403a3a0b0b1
DOWNLOAD_DIR ${CMAKE_CURRENT_SOURCE_DIR}/external_dependencies
CMAKE_ARGS
-DCMAKE_INSTALL_PREFIX=${ZLIB_DIR}
-DCMAKE_INSTALL_PREFIX=${ZLIB_ROOT}
${SUBPROJECT_CMAKE_ARGS}
UPDATE_COMMAND "" # Disable update
BUILD_IN_SOURCE 1
)
list(APPEND NETGEN_DEPENDENCIES project_zlib)
list(APPEND NETGEN_CMAKE_PREFIX_PATH ${ZLIB_DIR})
if(WIN32)
# force linking the static library
set(ZLIB_INCLUDE_DIRS ${ZLIB_DIR}/include)
set(ZLIB_LIBRARIES ${ZLIB_DIR}/lib/zlibstatic.lib)
set(ZLIB_INCLUDE_DIRS ${ZLIB_ROOT}/include)
set(ZLIB_LIBRARIES ${ZLIB_ROOT}/lib/zlibstatic.lib)
set(ZLIB_LIBRARY_RELEASE ${ZLIB_ROOT}/lib/zlibstatic.lib)
else(WIN32)
set(ZLIB_INCLUDE_DIRS ${ZLIB_ROOT}/include)
set(ZLIB_LIBRARIES ${ZLIB_ROOT}/lib/libz.a)
set(ZLIB_LIBRARY_RELEASE ${ZLIB_ROOT}/lib/libz.a)
endif(WIN32)
else()
include(cmake/external_projects/zlib.cmake)
@ -165,16 +175,20 @@ if (USE_PYTHON)
else( PYBIND_INCLUDE_DIR )
message(FATAL_ERROR "Could NOT find pybind11!")
endif( PYBIND_INCLUDE_DIR )
find_package(PythonInterp 3 REQUIRED)
if(NOT BUILD_FOR_CONDA)
find_package(PythonLibs 3 REQUIRED)
if(${CMAKE_VERSION} VERSION_GREATER_EQUAL 3.18)
find_package(Python3 COMPONENTS Interpreter Development.Module)
if(NOT EMSCRIPTEN)
find_package(Python3 COMPONENTS Interpreter Development.Embed)
endif()
else()
find_package(Python3 REQUIRED COMPONENTS Interpreter Development)
endif()
set_vars(NETGEN_CMAKE_ARGS
PYTHON_INCLUDE_DIRS
PYTHON_LIBRARIES
PYTHON_EXECUTABLE
PYTHON_VERSION
Python3_INCLUDE_DIRS
Python3_LIBRARIES
Python3_EXECUTABLE
Python3_VERSION
PYBIND_INCLUDE_DIR
NG_INSTALL_PYBIND
)
@ -192,7 +206,6 @@ endif(USE_CGNS)
#######################################################################
if(USE_MPI)
if(UNIX)
if (METIS_DIR)
message(STATUS "Using external METIS at: ${METIS_DIR}")
else (METIS_DIR)
@ -203,23 +216,24 @@ if(USE_MPI)
include(cmake/external_projects/metis.cmake)
endif(NOT METIS_FOUND)
endif(METIS_DIR)
else(UNIX)
find_package(METIS REQUIRED)
endif(UNIX)
endif(USE_MPI)
#######################################################################
# propagate cmake variables to Netgen subproject
set_vars( NETGEN_CMAKE_ARGS
CMAKE_MODULE_LINKER_FLAGS
CMAKE_MODULE_LINKER_FLAGS_RELEASE
CMAKE_SHARED_LINKER_FLAGS
CMAKE_SHARED_LINKER_FLAGS_RELEASE
CMAKE_CXX_FLAGS
CMAKE_CXX_FLAGS_RELEASE
CMAKE_STRIP
USE_GUI
USE_PYTHON
USE_MPI
USE_MPI_WRAPPER
USE_VT
USE_VTUNE
USE_NUMA
@ -245,10 +259,20 @@ set_vars( NETGEN_CMAKE_ARGS
OpenCascade_ROOT
ZLIB_INCLUDE_DIRS
ZLIB_LIBRARIES
ZLIB_LIBRARY_RELEASE
ZLIB_ROOT
NGLIB_LIBRARY_TYPE
NGCORE_LIBRARY_TYPE
NGGUI_LIBRARY_TYPE
NG_INSTALL_DIR_PYTHON
NG_INSTALL_DIR_BIN
NG_INSTALL_DIR_LIB
NG_INSTALL_DIR_INCLUDE
NG_INSTALL_DIR_CMAKE
NG_INSTALL_DIR_RES
NG_INSTALL_SUFFIX
)
# propagate all variables set on the command line using cmake -DFOO=BAR

View File

@ -3,8 +3,8 @@ set(METIS_DIR ${CMAKE_CURRENT_BINARY_DIR}/dependencies/metis)
ExternalProject_Add(project_metis
PREFIX ${CMAKE_CURRENT_BINARY_DIR}/dependencies
URL https://bitbucket.org/petsc/pkg-metis/get/v5.1.0-p6.tar.gz
URL_MD5 55fc654bb838846b856ba898795143f1
URL https://bitbucket.org/petsc/pkg-metis/get/v5.1.0-p12.tar.gz
URL_MD5 6cd66f75f88dfa2cf043de011f85d8bc
DOWNLOAD_DIR ${CMAKE_CURRENT_SOURCE_DIR}/external_dependencies
CMAKE_ARGS
-DGKLIB_PATH=${METIS_SRC_DIR}/GKlib

View File

@ -7,7 +7,7 @@ else(LINUX)
if(SKBUILD)
# we are building a pip package - download the tcl/tk sources matching the tkinter version (for private headers not shipped with python)
execute_process(COMMAND ${PYTHON_EXECUTABLE} -c
execute_process(COMMAND ${Python3_EXECUTABLE} -c
"import tkinter;print(tkinter.Tcl().eval('info patchlevel').replace('.','-'))"
OUTPUT_VARIABLE PYTHON_TCL_VERSION OUTPUT_STRIP_TRAILING_WHITESPACE)
@ -39,7 +39,7 @@ set(TK_INCLUDE_PATH ${TK_DIR}/generic)
list(APPEND NETGEN_DEPENDENCIES project_tcl project_tk)
if(APPLE OR WIN32)
execute_process(COMMAND ${PYTHON_EXECUTABLE} -c "import sys; print(sys.prefix)" OUTPUT_VARIABLE PYTHON_PREFIX OUTPUT_STRIP_TRAILING_WHITESPACE)
execute_process(COMMAND ${Python3_EXECUTABLE} -c "import sys; print(sys.prefix)" OUTPUT_VARIABLE PYTHON_PREFIX OUTPUT_STRIP_TRAILING_WHITESPACE)
file(TO_CMAKE_PATH ${PYTHON_PREFIX} PYTHON_PREFIX)
set(tcl_find_args
@ -51,12 +51,17 @@ if(APPLE OR WIN32)
NO_SYSTEM_ENVIRONMENT_PATH
NO_CMAKE_SYSTEM_PATH
NO_CMAKE_FIND_ROOT_PATH
HINTS ${PYTHON_PREFIX}/lib ${PYTHON_PREFIX}/tcl
HINTS
${PYTHON_PREFIX}/lib
${PYTHON_PREFIX}/tcl
${PYTHON_PREFIX}/Frameworks
${PYTHON_PREFIX}/Frameworks/Tcl.framework
${PYTHON_PREFIX}/Frameworks/Tk.framework
)
find_library(TCL_STUB_LIBRARY NAMES tclstub85 tclstub8.5 tclstub86 tclstub8.6 ${tcl_find_args})
find_library(TK_STUB_LIBRARY NAMES tkstub85 tkstub8.5 tkstub86 tkstub8.6 ${tcl_find_args})
find_library(TCL_LIBRARY NAMES tcl85 tcl8.5 tcl86 tcl8.6 tcl86t ${tcl_find_args})
find_library(TK_LIBRARY NAMES tk85 tk8.5 tk86 tk8.6 tk86t ${tcl_find_args})
find_library(TCL_LIBRARY NAMES tcl85 tcl8.5 tcl86 tcl8.6 tcl86t Tcl ${tcl_find_args})
find_library(TK_LIBRARY NAMES tk85 tk8.5 tk86 tk8.6 tk86t Tk ${tcl_find_args})
else()
# use system tcl/tk on linux
find_package(TclStub REQUIRED)
@ -93,7 +98,7 @@ if(APPLE)
)
ExternalProject_Add(project_tkdnd
URL "http://sourceforge.net/projects/tkdnd/files/TkDND/TkDND%202.8/tkdnd2.8-src.tar.gz"
URL "https://src.fedoraproject.org/repo/pkgs/tkdnd/tkdnd2.8-src.tar.gz/a6d47a996ea957416469b12965d4db91/tkdnd2.8-src.tar.gz"
URL_MD5 a6d47a996ea957416469b12965d4db91
DEPENDS project_tcl project_tk
DOWNLOAD_DIR ${CMAKE_CURRENT_SOURCE_DIR}/external_dependencies
@ -104,6 +109,7 @@ if(APPLE)
-DCMAKE_INSTALL_PREFIX=${CMAKE_INSTALL_PREFIX}/Contents/MacOS
-DTCL_INCLUDE_PATH=${CMAKE_INSTALL_PREFIX}/Contents/Frameworks/Tcl.framework/Headers
-DTK_INCLUDE_PATH=${CMAKE_INSTALL_PREFIX}/Contents/Frameworks/Tk.framework/Headers
-DCMAKE_POLICY_VERSION_MINIMUM=3.5
${SUBPROJECT_ARGS}
)
@ -183,7 +189,10 @@ elseif(WIN32)
BUILD_IN_SOURCE 1
CONFIGURE_COMMAND ""
BUILD_COMMAND ""
INSTALL_COMMAND ${CMAKE_COMMAND} -E copy_directory . ${CMAKE_INSTALL_PREFIX}
INSTALL_COMMAND ${CMAKE_COMMAND} -E copy_directory lib ${CMAKE_INSTALL_PREFIX}/${NG_INSTALL_DIR_LIB}
COMMAND ${CMAKE_COMMAND} -E copy_directory bin ${CMAKE_INSTALL_PREFIX}/${NG_INSTALL_DIR_BIN}
COMMAND ${CMAKE_COMMAND} -E copy_directory include ${CMAKE_INSTALL_PREFIX}/${NG_INSTALL_DIR_INCLUDE}
${SUBPROJECT_ARGS}
)

View File

@ -6,7 +6,9 @@ if(WIN32)
BUILD_IN_SOURCE 1
CONFIGURE_COMMAND ""
BUILD_COMMAND ""
INSTALL_COMMAND ${CMAKE_COMMAND} -E copy_directory . ${CMAKE_INSTALL_PREFIX}
INSTALL_COMMAND ${CMAKE_COMMAND} -E copy_directory lib ${CMAKE_INSTALL_PREFIX}/${NG_INSTALL_DIR_LIB}
COMMAND ${CMAKE_COMMAND} -E copy_directory bin ${CMAKE_INSTALL_PREFIX}/${NG_INSTALL_DIR_BIN}
COMMAND ${CMAKE_COMMAND} -E copy_directory include ${CMAKE_INSTALL_PREFIX}/${NG_INSTALL_DIR_INCLUDE}
LOG_DOWNLOAD 1
)

View File

@ -24,8 +24,8 @@ if(status AND NOT status EQUAL 0)
string(REGEX REPLACE "^netgen(.*)" "\\1" git_version_string "${git_version_string}")
endif()
else()
MESSAGE(WARNING "Could not determine git-version from source code - assuming 6.2.0.0")
set(git_version_string "v6.2.0.0")
MESSAGE(WARNING "Could not determine git-version from source code - assuming 6.2.0-0")
set(git_version_string "v6.2.0-0")
endif()
endif()
string(STRIP ${git_version_string} git_version_string)
@ -106,6 +106,7 @@ file(GENERATE OUTPUT netgen_config.hpp CONTENT
#define NETGEN_USE_CHECK_RANGE $<BOOL:${CHECK_RANGE}>
#define NETGEN_BUILD_STUB_FILES $<BOOL:${BUILD_STUB_FILES}>
#define NETGEN_BUILD_FOR_CONDA $<BOOL:${BUILD_FOR_CONDA}>
#define NETGEN_SHARED_LIBRARY_SUFFIX \"${CMAKE_SHARED_LIBRARY_SUFFIX}\"
#endif // NETGEN_CONFIG_HPP_INCLUDED___
")

@ -1 +1 @@
Subproject commit 80dc998efced8ceb2be59756668a7e90e8bef917
Subproject commit 38bf7b174875c27c1ba98bdf5a9bf13d967f14d4

View File

@ -1,4 +1,4 @@
Checks: '*,-clang-analyzer-alpha.*,-*braces-around-statements,-fuchsia-*,-google-runtime-references,-readability-implicit-bool-conversion,-google-explicit-constructor,-hicpp-explicit-conversions,-google-runtime-int,-llvm-header-guard,-modernize-pass-by-value,-cppcoreguidelines-non-private-member-variables-in-classes,-misc-non-private-member-variables-in-classes,-readability-magic-numbers,-cppcoreguidelines-avoid-magic-numbers'
Checks: '*,-cppcoreguidelines-avoid-non-const-global-variables,-llvmlibc-restrict-system-libc-headers,-clang-analyzer-alpha.*,-*braces-around-statements,-fuchsia-*,-google-runtime-references,-readability-implicit-bool-conversion,-google-explicit-constructor,-hicpp-explicit-conversions,-google-runtime-int,-llvm-header-guard,-modernize-pass-by-value,-cppcoreguidelines-non-private-member-variables-in-classes,-misc-non-private-member-variables-in-classes,-readability-magic-numbers,-cppcoreguidelines-avoid-magic-numbers'
CheckOptions:
- key: cppcoreguidelines-special-member-functions.AllowSoleDefaultDtor
value: 1

View File

@ -12,13 +12,42 @@ add_library(ngcore ${NGCORE_LIBRARY_TYPE}
taskmanager.cpp
utils.cpp
version.cpp
ng_mpi_wrapper.cpp
)
string(REPLACE "|" ";" ng_compile_flags_replace_sep "${NG_COMPILE_FLAGS}")
target_compile_options(ngcore PUBLIC ${ng_compile_flags_replace_sep})
if (CMAKE_CXX_COMPILER_ID MATCHES "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 9)
target_link_libraries(ngcore PUBLIC stdc++fs)
if(EMSCRIPTEN)
set(PYTHON_MODULE_EXTENSION ".so")
target_link_options(ngcore PUBLIC -sALLOW_MEMORY_GROWTH -sENVIRONMENT=web)
target_compile_options(ngcore PUBLIC -sNO_DISABLE_EXCEPTION_CATCHING)
endif()
if (CMAKE_CXX_COMPILER_ID MATCHES "GNU" AND USE_PYTHON)
# Python packages on Linux are compiled with the old ABI,
# make sure that the same ABI is used in plugins aswell
try_run(
ret_val can_compile
${CMAKE_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/_get_glibcxx_use_cxx11_abi.cpp
RUN_OUTPUT_VARIABLE use_glibcxx_cxx11_abi
)
target_compile_definitions(ngcore PUBLIC -D_GLIBCXX_USE_CXX11_ABI=${use_glibcxx_cxx11_abi})
try_run(
ret_val can_compile
${CMAKE_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/_get_gxx_abi.cpp
RUN_OUTPUT_VARIABLE default_cxx_abi_version
)
if(${can_compile} AND (${ret_val} EQUAL 0))
# Different python modules using pybind11 need to use the same C++ ABI version
# for compatibility
set(cxx_abi_version 17)
if(cxx_abi_version LESS default_cxx_abi_version)
set(cxx_abi_version ${default_cxx_abi_version})
endif()
message(STATUS "GNU C++ ABI version: ${cxx_abi_version}")
target_compile_options(ngcore PUBLIC "-fabi-version=${cxx_abi_version}")
endif()
endif()
if(USE_PYTHON)
@ -27,10 +56,12 @@ if(USE_PYTHON)
endif(USE_PYTHON)
if(WIN32)
target_compile_options(ngcore PUBLIC /bigobj /MP /W1 /wd4068)
target_compile_options(ngcore PUBLIC /bigobj $<BUILD_INTERFACE:/MP;/W1;/wd4068>)
get_WIN32_WINNT(ver)
target_compile_definitions(ngcore PUBLIC _WIN32_WINNT=${ver} WNT WNT_WINDOW NOMINMAX MSVC_EXPRESS _CRT_SECURE_NO_WARNINGS HAVE_STRUCT_TIMESPEC WIN32)
target_link_options(ngcore PUBLIC /ignore:4273 /ignore:4217 /ignore:4049)
else(WIN32)
target_link_libraries(ngcore PUBLIC dl)
endif(WIN32)
target_compile_definitions(ngcore PRIVATE NGCORE_EXPORTS)
@ -48,19 +79,6 @@ if(TRACE_MEMORY)
target_compile_definitions(ngcore PUBLIC NETGEN_TRACE_MEMORY)
endif(TRACE_MEMORY)
if(USE_SPDLOG)
include_directories(${SPDLOG_INCLUDE_DIR})
install(DIRECTORY ${SPDLOG_INCLUDE_DIR}
DESTINATION ${NG_INSTALL_DIR_INCLUDE}
)
add_dependencies(ngcore project_spdlog)
target_compile_definitions(ngcore PUBLIC NETGEN_USE_SPDLOG)
if(DEBUG_LOG)
target_compile_definitions(ngcore PUBLIC NETGEN_LOG_DEBUG)
endif(DEBUG_LOG)
endif(USE_SPDLOG)
if(USE_NUMA)
find_library(NUMA_LIBRARY libnuma.so)
target_compile_definitions(ngcore PUBLIC USE_NUMA)
@ -69,14 +87,15 @@ endif(USE_NUMA)
install(TARGETS ngcore DESTINATION ${NG_INSTALL_DIR} COMPONENT netgen)
target_link_libraries(ngcore PUBLIC netgen_mpi PRIVATE "$<BUILD_INTERFACE:netgen_python>" ${CMAKE_THREAD_LIBS_INIT})
target_link_libraries(ngcore PRIVATE "$<BUILD_INTERFACE:netgen_python>" ${CMAKE_THREAD_LIBS_INIT})
install(FILES ngcore.hpp archive.hpp type_traits.hpp version.hpp ngcore_api.hpp logging.hpp memtracer.hpp
exception.hpp symboltable.hpp paje_trace.hpp utils.hpp profiler.hpp mpi_wrapper.hpp
array.hpp taskmanager.hpp concurrentqueue.h localheap.hpp python_ngcore.hpp flags.hpp
xbool.hpp signal.hpp bitarray.hpp table.hpp hashtable.hpp ranges.hpp ngstream.hpp
simd.hpp simd_avx.hpp simd_avx512.hpp simd_generic.hpp simd_sse.hpp simd_arm64.hpp
register_archive.hpp
register_archive.hpp autodiff.hpp autodiffdiff.hpp
ng_mpi.hpp ng_mpi_generated_declarations.hpp mpi4py_pycapi.h ng_mpi_native.hpp
DESTINATION ${NG_INSTALL_DIR_INCLUDE}/core COMPONENT netgen_devel)
if(ENABLE_CPP_CORE_GUIDELINES_CHECK)
@ -86,9 +105,71 @@ endif(ENABLE_CPP_CORE_GUIDELINES_CHECK)
add_dependencies(ngcore ng_generate_version_file)
if(USE_PYTHON)
pybind11_add_module(pyngcore SHARED python_ngcore_export.cpp)
target_link_libraries(pyngcore PUBLIC ngcore netgen_python)
pybind11_add_module(pyngcore MODULE python_ngcore_export.cpp)
target_link_libraries(pyngcore PUBLIC ngcore PRIVATE netgen_python)
set_target_properties(pyngcore PROPERTIES INSTALL_RPATH "${NG_RPATH_TOKEN}/../${NETGEN_PYTHON_RPATH}")
if(EMSCRIPTEN)
target_compile_definitions(pyngcore PRIVATE NGCORE_EXPORTS)
endif(EMSCRIPTEN)
install(TARGETS pyngcore DESTINATION ${NG_INSTALL_DIR_PYTHON}/pyngcore COMPONENT netgen)
endif(USE_PYTHON)
function (build_mpi_variant)
set(target ng_${ARGV0})
set(include_dir ${ARGV1})
message("1Building MPI variant: ${ARGV0} ${ARGV1}")
add_library(${target} SHARED ng_mpi.cpp)
target_link_libraries(${target} PUBLIC ngcore PRIVATE netgen_python)
target_compile_definitions(${target} PUBLIC PARALLEL NG_MPI_WRAPPER)
target_include_directories(${target} PRIVATE ${include_dir})
set_target_properties(${target} PROPERTIES PREFIX "")
install(TARGETS ${target} RUNTIME DESTINATION ${NG_INSTALL_DIR_BIN} LIBRARY DESTINATION ${NG_INSTALL_DIR_LIB} COMPONENT netgen)
endfunction()
if(USE_MPI)
target_compile_definitions(ngcore PUBLIC PARALLEL)
message(STATUS "Found MPI version\n${MPI_C_LIBRARY_VERSION_STRING}")
if(USE_MPI_WRAPPER)
target_compile_definitions(ngcore PUBLIC NG_MPI_WRAPPER)
if(MPI_C_LIBRARY_VERSION_STRING MATCHES "Microsoft MPI.*")
set(MICROSOFT_MPI_INCLUDE_DIR ${MPI_C_HEADER_DIR})
set(MICROSOFT_MPI_LIBRARY ${MPI_msmpi_LIBRARY})
endif()
if(MPI_C_LIBRARY_VERSION_STRING MATCHES "Open MPI.*")
set(OPENMPI_INCLUDE_DIR ${MPI_C_INCLUDE_PATH})
endif()
if(MPI_C_LIBRARY_VERSION_STRING MATCHES "MPICH.*")
set(MPICH_INCLUDE_DIR ${MPI_C_INCLUDE_PATH})
endif()
if(MPI_C_LIBRARY_VERSION_STRING MATCHES "Intel.*")
set(INTEL_MPI_INCLUDE_DIR ${MPI_C_INCLUDE_PATH})
endif()
if(OPENMPI_INCLUDE_DIR)
build_mpi_variant(openmpi ${OPENMPI_INCLUDE_DIR})
endif()
if(MPICH_INCLUDE_DIR)
build_mpi_variant(mpich ${MPICH_INCLUDE_DIR})
endif()
if(INTEL_MPI_INCLUDE_DIR)
build_mpi_variant(intel_mpi ${INTEL_MPI_INCLUDE_DIR})
if(WIN32)
target_link_libraries(ng_intel_mpi PUBLIC ${INTEL_MPI_LIBRARY})
endif()
endif()
if(MICROSOFT_MPI_INCLUDE_DIR)
build_mpi_variant(microsoft_mpi ${MICROSOFT_MPI_INCLUDE_DIR})
target_link_libraries(ng_microsoft_mpi PUBLIC ${MICROSOFT_MPI_LIBRARY})
endif()
else()
target_link_libraries(ngcore PUBLIC ${MPI_C_LIBRARIES})
target_include_directories(ngcore PUBLIC ${MPI_C_INCLUDE_PATH})
endif(USE_MPI_WRAPPER)
endif(USE_MPI)

View File

@ -0,0 +1,13 @@
#include <iostream>
int main() {
#ifdef _GLIBCXX_USE_CXX11_ABI
if(_GLIBCXX_USE_CXX11_ABI)
std::cout << 1;
else
std::cout << 0;
#else // _GLIBCXX_USE_CXX11_ABI
std::cout << 0;
#endif // _GLIBCXX_USE_CXX11_ABI
return 0;
}

View File

@ -0,0 +1,7 @@
#include <iostream>
int main() {
if (__GXX_ABI_VERSION >= 2000 || __GXX_ABI_VERSION < 1000) return 1;
std::cout << (__GXX_ABI_VERSION % 100);
return 0;
}

View File

@ -10,24 +10,31 @@
namespace ngcore
{
// clang-tidy should ignore this static object
static std::unique_ptr<std::map<std::string, detail::ClassArchiveInfo>> type_register; // NOLINT
// static std::map<std::string, detail::ClassArchiveInfo> type_register; // NOLINT
auto& GetTypeRegister()
{
static std::map<std::string, detail::ClassArchiveInfo> type_register;
return type_register;
}
const detail::ClassArchiveInfo& Archive :: GetArchiveRegister(const std::string& classname)
{
if(type_register == nullptr) type_register =
std::make_unique<std::map<std::string, detail::ClassArchiveInfo>>();
return (*type_register)[classname];
// if(type_register == nullptr) type_register =
// std::make_unique<std::map<std::string, detail::ClassArchiveInfo>>();
return GetTypeRegister()[classname];
}
void Archive :: SetArchiveRegister(const std::string& classname, const detail::ClassArchiveInfo& info)
{
if(type_register == nullptr) type_register =
std::make_unique<std::map<std::string, detail::ClassArchiveInfo>>();
(*type_register)[classname] = info;
// if(type_register == nullptr) type_register =
// std::make_unique<std::map<std::string, detail::ClassArchiveInfo>>();
GetTypeRegister()[classname] = info;
}
bool Archive :: IsRegistered(const std::string& classname)
{
if(type_register == nullptr) type_register =
std::make_unique<std::map<std::string, detail::ClassArchiveInfo>>();
return type_register->count(classname) != 0;
// if(type_register == nullptr) type_register =
// std::make_unique<std::map<std::string, detail::ClassArchiveInfo>>();
return GetTypeRegister().count(classname) != 0;
}
#ifdef NETGEN_PYTHON

View File

@ -1,6 +1,7 @@
#ifndef NETGEN_CORE_ARCHIVE_HPP
#define NETGEN_CORE_ARCHIVE_HPP
#include <algorithm>
#include <any>
#include <array> // for array
#include <complex> // for complex
@ -14,12 +15,12 @@
#include <string> // for string
#include <type_traits> // for declval, enable_if_t, false_type, is_co...
#include <cstddef> // for std::byte
#include <set> // for set
#include <typeinfo> // for type_info
#include <utility> // for move, swap, pair
#include <vector> // for vector
#include "exception.hpp" // for UnreachableCodeException, Exception
#include "logging.hpp" // for logger
#include "ngcore_api.hpp" // for NGCORE_API
#include "type_traits.hpp" // for all_of_tmpl
#include "utils.hpp" // for Demangle, unlikely
@ -34,7 +35,40 @@ namespace pybind11
namespace ngcore
{
template <typename T>
struct Shallow {
T val;
Shallow() = default;
Shallow(T aval) : val(aval) { ; }
operator T&() { return val; }
};
// Helper to detect shared_from_this
template <typename T>
class has_shared_from_this2
{
private:
// typedef T* T_ptr;
template <typename C> static std::true_type test(decltype(((C*)nullptr)->shared_from_this()));
template <typename C> static std::false_type test(...);
public:
// If the test returns true_type, then T has shared_from_this
static constexpr bool value = decltype(test<T>(0))::value;
};
template <typename T, typename = void>
class has_shallow_archive : public std::false_type {};
template <typename T>
class has_shallow_archive<T, std::void_t<decltype(T::shallow_archive)>>
: public std::is_same<decltype(T::shallow_archive), std::true_type> {};
#ifdef NETGEN_PYTHON
pybind11::object CastAnyToPy(const std::any& a);
#endif // NETGEN_PYTHON
@ -42,16 +76,36 @@ namespace ngcore
class NGCORE_API Archive;
namespace detail
{
template <class T, class Tuple, size_t... Is>
T* construct_from_tuple(Tuple&& tuple, std::index_sequence<Is...> ) {
// return new T{std::get<Is>(std::forward<Tuple>(tuple))...};
return new T{std::get<Is>(std::move(tuple))...};
}
template <class T, class Tuple>
T* construct_from_tuple(Tuple&& tuple) {
return construct_from_tuple<T>(std::forward<Tuple>(tuple),
std::make_index_sequence<std::tuple_size<std::decay_t<Tuple>>::value>{}
);
}
// create new pointer of type T if it is default constructible, else throw
template<typename T, typename ...Rest>
T* constructIfPossible_impl(Rest... /*unused*/)
{ throw Exception(std::string(Demangle(typeid(T).name())) + " is not default constructible!"); }
template<typename T, typename... TArgs>
T* constructIfPossible(std::tuple<TArgs...> args)
{
if constexpr(std::is_constructible_v<T, TArgs...>)
return construct_from_tuple<T>(args);
throw Exception(std::string(Demangle(typeid(T).name())) +
" is not constructible!");
}
template<typename T, typename= std::enable_if_t<std::is_constructible<T>::value>>
T* constructIfPossible_impl(int /*unused*/) { return new T; } // NOLINT
template<typename T>
T* constructIfPossible() { return constructIfPossible_impl<T>(int{}); }
template <typename T> T *constructIfPossible()
{
if constexpr(std::is_constructible_v<T>)
return new T();
throw Exception(std::string(Demangle(typeid(T).name())) +
" is not default constructible!");
}
//Type trait to check if a class implements a 'void DoArchive(Archive&)' function
template<typename T>
@ -83,20 +137,53 @@ namespace ngcore
NGCORE_API static constexpr bool value = type::value;
};
template <typename T>
struct has_GetCArgs
{
template <typename C> static std::true_type check( decltype( sizeof(&C::GetCArgs )) ) { return std::true_type(); }
template <typename> static std::false_type check(...) { return std::false_type(); }
typedef decltype( check<T>(sizeof(char)) ) type;
static constexpr type value = type();
};
template<typename T>
constexpr bool has_GetCArgs_v = has_GetCArgs<T>::value;
template<typename T,
typename std::enable_if<!has_GetCArgs_v<T>>::type* = nullptr>
std::tuple<> GetCArgs(T&val) { return {}; }
template<typename T,
typename std::enable_if<has_GetCArgs_v<T>>::type* = nullptr>
auto GetCArgs(T&val) {
return val.GetCArgs();
}
template<typename T>
using TCargs = decltype(GetCArgs<T>(*static_cast<T*>(nullptr)));
struct ClassArchiveInfo
{
// create new object of this type and return a void* pointer that is points to the location
// of the (base)class given by type_info
std::function<void*(const std::type_info&)> creator;
// std::function<void*(const std::type_info&)> creator;
void* (*creator)(const std::type_info&, Archive&);
// This caster takes a void* pointer to the type stored in this info and casts it to a
// void* pointer pointing to the (base)class type_info
std::function<void*(const std::type_info&, void*)> upcaster;
// std::function<void*(const std::type_info&, void*)> upcaster;
void* (*upcaster) (const std::type_info&, void*);
// This caster takes a void* pointer to the (base)class type_info and returns void* pointing
// to the type stored in this info
std::function<void*(const std::type_info&, void*)> downcaster;
// std::function<void*(const std::type_info&, void*)> downcaster;
void* (*downcaster)(const std::type_info&, void*);
// Archive constructor arguments
// std::function<void(Archive&, void*)> cargs_archiver;
void (*cargs_archiver)(Archive&, void*);
#ifdef NETGEN_PYTHON
std::function<pybind11::object(const std::any&)> anyToPyCaster;
// std::function<pybind11::object(const std::any&)> anyToPyCaster;
pybind11::object (*anyToPyCaster)(const std::any&);
#endif // NETGEN_PYTHON
};
} // namespace detail
@ -129,7 +216,6 @@ namespace ngcore
protected:
bool shallow_to_python = false;
std::map<std::string, VersionInfo> version_map = GetLibraryVersions();
std::shared_ptr<Logger> logger = GetLogger("Archive");
public:
template<typename T>
static constexpr bool is_archivable = detail::is_Archivable_struct<T>::value;
@ -250,7 +336,6 @@ namespace ngcore
// don't use it that often anyway)
Archive& operator& (std::vector<bool>& v)
{
logger->debug("In special archive for std::vector<bool>");
size_t size;
if(Output())
size = v.size();
@ -313,6 +398,26 @@ namespace ngcore
}
return (*this);
}
template <typename T>
Archive& operator&(std::set<T> &s)
{
auto size = s.size();
(*this) & size;
if(Output())
for(const auto & val : s)
(*this) << val;
else
{
for(size_t i=0; i<size; i++)
{
T val;
(*this) & val;
s.insert(val);
}
}
return *this;
}
// Archive arrays =====================================================
// this functions can be overloaded in Archive implementations for more efficiency
template <typename T, typename = std::enable_if_t<is_archivable<T>>>
@ -397,30 +502,36 @@ namespace ngcore
template <typename T>
Archive& operator & (ngcore::Shallow<T>& shallow)
{
this->Shallow(shallow.val);
return *this;
}
// Archive shared_ptrs =================================================
template <typename T>
Archive& operator & (std::shared_ptr<T>& ptr)
{
if constexpr(has_shallow_archive<T>::value)
if (shallow_to_python)
{
Shallow (ptr);
return *this;
}
if(Output())
{
logger->debug("Store shared ptr of type {}", Demangle(typeid(T).name()));
// save -2 for nullptr
if(!ptr)
{
logger->debug("Storing nullptr");
return (*this) << -2;
}
return (*this) << -2;
void* reg_ptr = ptr.get();
bool neededDowncast = false;
// Downcasting is only possible for our registered classes
if(typeid(T) != typeid(*ptr))
{
logger->debug("Typids are different: {} vs {}",
Demangle(typeid(T).name()),
Demangle(typeid(*ptr).name()));
if(!IsRegistered(Demangle(typeid(*ptr).name())))
throw Exception(std::string("Archive error: Polymorphic type ")
+ Demangle(typeid(*ptr).name())
@ -428,17 +539,12 @@ namespace ngcore
reg_ptr = GetArchiveRegister(Demangle(typeid(*ptr).name())).downcaster(typeid(T), ptr.get());
// if there was a true downcast we have to store more information
if(reg_ptr != static_cast<void*>(ptr.get()))
{
logger->debug("Multiple/Virtual inheritance involved, need to cast pointer");
neededDowncast = true;
}
neededDowncast = true;
}
auto pos = shared_ptr2nr.find(reg_ptr);
// if not found store -1 and the pointer
if(pos == shared_ptr2nr.end())
{
logger->debug("Didn't find the shared_ptr, create new registry entry at {}",
shared_ptr_count);
auto p = ptr.get();
(*this) << -1;
(*this) & neededDowncast & p;
@ -449,27 +555,23 @@ namespace ngcore
return *this;
}
// if found store the position and if it has to be downcasted and how
logger->debug("Found shared_ptr at position {}", pos->second);
(*this) << pos->second << neededDowncast;
if(neededDowncast)
(*this) << Demangle(typeid(*ptr).name());
}
else // Input
{
logger->debug("Reading shared_ptr of type {}", Demangle(typeid(T).name()));
int nr;
(*this) & nr;
// -2 restores a nullptr
if(nr == -2)
{
logger->debug("Reading a nullptr");
ptr = nullptr;
return *this;
}
// -1 restores a new shared ptr by restoring the inner pointer and creating a shared_ptr to it
if (nr == -1)
{
logger->debug("Creating new shared_ptr");
T* p = nullptr;
bool neededDowncast;
(*this) & neededDowncast & p;
@ -477,7 +579,6 @@ namespace ngcore
// if we did downcast we need to store a shared_ptr<void> to the true object
if(neededDowncast)
{
logger->debug("Shared pointer needed downcasting");
std::string name;
(*this) & name;
auto info = GetArchiveRegister(name);
@ -488,20 +589,15 @@ namespace ngcore
ptr.get())));
}
else
{
logger->debug("Shared pointer didn't need downcasting");
nr2shared_ptr.push_back(ptr);
}
}
else
{
logger->debug("Reading already existing pointer at entry {}", nr);
auto other = nr2shared_ptr[nr];
bool neededDowncast;
(*this) & neededDowncast;
if(neededDowncast)
{
logger->debug("Shared pointer needed pointer downcast");
// if there was a downcast we can expect the class to be registered (since archiving
// wouldn't have worked else)
std::string name;
@ -515,7 +611,6 @@ namespace ngcore
}
else
{
logger->debug("Shared pointer didn't need pointer casts");
ptr = std::static_pointer_cast<T>(other);
}
}
@ -529,45 +624,39 @@ namespace ngcore
{
if (Output())
{
logger->debug("Store pointer of type {}",Demangle(typeid(T).name()));
// if the pointer is null store -2
if (!p)
{
logger->debug("Storing nullptr");
return (*this) << -2;
}
auto reg_ptr = static_cast<void*>(p);
if(typeid(T) != typeid(*p))
{
logger->debug("Typeids are different: {} vs {}",
Demangle(typeid(T).name()),
Demangle(typeid(*p).name()));
if(!IsRegistered(Demangle(typeid(*p).name())))
throw Exception(std::string("Archive error: Polymorphic type ")
+ Demangle(typeid(*p).name())
+ " not registered for archive");
reg_ptr = GetArchiveRegister(Demangle(typeid(*p).name())).downcaster(typeid(T), static_cast<void*>(p));
if(reg_ptr != static_cast<void*>(p))
{
logger->debug("Multiple/Virtual inheritance involved, need to cast pointer");
}
}
auto pos = ptr2nr.find(reg_ptr);
// if the pointer is not found in the map create a new entry
if (pos == ptr2nr.end())
{
logger->debug("Didn't find pointer, create new registry entry at {}",
ptr_count);
ptr2nr[reg_ptr] = ptr_count++;
if(typeid(*p) == typeid(T))
if (std::is_constructible<T>::value)
{
logger->debug("Store standard class pointer (no virt. inh,...)");
return (*this) << -1 & (*p);
}
return (*this) << -1 & (*p);
else
throw Exception(std::string("Archive error: Class ") +
Demangle(typeid(*p).name()) + " does not provide a default constructor!");
{
if (IsRegistered(Demangle(typeid(*p).name())))
{
(*this) << -3 << Demangle(typeid(*p).name());
GetArchiveRegister(Demangle(typeid(*p).name())).
cargs_archiver(*this, p);
return (*this) & (*p);
}
else
throw Exception(std::string("Archive error: Class ") +
Demangle(typeid(*p).name()) + " does not provide a default constructor!");
}
else
{
// if a pointer to a base class is archived, the class hierarchy must be registered
@ -578,49 +667,41 @@ namespace ngcore
throw Exception(std::string("Archive error: Polymorphic type ")
+ Demangle(typeid(*p).name())
+ " not registered for archive");
logger->debug("Store a possibly more complicated pointer");
return (*this) << -3 << Demangle(typeid(*p).name()) & (*p);
(*this) << -3 << Demangle(typeid(*p).name());
GetArchiveRegister(Demangle(typeid(*p).name())).
cargs_archiver(*this, p);
return (*this) & (*p);
}
}
else
{
(*this) & pos->second;
bool downcasted = !(reg_ptr == static_cast<void*>(p) );
logger->debug("Store a the existing position in registry at {}", pos->second);
logger->debug("Pointer {} downcasting", downcasted ? "needs" : "doesn't need");
// store if the class has been downcasted and the name
(*this) << downcasted << Demangle(typeid(*p).name());
}
}
else
{
logger->debug("Reading pointer of type {}", Demangle(typeid(T).name()));
int nr;
(*this) & nr;
if (nr == -2) // restore a nullptr
{
logger->debug("Loading a nullptr");
p = nullptr;
}
else if (nr == -1) // create a new pointer of standard type (no virtual or multiple inheritance,...)
{
logger->debug("Load a new pointer to a simple class");
p = detail::constructIfPossible<T>();
nr2ptr.push_back(p);
(*this) & *p;
}
else if(nr == -3) // restore one of our registered classes that can have multiple inheritance,...
{
logger->debug("Load a new pointer to a potentially more complicated class "
"(allows for multiple/virtual inheritance,...)");
// As stated above, we want this special behaviour only for our classes that implement DoArchive
std::string name;
(*this) & name;
logger->debug("Name = {}", name);
auto info = GetArchiveRegister(name);
// the creator creates a new object of type name, and returns a void* pointing
// to T (which may have an offset)
p = static_cast<T*>(info.creator(typeid(T)));
p = static_cast<T*>(info.creator(typeid(T), *this));
// we store the downcasted pointer (to be able to find it again from
// another class in a multiple inheritance tree)
nr2ptr.push_back(info.downcaster(typeid(T),p));
@ -628,11 +709,9 @@ namespace ngcore
}
else
{
logger->debug("Restoring pointer to already existing object at registry position {}", nr);
bool downcasted;
std::string name;
(*this) & downcasted & name;
logger->debug("{} object of type {}", downcasted ? "Downcasted" : "Not downcasted", name);
if(downcasted)
{
// if the class has been downcasted we can assume it is in the register
@ -646,6 +725,16 @@ namespace ngcore
return *this;
}
Archive& operator&(std::tuple<>&) { return *this; }
template <typename... T>
Archive& operator&(std::tuple<T...> &t)
{
// call operator& for each element of the tuple
std::apply([this](auto&... arg) { std::make_tuple(((*this) & arg).IsParallel()...);}, t);
return *this;
}
// const ptr
template<typename T>
Archive& operator &(const T*& t)
@ -669,7 +758,7 @@ namespace ngcore
void SetParallel (bool _parallel) { parallel = _parallel; }
private:
template<typename T, typename ... Bases>
template<typename T, typename Bases>
friend class RegisterClassForArchive;
#ifdef NETGEN_PYTHON
@ -688,7 +777,7 @@ namespace ngcore
struct Caster{};
template<typename T>
struct Caster<T>
struct Caster<T, std::tuple<>>
{
static void* tryUpcast (const std::type_info& /*unused*/, T* /*unused*/)
{
@ -700,8 +789,37 @@ namespace ngcore
}
};
template<typename T, typename B1>
struct Caster<T,B1>
{
static void* tryUpcast(const std::type_info& ti, T* p)
{
try {
return GetArchiveRegister(Demangle(typeid(B1).name()))
.upcaster(ti, static_cast<void *>(dynamic_cast<B1 *>(p)));
} catch (const Exception &) {
throw Exception("Upcast not successful, some classes are not "
"registered properly for archiving!");
}
}
static void* tryDowncast(const std::type_info& ti, void* p)
{
if(typeid(B1) == ti)
return dynamic_cast<T*>(static_cast<B1*>(p));
try
{
return dynamic_cast<T*>(static_cast<B1*>(GetArchiveRegister(Demangle(typeid(B1).name())).
downcaster(ti, p)));
} catch (const Exception &) {
throw Exception("Downcast not successful, some classes are not "
"registered properly for archiving!");
}
}
};
template<typename T, typename B1, typename ... Brest>
struct Caster<T,B1,Brest...>
struct Caster<T,std::tuple<B1, Brest...>>
{
static void* tryUpcast(const std::type_info& ti, T* p)
{
@ -709,7 +827,7 @@ namespace ngcore
{ return GetArchiveRegister(Demangle(typeid(B1).name())).
upcaster(ti, static_cast<void*>(dynamic_cast<B1*>(p))); }
catch(const Exception&)
{ return Caster<T, Brest...>::tryUpcast(ti, p); }
{ return Caster<T, std::tuple<Brest...>>::tryUpcast(ti, p); }
}
static void* tryDowncast(const std::type_info& ti, void* p)
@ -723,7 +841,7 @@ namespace ngcore
}
catch(const Exception&)
{
return Caster<T, Brest...>::tryDowncast(ti, p);
return Caster<T, std::tuple<Brest...>>::tryDowncast(ti, p);
}
}
};
@ -765,11 +883,19 @@ namespace ngcore
Archive & operator & (long & i) override
{
// for platform independence
int64_t tmp = i;
return Write(tmp);
if constexpr (sizeof(long) == 8)
return Write(i);
else
return Write(static_cast<int64_t>(i));
}
Archive & operator & (size_t & i) override
{ return Write(i); }
{
// for platform independence
if constexpr (sizeof(size_t) == 8)
return Write(i);
else
return Write(static_cast<uint64_t>(i));
}
Archive & operator & (unsigned char & i) override
{ return Write(i); }
Archive & operator & (bool & b) override
@ -848,13 +974,30 @@ namespace ngcore
{ Read(i); return *this; }
Archive & operator & (long & i) override
{
int64_t tmp;
Read(tmp);
i = tmp;
// for platform independence
if constexpr (sizeof(long) == 8)
Read(i);
else
{
int64_t tmp = 0;
Read(tmp);
i = tmp;
}
return *this;
}
Archive & operator & (size_t & i) override
{ Read(i); return *this; }
{
// for platform independence
if constexpr (sizeof(long) == 8)
Read(i);
else
{
uint64_t tmp = 0;
Read(tmp);
i = tmp;
}
return *this;
}
Archive & operator & (unsigned char & i) override
{ Read(i); return *this; }
Archive & operator & (bool & b) override
@ -890,7 +1033,15 @@ namespace ngcore
Archive & Do (int * i, size_t n) override
{ stream->read(reinterpret_cast<char*>(i), n*sizeof(int)); return *this; } // NOLINT
Archive & Do (size_t * i, size_t n) override
{ stream->read(reinterpret_cast<char*>(i), n*sizeof(size_t)); return *this; } // NOLINT
{
// for platform independence
if constexpr (sizeof(long) == 8)
stream->read(reinterpret_cast<char*>(i), n*sizeof(size_t)); // NOLINT
else
for(size_t j = 0; j < n; j++)
(*this) & i[j];
return *this;
}
private:
template<typename T>
@ -912,7 +1063,7 @@ namespace ngcore
using Archive::operator&;
Archive & operator & (std::byte & d) override
{ *stream << std::hex << int(d) << ' '; return *this; }
{ *stream << int(d) << ' '; return *this; }
Archive & operator & (float & f) override
{ *stream << f << '\n'; return *this; }
Archive & operator & (double & d) override
@ -967,7 +1118,7 @@ namespace ngcore
using Archive::operator&;
Archive & operator & (std::byte & d) override
{ int tmp; *stream >> std::hex >> tmp; d = std::byte(tmp); return *this; }
{ int tmp; *stream >> tmp; d = std::byte(tmp); return *this; }
Archive & operator & (float & f) override
{ *stream >> f; return *this; }
Archive & operator & (double & d) override
@ -986,15 +1137,32 @@ namespace ngcore
{ char c; *stream >> c; b = (c=='t'); return *this; }
Archive & operator & (std::string & str) override
{
// Ignore \r (carriage return) characters when reading strings
// this is necessary for instance when a file was written on Windows and is read on Unix
int len;
*stream >> len;
char ch;
stream->get(ch); // '\n'
stream->get(ch); // read newline character
if(ch == '\r') // windows line endings -> read \n as well
stream->get(ch);
str.resize(len);
if(len)
stream->get(&str[0], len+1, '\0');
// remove all \r characters from the string, check if size changed
// if so, read the remaining characters
str.erase(std::remove(str.begin(), str.end(), '\r'), str.cend());
size_t chars_to_read = len-str.size();
while (chars_to_read>0)
{
auto old_size = str.size();
str.resize(len);
stream->get(&str[old_size], chars_to_read+1, '\0');
str.erase(std::remove(str.begin()+old_size, str.end(), '\r'), str.cend());
chars_to_read = len - str.size();
}
return *this;
}
Archive & operator & (char *& str) override

View File

@ -216,6 +216,10 @@ namespace ngcore
template <typename T>
constexpr T IndexBASE () { return T(0); }
template <typename T>
constexpr T IndexBASE (T ind) { return IndexBASE<T>(); }
class IndexFromEnd
{
@ -278,7 +282,8 @@ namespace ngcore
T first, next;
public:
NETGEN_INLINE T_Range () { ; }
NETGEN_INLINE T_Range (T n) : first(0), next(n) {;}
// NETGEN_INLINE T_Range (T n) : first(0), next(n) {;}
NETGEN_INLINE explicit T_Range (size_t n) : first(IndexBASE<T>()), next(IndexBASE<T>()+n) {;}
NETGEN_INLINE T_Range (T f, T n) : first(f), next(n) {;}
template <typename T2>
NETGEN_INLINE T_Range(T_Range<T2> r2) : first(r2.First()), next(r2.Next()) { ; }
@ -296,7 +301,7 @@ namespace ngcore
NETGEN_INLINE T_Range Split (size_t nr, int tot) const
{
T diff = next-first;
auto diff = next-first;
return T_Range (first + nr * diff / tot,
first + (nr+1) * diff / tot);
}
@ -554,6 +559,13 @@ namespace ngcore
// { return CArray<T> (data+pos); }
NETGEN_INLINE T * operator+ (size_t pos) const { return data+pos; }
/// access first element. check by macro NETGEN_CHECK_RANGE
T & First () const
{
NETGEN_CHECK_RANGE(0,0,size);
return data[0];
}
/// access last element. check by macro NETGEN_CHECK_RANGE
T & Last () const
{
@ -687,6 +699,7 @@ namespace ngcore
size_t allocsize;
/// that's the data we have to delete, nullptr for not owning the memory
T * mem_to_delete;
MemoryTracer mt;
using FlatArray<T,IndexType>::size;
@ -708,6 +721,7 @@ namespace ngcore
{
allocsize = asize;
mem_to_delete = data;
mt.Alloc(sizeof(T)*asize);
}
@ -717,7 +731,10 @@ namespace ngcore
{
allocsize = asize;
if(ownMemory)
{
mem_to_delete = adata;
mt.Alloc(sizeof(T)*asize);
}
else
mem_to_delete = nullptr;
}
@ -733,8 +750,7 @@ namespace ngcore
NETGEN_INLINE Array (Array && a2)
{
mt.Swap(sizeof(T) * allocsize, a2.mt, sizeof(T) * a2.allocsize);
mt = std::move(a2.mt);
size = a2.size;
data = a2.data;
allocsize = a2.allocsize;
@ -753,6 +769,7 @@ namespace ngcore
{
allocsize = size;
mem_to_delete = data;
mt.Alloc(sizeof(T)*size);
for (size_t i = 0; i < size; i++)
data[i] = a2.data[i];
}
@ -772,6 +789,7 @@ namespace ngcore
{
allocsize = size;
mem_to_delete = data;
mt.Alloc(sizeof(T)*size);
/*
for (size_t i = 0; i < size; i++)
data[i] = a2[i];
@ -788,6 +806,7 @@ namespace ngcore
{
allocsize = size;
mem_to_delete = data;
mt.Alloc(sizeof(T)*size);
size_t cnt = 0;
for (auto val : list)
data[cnt++] = val;
@ -800,6 +819,7 @@ namespace ngcore
{
allocsize = size;
mem_to_delete = data;
mt.Alloc(sizeof(T)*size);
for(size_t i = 0; i < a2.Size(); i++)
data[i] = a2[i];
for (size_t i = a2.Size(), j=0; i < size; i++,j++)
@ -834,6 +854,9 @@ namespace ngcore
NETGEN_INLINE void NothingToDelete ()
{
mem_to_delete = nullptr;
// this memory is not managed by the Array anymore, so set the memory usage to 0
mt.Free(sizeof(T)*allocsize);
}
/// Change logical size. If necessary, do reallocation. Keeps contents.
@ -947,7 +970,7 @@ namespace ngcore
/// Delete element i. Move last element to position i.
NETGEN_INLINE void DeleteElement (size_t i)
NETGEN_INLINE void DeleteElement (IndexType i)
{
NETGEN_CHECK_RANGE(i,BASE,BASE+size);
data[i-BASE] = std::move(data[size-1]);
@ -956,10 +979,10 @@ namespace ngcore
/// Delete element i. Move all remaining elements forward
NETGEN_INLINE void RemoveElement (size_t i)
NETGEN_INLINE void RemoveElement (IndexType i)
{
NETGEN_CHECK_RANGE(i, BASE, BASE+size);
for(size_t j = i; j < this->size-1; j++)
for(size_t j = i-BASE; j+1 < this->size; j++)
this->data[j] = this->data[j+1];
this->size--;
}
@ -1001,16 +1024,17 @@ namespace ngcore
data[i] = a2.data[i];
return *this;
}
#ifndef __CUDA_ARCH__
else
throw Exception(std::string("cannot copy Array of type ") + typeid(T).name());
#endif
}
/// steal array
NETGEN_INLINE Array & operator= (Array && a2)
{
mt.Swap(sizeof(T)*allocsize, a2.mt, sizeof(T)*a2.allocsize);
mt = std::move(a2.mt);
ngcore::Swap (size, a2.size);
ngcore::Swap (data, a2.data);
ngcore::Swap (allocsize, a2.allocsize);
@ -1084,8 +1108,7 @@ namespace ngcore
NETGEN_INLINE void Swap (Array & b)
{
mt.Swap(sizeof(T) * allocsize, b.mt, sizeof(T) * b.allocsize);
mt = std::move(b.mt);
ngcore::Swap (size, b.size);
ngcore::Swap (data, b.data);
ngcore::Swap (allocsize, b.allocsize);
@ -1094,7 +1117,8 @@ namespace ngcore
NETGEN_INLINE void StartMemoryTracing () const
{
mt.Alloc(sizeof(T) * allocsize);
if(mem_to_delete)
mt.Alloc(sizeof(T) * allocsize);
}
const MemoryTracer& GetMemoryTracer() const { return mt; }
@ -1103,7 +1127,6 @@ namespace ngcore
/// resize array, at least to size minsize. copy contents
NETGEN_INLINE void ReSize (size_t minsize);
MemoryTracer mt;
};
@ -1156,6 +1179,7 @@ namespace ngcore
using Array<T>::allocsize;
using Array<T>::data;
using Array<T>::mem_to_delete;
using Array<T>::mt;
// using Array<T>::ownmem;
public:
@ -1169,6 +1193,7 @@ namespace ngcore
data = new T[asize];
allocsize = size;
mem_to_delete = data;
mt.Alloc(sizeof(T)*asize);
}
}
@ -1189,6 +1214,7 @@ namespace ngcore
ArrayMem(ArrayMem && a2)
: Array<T> (a2.Size(), (T*)mem)
{
mt = std::move(a2.mt);
if (a2.mem_to_delete)
{
mem_to_delete = a2.mem_to_delete;
@ -1231,6 +1257,7 @@ namespace ngcore
ArrayMem & operator= (ArrayMem && a2)
{
mt = std::move(a2.mt);
ngcore::Swap (mem_to_delete, a2.mem_to_delete);
ngcore::Swap (allocsize, a2.allocsize);
ngcore::Swap (size, a2.size);
@ -1526,6 +1553,8 @@ namespace ngcore
}
struct HTAHelp { };
// head-tail array
template <size_t S, typename T>
class HTArray
@ -1533,10 +1562,22 @@ namespace ngcore
HTArray<S-1,T> tail;
T head;
public:
HTArray () = default;
HTArray (const HTArray &) = default;
constexpr HTArray () = default;
constexpr HTArray (const HTArray &) = default;
template <typename T2>
HTArray (const HTArray<S,T2> & a2) : tail(a2.Tail()), head(a2.Head()) { ; }
constexpr HTArray (const HTArray<S,T2> & a2) : tail(a2.Tail()), head(a2.Head()) { ; }
constexpr HTArray (T v) : tail(v), head(v) { } // all the same
template <class... T2,
std::enable_if_t<S==1+sizeof...(T2),bool> = true>
constexpr HTArray (const T &v, T2... rest)
: tail{HTAHelp(), v,rest...}, head(std::get<S-2>(std::tuple(rest...))) { }
template <class... T2>
constexpr HTArray (HTAHelp h, const T &v, T2... rest)
: tail{h, v,rest...}, head(std::get<S-2>(std::tuple(rest...))) { }
HTArray & operator= (const HTArray &) = default;
@ -1557,10 +1598,15 @@ namespace ngcore
{
T head;
public:
HTArray () = default;
HTArray (const HTArray &) = default;
constexpr HTArray () = default;
constexpr HTArray (const HTArray &) = default;
template <typename T2>
HTArray (const HTArray<1,T2> & a2) : head(a2.Head()) { ; }
constexpr HTArray (const HTArray<1,T2> & a2) : head(a2.Head()) { ; }
constexpr HTArray (T v) : head(v) { } // all the same
template <class... T2>
constexpr HTArray (HTAHelp h, const T &v, T2... rest)
: head(v) { }
HTArray & operator= (const HTArray &) = default;
@ -1588,7 +1634,7 @@ namespace ngcore
HTArray (const HTArray &) = default;
template <typename T2>
HTArray (const HTArray<0,T2> & a2) { ; }
constexpr HTArray (T v) { } // all the same
HTArray & operator= (const HTArray &) = default;
/*

1131
libsrc/core/autodiff.hpp Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,733 @@
#ifndef FILE_AUTODIFFDIFF
#define FILE_AUTODIFFDIFF
/**************************************************************************/
/* File: autodiffdiff.hpp */
/* Author: Joachim Schoeberl */
/* Date: 13. June. 05 */
/**************************************************************************/
namespace ngcore
{
using ngcore::IfPos;
// Automatic second differentiation datatype
/**
Datatype for automatic differentiation. Contains function value,
D first derivatives, and D*D second derivatives. Algebraic operations are
overloaded by using product-rule etc. etc.
**/
template <int D, typename SCAL = double>
class AutoDiffDiff
{
SCAL val;
SCAL dval[D?D:1];
SCAL ddval[D?D*D:1];
public:
typedef AutoDiffDiff<D, SCAL> TELEM;
/// elements are undefined
AutoDiffDiff () throw() { ; }
/// copy constructor
AutoDiffDiff (const AutoDiffDiff & ad2) throw()
{
val = ad2.val;
for (int i = 0; i < D; i++)
dval[i] = ad2.dval[i];
for (int i = 0; i < D*D; i++)
ddval[i] = ad2.ddval[i];
}
/// initial object with constant value
AutoDiffDiff (SCAL aval) throw()
{
val = aval;
for (int i = 0; i < D; i++)
dval[i] = 0;
for (int i = 0; i < D*D; i++)
ddval[i] = 0;
}
/// initial object with value and derivative
AutoDiffDiff (const AutoDiff<D, SCAL> & ad2) throw()
{
val = ad2.Value();
for (int i = 0; i < D; i++)
dval[i] = ad2.DValue(i);
for (int i = 0; i < D*D; i++)
ddval[i] = 0;
}
/// init object with (val, e_diffindex)
AutoDiffDiff (SCAL aval, int diffindex) throw()
{
val = aval;
for (int i = 0; i < D; i++)
dval[i] = 0;
for (int i = 0; i < D*D; i++)
ddval[i] = 0;
dval[diffindex] = 1;
}
NETGEN_INLINE AutoDiffDiff (SCAL aval, const SCAL * grad)
{
val = aval;
LoadGradient (grad);
for (int i = 0; i < D*D; i++)
ddval[i] = 0;
}
NETGEN_INLINE AutoDiffDiff (SCAL aval, const SCAL * grad, const SCAL * hesse)
{
val = aval;
LoadGradient (grad);
LoadHessian (hesse);
}
/// assign constant value
AutoDiffDiff & operator= (SCAL aval) throw()
{
val = aval;
for (int i = 0; i < D; i++)
dval[i] = 0;
for (int i = 0; i < D*D; i++)
ddval[i] = 0;
return *this;
}
NETGEN_INLINE void StoreGradient (SCAL * p) const
{
for (int i = 0; i < D; i++)
p[i] = dval[i];
}
NETGEN_INLINE void LoadGradient (const SCAL * p)
{
for (int i = 0; i < D; i++)
dval[i] = p[i];
}
NETGEN_INLINE void StoreHessian (SCAL * p) const
{
for (int i = 0; i < D*D; i++)
p[i] = ddval[i];
}
NETGEN_INLINE void LoadHessian (const SCAL * p)
{
for (int i = 0; i < D*D; i++)
ddval[i] = p[i];
}
/// returns value
SCAL Value() const throw() { return val; }
/// returns partial derivative
SCAL DValue (int i) const throw() { return dval[i]; }
AutoDiff<D,SCAL> DValueAD (int i) const
{
AutoDiff<D,SCAL> r(dval[i]);
for (int j = 0; j < D; j++)
r.DValue(j) = ddval[i*D+j];
return r;
}
/// returns partial derivative
SCAL DDValue (int i) const throw() { return ddval[i]; }
/// returns partial derivative
SCAL DDValue (int i, int j) const throw() { return ddval[i*D+j]; }
/// access value
SCAL & Value() throw() { return val; }
/// accesses partial derivative
SCAL & DValue (int i) throw() { return dval[i]; }
/// accesses partial derivative
SCAL & DDValue (int i) throw() { return ddval[i]; }
/// accesses partial derivative
SCAL & DDValue (int i, int j) throw() { return ddval[i*D+j]; }
explicit operator AutoDiff<D,SCAL> () const
{ return AutoDiff<D,SCAL> (val, &dval[0]); }
/// add autodiffdiff object
AutoDiffDiff<D, SCAL> & operator+= (const AutoDiffDiff<D, SCAL> & y) throw()
{
val += y.val;
for (int i = 0; i < D; i++)
dval[i] += y.dval[i];
for (int i = 0; i < D*D; i++)
ddval[i] += y.ddval[i];
return *this;
}
/// subtract autodiffdiff object
AutoDiffDiff<D, SCAL> & operator-= (const AutoDiffDiff<D, SCAL> & y) throw()
{
val -= y.val;
for (int i = 0; i < D; i++)
dval[i] -= y.dval[i];
for (int i = 0; i < D*D; i++)
ddval[i] -= y.ddval[i];
return *this;
}
/// multiply with autodiffdiff object
AutoDiffDiff<D, SCAL> & operator*= (const AutoDiffDiff<D, SCAL> & y) throw()
{
for (int i = 0; i < D*D; i++)
ddval[i] = val * y.ddval[i] + y.val * ddval[i];
for (int i = 0; i < D; i++)
for (int j = 0; j < D; j++)
ddval[i*D+j] += dval[i] * y.dval[j] + dval[j] * y.dval[i];
for (int i = 0; i < D; i++)
{
dval[i] *= y.val;
dval[i] += val * y.dval[i];
}
val *= y.val;
return *this;
}
/// multiply with scalar
AutoDiffDiff<D, SCAL> & operator*= (const SCAL & y) throw()
{
for ( int i = 0; i < D*D; i++ )
ddval[i] *= y;
for (int i = 0; i < D; i++)
dval[i] *= y;
val *= y;
return *this;
}
/// divide by scalar
AutoDiffDiff<D, SCAL> & operator/= (const SCAL & y) throw()
{
SCAL iy = 1.0 / y;
for ( int i = 0; i < D*D; i++ )
ddval[i] *= iy;
for (int i = 0; i < D; i++)
dval[i] *= iy;
val *= iy;
return *this;
}
/// same value
bool operator== (SCAL val2) throw()
{
return val == val2;
}
/// different values
bool operator!= (SCAL val2) throw()
{
return val != val2;
}
/// less
bool operator< (SCAL val2) throw()
{
return val < val2;
}
/// greater
bool operator> (SCAL val2) throw()
{
return val > val2;
}
};
//@{ AutoDiff helper functions.
/// Prints AudoDiffDiff
template<int D, typename SCAL>
inline ostream & operator<< (ostream & ost, const AutoDiffDiff<D, SCAL> & x)
{
ost << x.Value() << ", D = ";
for (int i = 0; i < D; i++)
ost << x.DValue(i) << " ";
ost << ", DD = ";
for (int i = 0; i < D*D; i++)
ost << x.DDValue(i) << " ";
return ost;
}
///
template<int D, typename SCAL>
inline AutoDiffDiff<D, SCAL> operator+ (const AutoDiffDiff<D, SCAL> & x, const AutoDiffDiff<D, SCAL> & y) throw()
{
AutoDiffDiff<D, SCAL> res;
res.Value () = x.Value()+y.Value();
for (int i = 0; i < D; i++)
res.DValue(i) = x.DValue(i) + y.DValue(i);
for (int i = 0; i < D*D; i++)
res.DDValue(i) = x.DDValue(i) + y.DDValue(i);
return res;
}
///
template<int D, typename SCAL>
inline AutoDiffDiff<D, SCAL> operator- (const AutoDiffDiff<D, SCAL> & x, const AutoDiffDiff<D, SCAL> & y) throw()
{
AutoDiffDiff<D, SCAL> res;
res.Value() = x.Value()-y.Value();
for (int i = 0; i < D; i++)
res.DValue(i) = x.DValue(i) - y.DValue(i);
for (int i = 0; i < D*D; i++)
res.DDValue(i) = x.DDValue(i) - y.DDValue(i);
return res;
}
///
template<int D, typename SCAL, typename SCAL2,
typename std::enable_if<std::is_convertible<SCAL2,SCAL>::value, int>::type = 0>
inline AutoDiffDiff<D, SCAL> operator+ (SCAL2 x, const AutoDiffDiff<D, SCAL> & y) throw()
{
AutoDiffDiff<D, SCAL> res;
res.Value() = x+y.Value();
for (int i = 0; i < D; i++)
res.DValue(i) = y.DValue(i);
for (int i = 0; i < D*D; i++)
res.DDValue(i) = y.DDValue(i);
return res;
}
///
template<int D, typename SCAL, typename SCAL2,
typename std::enable_if<std::is_convertible<SCAL2,SCAL>::value, int>::type = 0>
inline AutoDiffDiff<D, SCAL> operator+ (const AutoDiffDiff<D, SCAL> & y, SCAL2 x) throw()
{
AutoDiffDiff<D, SCAL> res;
res.Value() = x+y.Value();
for (int i = 0; i < D; i++)
res.DValue(i) = y.DValue(i);
for (int i = 0; i < D*D; i++)
res.DDValue(i) = y.DDValue(i);
return res;
}
///
template<int D, typename SCAL>
inline AutoDiffDiff<D, SCAL> operator- (const AutoDiffDiff<D, SCAL> & x) throw()
{
AutoDiffDiff<D, SCAL> res;
res.Value() = -x.Value();
for (int i = 0; i < D; i++)
res.DValue(i) = -x.DValue(i);
for (int i = 0; i < D*D; i++)
res.DDValue(i) = -x.DDValue(i);
return res;
}
///
template<int D, typename SCAL, typename SCAL2,
typename std::enable_if<std::is_convertible<SCAL2,SCAL>::value, int>::type = 0>
inline AutoDiffDiff<D, SCAL> operator- (const AutoDiffDiff<D, SCAL> & x, SCAL2 y) throw()
{
AutoDiffDiff<D, SCAL> res;
res.Value() = x.Value()-y;
for (int i = 0; i < D; i++)
res.DValue(i) = x.DValue(i);
for (int i = 0; i < D*D; i++)
res.DDValue(i) = x.DDValue(i);
return res;
}
///
template<int D, typename SCAL, typename SCAL2,
typename std::enable_if<std::is_convertible<SCAL2,SCAL>::value, int>::type = 0>
inline AutoDiffDiff<D, SCAL> operator- (SCAL2 x, const AutoDiffDiff<D, SCAL> & y) throw()
{
AutoDiffDiff<D, SCAL> res;
res.Value() = x-y.Value();
for (int i = 0; i < D; i++)
res.DValue(i) = -y.DValue(i);
for (int i = 0; i < D*D; i++)
res.DDValue(i) = -y.DDValue(i);
return res;
}
///
template<int D, typename SCAL, typename SCAL2,
typename std::enable_if<std::is_convertible<SCAL2,SCAL>::value, int>::type = 0>
inline AutoDiffDiff<D, SCAL> operator* (SCAL2 x, const AutoDiffDiff<D, SCAL> & y) throw()
{
AutoDiffDiff<D, SCAL> res;
res.Value() = x*y.Value();
for (int i = 0; i < D; i++)
res.DValue(i) = x*y.DValue(i);
for (int i = 0; i < D*D; i++)
res.DDValue(i) = x*y.DDValue(i);
return res;
}
///
template<int D, typename SCAL, typename SCAL2,
typename std::enable_if<std::is_convertible<SCAL2,SCAL>::value, int>::type = 0>
inline AutoDiffDiff<D, SCAL> operator* (const AutoDiffDiff<D, SCAL> & y, SCAL2 x) throw()
{
AutoDiffDiff<D, SCAL> res;
res.Value() = x*y.Value();
for (int i = 0; i < D; i++)
res.DValue(i) = x*y.DValue(i);
for (int i = 0; i < D*D; i++)
res.DDValue(i) = x*y.DDValue(i);
return res;
}
///
template<int D, typename SCAL>
inline AutoDiffDiff<D, SCAL> operator* (const AutoDiffDiff<D, SCAL> & x, const AutoDiffDiff<D, SCAL> & y) throw()
{
AutoDiffDiff<D, SCAL> res;
SCAL hx = x.Value();
SCAL hy = y.Value();
res.Value() = hx*hy;
for (int i = 0; i < D; i++)
res.DValue(i) = hx*y.DValue(i) + hy*x.DValue(i);
for (int i = 0; i < D; i++)
for (int j = 0; j < D; j++)
res.DDValue(i,j) = hx * y.DDValue(i,j) + hy * x.DDValue(i,j)
+ x.DValue(i) * y.DValue(j) + x.DValue(j) * y.DValue(i);
return res;
}
template<int D, typename SCAL>
inline AutoDiffDiff<D, SCAL> Inv (const AutoDiffDiff<D, SCAL> & x)
{
AutoDiffDiff<D, SCAL> res(1.0 / x.Value());
for (int i = 0; i < D; i++)
res.DValue(i) = -x.DValue(i) / (x.Value() * x.Value());
SCAL fac1 = 2/(x.Value()*x.Value()*x.Value());
SCAL fac2 = 1/sqr(x.Value());
for (int i = 0; i < D; i++)
for (int j = 0; j < D; j++)
res.DDValue(i,j) = fac1*x.DValue(i)*x.DValue(j) - fac2*x.DDValue(i,j);
return res;
}
template<int D, typename SCAL>
inline AutoDiffDiff<D, SCAL> operator/ (const AutoDiffDiff<D, SCAL> & x, const AutoDiffDiff<D, SCAL> & y)
{
return x * Inv (y);
}
template<int D, typename SCAL, typename SCAL2,
typename std::enable_if<std::is_convertible<SCAL2,SCAL>::value, int>::type = 0>
inline AutoDiffDiff<D, SCAL> operator/ (const AutoDiffDiff<D, SCAL> & x, SCAL2 y)
{
return (1/y) * x;
}
template<int D, typename SCAL, typename SCAL2,
typename std::enable_if<std::is_convertible<SCAL2,SCAL>::value, int>::type = 0>
inline AutoDiffDiff<D, SCAL> operator/ (SCAL2 x, const AutoDiffDiff<D, SCAL> & y)
{
return x * Inv(y);
}
template<int D, typename SCAL>
inline AutoDiffDiff<D, SCAL> sqrt (const AutoDiffDiff<D, SCAL> & x)
{
AutoDiffDiff<D, SCAL> res;
res.Value() = sqrt(x.Value());
for (int j = 0; j < D; j++)
res.DValue(j) = IfZero(x.DValue(j),SCAL{0.},0.5 / res.Value() * x.DValue(j));
for (int i = 0; i < D; i++)
for (int j = 0; j < D; j++)
res.DDValue(i,j) = IfZero(x.DDValue(i,j)+x.DValue(i) * x.DValue(j),SCAL{0.},0.5/res.Value() * x.DDValue(i,j) - 0.25 / (x.Value()*res.Value()) * x.DValue(i) * x.DValue(j));
return res;
}
// df(u)/dx = exp(x) * du/dx
// d^2 f(u) / dx^2 = exp(x) * (du/dx)^2 + exp(x) * d^2u /dx^2
template <int D, typename SCAL>
NETGEN_INLINE AutoDiffDiff<D, SCAL> exp (AutoDiffDiff<D, SCAL> x)
{
AutoDiffDiff<D, SCAL> res;
res.Value() = exp(x.Value());
for (int k = 0; k < D; k++)
res.DValue(k) = x.DValue(k) * res.Value();
for (int k = 0; k < D; k++)
for (int l = 0; l < D; l++)
res.DDValue(k,l) = (x.DValue(k) * x.DValue(l)+x.DDValue(k,l)) * res.Value();
return res;
}
using std::pow;
template <int D, typename SCAL>
NETGEN_INLINE AutoDiffDiff<D,SCAL> pow (AutoDiffDiff<D,SCAL> x, AutoDiffDiff<D,SCAL> y )
{
return exp(log(x)*y);
}
template <int D, typename SCAL>
NETGEN_INLINE AutoDiffDiff<D, SCAL> log (AutoDiffDiff<D, SCAL> x)
{
AutoDiffDiff<D, SCAL> res;
res.Value() = log(x.Value());
SCAL xinv = 1.0/x.Value();
for (int k = 0; k < D; k++)
res.DValue(k) = x.DValue(k) * xinv;
for (int k = 0; k < D; k++)
for (int l = 0; l < D; l++)
res.DDValue(k,l) = -xinv*xinv*x.DValue(k) * x.DValue(l) + xinv * x.DDValue(k,l);
return res;
}
template <int D, typename SCAL>
NETGEN_INLINE AutoDiffDiff<D, SCAL> sin (AutoDiffDiff<D, SCAL> x)
{
AutoDiffDiff<D, SCAL> res;
SCAL s = sin(x.Value());
SCAL c = cos(x.Value());
res.Value() = s;
for (int k = 0; k < D; k++)
res.DValue(k) = x.DValue(k) * c;
for (int k = 0; k < D; k++)
for (int l = 0; l < D; l++)
res.DDValue(k,l) = -s * x.DValue(k) * x.DValue(l) + c * x.DDValue(k,l);
return res;
}
template <int D, typename SCAL>
NETGEN_INLINE AutoDiffDiff<D, SCAL> cos (AutoDiffDiff<D, SCAL> x)
{
AutoDiffDiff<D, SCAL> res;
SCAL s = sin(x.Value());
SCAL c = cos(x.Value());
res.Value() = c;
for (int k = 0; k < D; k++)
res.DValue(k) = -s * x.DValue(k);
for (int k = 0; k < D; k++)
for (int l = 0; l < D; l++)
res.DDValue(k,l) = -c * x.DValue(k) * x.DValue(l) - s * x.DDValue(k,l);
return res;
}
template <int D, typename SCAL>
NETGEN_INLINE AutoDiffDiff<D, SCAL> tan (AutoDiffDiff<D, SCAL> x)
{ return sin(x) / cos(x); }
template <int D, typename SCAL>
NETGEN_INLINE AutoDiffDiff<D, SCAL> atan (AutoDiffDiff<D, SCAL> x)
{
AutoDiffDiff<D, SCAL> res;
SCAL a = atan(x.Value());
res.Value() = a;
for (int k = 0; k < D; k++)
res.DValue(k) = x.DValue(k)/(1+x.Value()*x.Value()) ;
for (int k = 0; k < D; k++)
for (int l = 0; l < D; l++)
res.DDValue(k,l) = -2*x.Value()/((1+x.Value()*x.Value())*(1+x.Value()*x.Value())) * x.DValue(k) * x.DValue(l) + x.DDValue(k,l)/(1+x.Value()*x.Value());
return res;
}
template <int D, typename SCAL>
NETGEN_INLINE AutoDiffDiff<D, SCAL> atan2 (AutoDiffDiff<D, SCAL> x,AutoDiffDiff<D, SCAL> y)
{
AutoDiffDiff<D, SCAL> res;
SCAL a = atan2(x.Value(), y.Value());
res.Value() = a;
for (int k = 0; k < D; k++)
res.DValue(k) = (x.Value()*y.DValue(k)-y.Value()*x.DValue(k))/(y.Value()*y.Value()+x.Value()*x.Value());
for (int k = 0; k < D; k++)
for (int l = 0; l < D; l++)
res.DDValue(k,l) = (x.DValue(k)*y.DValue(l)+x.Value()*y.DDValue(l,k) - y.DValue(k)*x.DValue(l) - y.Value()*x.DDValue(l,k))/(y.Value()*y.Value()+x.Value()*x.Value()) - 2 * (x.Value()*y.DValue(k)-y.Value()*x.DValue(k)) * (x.Value()*x.DValue(k) + y.Value()*y.DValue(k))/( (y.Value()*y.Value()+x.Value()*x.Value()) * (y.Value()*y.Value()+x.Value()*x.Value()) );
return res;
}
using std::acos;
template <int D, typename SCAL>
NETGEN_INLINE AutoDiffDiff<D,SCAL> acos (AutoDiffDiff<D,SCAL> x)
{
AutoDiffDiff<D,SCAL> res;
SCAL a = acos(x.Value());
res.Value() = a;
auto omaa = 1-x.Value()*x.Value();
auto s = sqrt(omaa);
SCAL da = -1 / s;
SCAL dda = -x.Value() / (s*omaa);
for (int k = 0; k < D; k++)
res.DValue(k) = x.DValue(k)*da;
for (int k = 0; k < D; k++)
for (int l = 0; l < D; l++)
res.DDValue(k,l) = dda * x.DValue(k) * x.DValue(l) + da * x.DDValue(k,l);
return res;
}
using std::acos;
template <int D, typename SCAL>
NETGEN_INLINE AutoDiffDiff<D,SCAL> asin (AutoDiffDiff<D,SCAL> x)
{
AutoDiffDiff<D,SCAL> res;
SCAL a = asin(x.Value());
res.Value() = a;
auto omaa = 1-x.Value()*x.Value();
auto s = sqrt(omaa);
SCAL da = 1 / s;
SCAL dda = x.Value() / (s*omaa);
for (int k = 0; k < D; k++)
res.DValue(k) = x.DValue(k)*da;
for (int k = 0; k < D; k++)
for (int l = 0; l < D; l++)
res.DDValue(k,l) = dda * x.DValue(k) * x.DValue(l) + da * x.DDValue(k,l);
return res;
}
template <int D, typename SCAL>
NETGEN_INLINE AutoDiffDiff<D, SCAL> sinh (AutoDiffDiff<D, SCAL> x)
{
AutoDiffDiff<D, SCAL> res;
SCAL sh = sinh(x.Value());
SCAL ch = cosh(x.Value());
res.Value() = sh;
for (int k = 0; k < D; k++)
res.DValue(k) = x.DValue(k) * ch;
for (int k = 0; k < D; k++)
for (int l = 0; l < D; l++)
res.DDValue(k,l) = sh * x.DValue(k) * x.DValue(l) + ch * x.DDValue(k,l);
return res;
}
template <int D, typename SCAL>
NETGEN_INLINE AutoDiffDiff<D, SCAL> cosh (AutoDiffDiff<D, SCAL> x)
{
AutoDiffDiff<D, SCAL> res;
SCAL sh = sinh(x.Value());
SCAL ch = cosh(x.Value());
res.Value() = ch;
for (int k = 0; k < D; k++)
res.DValue(k) = sh * x.DValue(k);
for (int k = 0; k < D; k++)
for (int l = 0; l < D; l++)
res.DDValue(k,l) = ch * x.DValue(k) * x.DValue(l) + sh * x.DDValue(k,l);
return res;
}
template <int D, typename SCAL>
NETGEN_INLINE AutoDiffDiff<D, SCAL> erf (AutoDiffDiff<D, SCAL> x)
{
AutoDiffDiff<D, SCAL> res;
SCAL derf = 2. / sqrt(M_PI) * exp(- x.Value() * x.Value());
res.Value() = erf(x.Value());
for (int k = 0; k < D; k++)
res.DValue(k) = - derf * x.DValue(k);
for (int k = 0; k < D; k++)
for (int l = 0; l < D; l++)
res.DDValue(k,l) = derf * (x.DDValue(k, l) - 2 * x.Value() * x.DValue(k) * x.DValue(l));
return res;
}
using std::floor;
template<int D, typename SCAL>
NETGEN_INLINE AutoDiffDiff<D,SCAL> floor (const AutoDiffDiff<D,SCAL> & x)
{
return floor(x.Value());
}
using std::ceil;
template<int D, typename SCAL>
NETGEN_INLINE AutoDiffDiff<D,SCAL> ceil (const AutoDiffDiff<D,SCAL> & x)
{
return ceil(x.Value());
}
template <int D, typename SCAL, typename TB, typename TC>
auto IfPos (AutoDiffDiff<D,SCAL> a, TB b, TC c) -> decltype(IfPos (a.Value(), b, c))
{
return IfPos (a.Value(), b, c);
}
template <int D, typename SCAL>
NETGEN_INLINE AutoDiffDiff<D,SCAL> IfPos (SCAL /* SIMD<double> */ a, AutoDiffDiff<D,SCAL> b, AutoDiffDiff<D,SCAL> c)
{
AutoDiffDiff<D,SCAL> res;
res.Value() = IfPos (a, b.Value(), c.Value());
for (int j = 0; j < D; j++)
{
res.DValue(j) = IfPos (a, b.DValue(j), c.DValue(j));
res.DDValue(j) = IfPos (a, b.DDValue(j), c.DDValue(j));
}
return res;
}
template <int D, typename SCAL, typename TC>
NETGEN_INLINE AutoDiffDiff<D,SCAL> IfPos (SCAL /* SIMD<double> */ a, AutoDiffDiff<D,SCAL> b, TC c)
{
return IfPos (a, b, AutoDiffDiff<D,SCAL> (c));
}
//@}
}
namespace ngbla
{
template <typename T> struct is_scalar_type;
template <int D, typename T>
struct is_scalar_type<ngcore::AutoDiffDiff<D,T>> { static constexpr bool value = true; };
// not meaningful for AutoDiff<D,Complex>, since this is
// not (complex) differentiable anyway
template<int D, typename SCAL>
inline auto L2Norm2 (const ngcore::AutoDiffDiff<D,SCAL> & x)
{
return x*x;
}
}
#endif

View File

@ -40,12 +40,13 @@ namespace ngcore
if (owns_data)
{
delete [] data;
mt.Free(Addr(size)+1);
mt.Free(GetMemoryUsage());
}
size = asize;
data = new unsigned char [Addr (size)+1];
mt.Alloc(Addr(size)+1);
owns_data = true;
mt.Alloc(GetMemoryUsage());
}
BitArray & BitArray :: Set () throw()

View File

@ -49,6 +49,7 @@ public:
{
ba2.owns_data = false;
ba2.data = nullptr;
mt = std::move(ba2.mt);
}
template <typename T>
@ -59,13 +60,17 @@ public:
int cnt = 0;
for (auto i = list.begin(); i < list.end(); i++, cnt++)
if (*i) SetBit(cnt);
StartMemoryTracing();
}
/// delete data
~BitArray ()
{
if (owns_data)
{
delete [] data;
mt.Free(GetMemoryUsage());
}
}
/// Set size, loose values
@ -150,11 +155,11 @@ public:
NGCORE_API auto * Data() const { return data; }
const size_t GetMemoryUsage() const { return owns_data ? (size+CHAR_BIT-1)/CHAR_BIT : 0; }
const MemoryTracer& GetMemoryTracer() const { return mt; }
void StartMemoryTracing() const
{
if(owns_data)
mt.Alloc(Addr(size)+1);
mt.Alloc(GetMemoryUsage());
}
private:
@ -205,6 +210,31 @@ private:
NGCORE_API std::ostream & operator<<(std::ostream & s, const BitArray & ba);
template <typename IndexType>
class TBitArray : public BitArray
{
public:
using BitArray::BitArray;
void SetBit (IndexType i) { BitArray::SetBit(i-IndexBASE<IndexType>()); }
void Clear () { BitArray::Clear(); }
void Clear (IndexType i) { BitArray::Clear(i-IndexBASE<IndexType>()); }
void SetBitAtomic (IndexType i) { BitArray::SetBitAtomic(i-IndexBASE<IndexType>()); }
bool Test (IndexType i) const { return BitArray::Test(i-IndexBASE<IndexType>()); }
bool operator[] (IndexType i) const { return Test(i); }
T_Range<IndexType> Range() const { return { IndexBASE<IndexType>(), IndexBASE<IndexType>()+Size() }; }
NGCORE_API TBitArray & Or (const TBitArray & ba2)
{
BitArray::Or(ba2);
return *this;
}
};
} // namespace ngcore
#endif // NETGEN_CORE_BITARRAY

View File

@ -1,15 +1,69 @@
#include "exception.hpp"
#include "utils.hpp"
#ifdef EMSCRIPTEN
#include <iostream>
#endif // EMSCRIPTEN
namespace ngcore
{
Exception :: Exception(const std::string& s)
: m_what(s) {}
: m_what(s) {
#ifdef EMSCRIPTEN
std::cout << "THROW Exception " << s << std::endl;
#endif
}
Exception :: Exception(const char* s)
: m_what(s) {}
: m_what(s) {
#ifdef EMSCRIPTEN
std::cout << "THROW Exception " << s << std::endl;
#endif
}
Exception :: Exception(std::string_view s1, std::string_view s2)
: Exception(std::string(s1)+std::string(s2))
{ }
Exception :: Exception(std::string_view s1, std::string_view s2, std::string_view s3)
: Exception(std::string(s1)+std::string(s2)+std::string(s3))
{ }
void Exception :: Throw (std::string_view s1)
{
throw Exception(std::string(s1));
}
void Exception :: Throw (std::string_view s1, std::string_view s2)
{
throw Exception(std::string(s1)+std::string(s2));
}
void Exception :: Throw (std::string_view s1, std::string_view s2, std::string_view s3)
{
throw Exception(std::string(s1)+std::string(s2)+std::string(s3));
}
RangeException :: RangeException (// const std::string & where,
const char * where,
ptrdiff_t ind, ptrdiff_t imin, ptrdiff_t imax) : Exception("")
{
std::stringstream str;
str << where << ": index " << ind << " out of range [" << imin << "," << imax << ")\n";
Append (str.str());
Append (GetBackTrace());
}
void ThrowRangeException(const char * s, ptrdiff_t ind, ptrdiff_t imin, ptrdiff_t imax)
{
throw RangeException(s, ind, imin, imax);
}
void ThrowException(const std::string & s)
{
throw Exception (s);
@ -19,11 +73,18 @@ namespace ngcore
{
throw Exception (s);
}
void ThrowNotTheSameException(const char * s, ptrdiff_t a, ptrdiff_t b)
{
throw ngcore::Exception(std::string(s) + ", a="+ToString(a) + ", b="+ToString(b) + GetBackTrace());
}
} // namespace ngcore
// ********* STUFF FOR GETBACKTRACE ***************************
#ifdef __GNUC__
#if defined __GNUC__ && !defined __EMSCRIPTEN__
#include <execinfo.h>
#include <string.h>
@ -67,7 +128,7 @@ namespace ngcore
// 1 libngcore.dylib 0x000000010ddb298c _ZL21ngcore_signal_handleri + 316
constexpr char reset_shell[] = "\033[0m";
constexpr char green[] = "\033[32m";
constexpr char yellow[] = "\033[33m";
[[maybe_unused]] constexpr char yellow[] = "\033[33m";
std::istringstream in(s);
@ -122,7 +183,7 @@ namespace ngcore
auto libname = s.substr(0, brace_open_pos);
auto funcname = s.substr(brace_open_pos+1, plus_pos - brace_open_pos - 1);
auto offset = std::strtoul(s.substr(plus_pos+1, brace_close_pos - plus_pos - 1).c_str(), 0, 16);
auto position = std::strtoul(s.substr(bracket_open_pos+1, bracket_close_pos - bracket_open_pos - 1).c_str(), 0, 16);
// auto position = std::strtoul(s.substr(bracket_open_pos+1, bracket_close_pos - bracket_open_pos - 1).c_str(), 0, 16);
std::stringstream out;
if(!funcname.empty())
@ -181,7 +242,7 @@ namespace ngcore
for (i = 1; i < bt_size-1; i++)
{
dladdr(bt[i], &info);
size_t len = strlen(bt_syms[i]);
// size_t len = strlen(bt_syms[i]);
result << '#'<< i << '\t' << detail::TranslateBacktrace( bt_syms[i], info.dli_fname );
}
free(bt_syms);
@ -226,7 +287,7 @@ static bool dummy = []()
return true;
}();
#else // __GNUC__
#else // __GNUC__ and not __EMSCRIPTEN__
namespace ngcore
{

View File

@ -1,16 +1,17 @@
#ifndef NETGEN_CORE_EXCEPTION_HPP
#define NETGEN_CORE_EXCEPTION_HPP
#include <cstddef>
#include <sstream> // for stringstream
#include <stdexcept> // for exception
#include <string> // for string
#include "ngcore_api.hpp" // for NGCORE_API
#include "utils.hpp" // for ToString
namespace ngcore
{
NGCORE_API std::string GetBackTrace();
// Exception for code that shouldn't be executed
@ -33,8 +34,14 @@ namespace ngcore
Exception(Exception&&) = default;
Exception(const std::string& s); // : m_what(s) {}
Exception(const char* s); // : m_what(s) {}
Exception(std::string_view s1, std::string_view s2);
Exception(std::string_view s1, std::string_view s2, std::string_view s3);
~Exception() override = default;
[[noreturn]] static void Throw (std::string_view s1);
[[noreturn]] static void Throw (std::string_view s1, std::string_view s2);
[[noreturn]] static void Throw (std::string_view s1, std::string_view s2, std::string_view s3);
Exception& operator =(const Exception&) = default;
Exception& operator =(Exception&&) noexcept = default;
@ -50,23 +57,26 @@ namespace ngcore
const char* what() const noexcept override { return m_what.c_str(); }
};
NGCORE_API void ThrowException(const std::string & s);
NGCORE_API void ThrowException(const char * s);
[[noreturn]] NGCORE_API void ThrowException(const std::string & s);
[[noreturn]] NGCORE_API void ThrowException(const char * s);
// Out of Range exception
class NGCORE_API RangeException : public Exception
{
public:
/// where it occurs, index, minimal and maximal indices
RangeException (const std::string & where,
int ind, int imin, int imax) : Exception("")
RangeException (// const std::string & where,
const char * where,
ptrdiff_t ind, ptrdiff_t imin, ptrdiff_t imax);
/*
: Exception("")
{
std::stringstream str;
str << where << ": index " << ind << " out of range [" << imin << "," << imax << ")\n";
Append (str.str());
Append (GetBackTrace());
}
*/
template<typename T>
RangeException(const std::string& where, const T& value)
{
@ -76,9 +86,40 @@ namespace ngcore
}
};
[[noreturn]] NGCORE_API void ThrowRangeException(const char * s, ptrdiff_t ind, ptrdiff_t imin, ptrdiff_t imax);
[[noreturn]] NGCORE_API void ThrowNotTheSameException(const char * s, ptrdiff_t a, ptrdiff_t b);
// Exception used if no simd implementation is available to fall back to standard evaluation
class NGCORE_API ExceptionNOSIMD : public Exception
{ public: using Exception::Exception; };
template <typename T>
struct IsSafe {
constexpr operator bool() const { return false; } };
namespace detail {
template <typename T, typename Tmin, typename Tmax>
inline static constexpr void CheckRange(const char * s, const T& n, Tmin first, Tmax next)
{
if constexpr (!IsSafe<decltype(n)>())
if (n<first || n>=next)
ThrowRangeException(s, ptrdiff_t(n), ptrdiff_t(first), ptrdiff_t(next));
}
template <typename Ta, typename Tb>
inline static constexpr void CheckSame(const char * s, const Ta& a, const Tb& b)
{
if constexpr (!IsSafe<decltype(a)>() || !IsSafe<decltype(b)>())
if(a != b)
{
if constexpr(std::is_integral_v<decltype(a)> && std::is_same_v<decltype(a),decltype(b)>)
ThrowNotTheSameException(s, long(a), long(b)); \
else
throw Exception(std::string(s) + "\t: not the same, a="+ToString(a) + ", b="+ngcore::ToString(b) + GetBackTrace());
}
}
} // namespace detail
} // namespace ngcore
#define NETGEN_CORE_NGEXEPTION_STR_HELPER(x) #x
@ -88,16 +129,15 @@ namespace ngcore
#define NG_EXCEPTION(s) ngcore::Exception(__FILE__ ":" NETGEN_CORE_NGEXEPTION_STR(__LINE__) "\t"+std::string(s))
#if defined(NETGEN_ENABLE_CHECK_RANGE) && !defined(__CUDA_ARCH__)
#define NETGEN_CHECK_RANGE(value, min, max_plus_one) \
{ if ((value)<(min) || (value)>=(max_plus_one)) \
throw ngcore::RangeException(__FILE__ ":" NETGEN_CORE_NGEXEPTION_STR(__LINE__) "\t", (value), (min), (max_plus_one)); }
#define NETGEN_CHECK_SHAPE(a,b) \
{ if(a.Shape() != b.Shape()) \
throw ngcore::Exception(__FILE__": shape don't match"); }
#define NETGEN_CHECK_RANGE(value, min, max_plus_one) ngcore::detail::CheckRange(__FILE__ ":" NETGEN_CORE_NGEXEPTION_STR(__LINE__) "\t", value, min, max_plus_one);
#define NETGEN_CHECK_SAME(a,b) ngcore::detail::CheckSame(__FILE__ ":" NETGEN_CORE_NGEXEPTION_STR(__LINE__) "\t", a, b);
#define NETGEN_NOEXCEPT
#else // defined(NETGEN_ENABLE_CHECK_RANGE) && !defined(__CUDA_ARCH__)
#define NETGEN_CHECK_RANGE(value, min, max)
#define NETGEN_CHECK_SHAPE(a,b)
#define NETGEN_CHECK_SAME(a,b)
// #define NETGEN_CHECK_SHAPE(a,b)
#define NETGEN_NOEXCEPT noexcept
#endif // defined(NETGEN_ENABLE_CHECK_RANGE) && !defined(__CUDA_ARCH__)

View File

@ -16,6 +16,7 @@
namespace ngcore
{
using std::string;
using std::string_view;
using std::endl;
Flags :: Flags () { ; }
@ -209,18 +210,18 @@ namespace ngcore
}
double Flags :: GetNumFlag (const string & name, double def) const
double Flags :: GetNumFlag (string_view name, double def) const
{
if (numflags.Used (name))
return numflags[name];
return numflags[string(name)];
else
return def;
}
const double * Flags :: GetNumFlagPtr (const string & name) const
const double * Flags :: GetNumFlagPtr (string_view name) const
{
if (numflags.Used (name))
return & ((SymbolTable<double>&)numflags)[name];
return & ((SymbolTable<double>&)numflags)[string(name)];
else
return NULL;
}
@ -239,16 +240,16 @@ namespace ngcore
return defflags.Used (name);
}
*/
bool Flags :: GetDefineFlag (const string & name) const throw()
bool Flags :: GetDefineFlag (string_view name) const throw()
{
if (!defflags.Used (name)) return false;
return defflags[name];
if (!defflags.Used (string(name))) return false;
return defflags[string(name)];
}
xbool Flags :: GetDefineFlagX (const string & name) const throw()
xbool Flags :: GetDefineFlagX (string_view name) const throw()
{
if (!defflags.Used (name)) return maybe;
return bool(defflags[name]);
if (!defflags.Used (string(name))) return maybe;
return bool(defflags[string(name)]);
}
@ -296,32 +297,32 @@ namespace ngcore
return empty;
}
bool Flags :: StringFlagDefined (const string & name) const
bool Flags :: StringFlagDefined (string_view name) const noexcept
{
return strflags.Used (name);
}
bool Flags :: NumFlagDefined (const string &name) const
bool Flags :: NumFlagDefined (string_view name) const noexcept
{
return numflags.Used (name);
}
bool Flags :: FlagsFlagDefined (const string &name) const
bool Flags :: FlagsFlagDefined (string_view name) const noexcept
{
return flaglistflags.Used (name);
}
bool Flags :: StringListFlagDefined (const string & name) const
bool Flags :: StringListFlagDefined (string_view name) const noexcept
{
return strlistflags.Used (name);
}
bool Flags :: NumListFlagDefined (const string & name) const
bool Flags :: NumListFlagDefined (string_view name) const noexcept
{
return numlistflags.Used (name);
}
bool Flags :: AnyFlagDefined (const string& name) const
bool Flags :: AnyFlagDefined (string_view name) const noexcept
{
return anyflags.Used(name);
}

View File

@ -125,15 +125,15 @@ namespace ngcore
/// Returns std::string flag, default value if not exists
std::string GetStringFlag (const std::string & name, std::string def = "") const;
/// Returns numerical flag, default value if not exists
double GetNumFlag (const std::string & name, double def) const;
double GetNumFlag (std::string_view name, double def) const;
/// Returns address of numerical flag, null if not exists
const double * GetNumFlagPtr (const std::string & name) const;
const double * GetNumFlagPtr (std::string_view name) const;
/// Returns address of numerical flag, null if not exists
double * GetNumFlagPtr (const std::string & name);
/// Returns boolean flag
// int GetDefineFlag (const char * name) const;
bool GetDefineFlag (const std::string & name) const throw();
xbool GetDefineFlagX (const std::string & name) const throw();
bool GetDefineFlag (std::string_view name) const noexcept;
xbool GetDefineFlagX (std::string_view name) const noexcept;
/// Returns string list flag, empty array if not exist
const Array<std::string> & GetStringListFlag (const std::string & name) const;
/// Returns num list flag, empty array if not exist
@ -144,16 +144,16 @@ namespace ngcore
/// Test, if string flag is defined
bool StringFlagDefined (const std::string & name) const;
bool StringFlagDefined (std::string_view name) const noexcept;
/// Test, if num flag is defined
bool NumFlagDefined (const std::string & name) const;
bool NumFlagDefined (std::string_view name) const noexcept;
/// Test, if num flag is defined
bool FlagsFlagDefined (const std::string & name) const;
bool FlagsFlagDefined (std::string_view name) const noexcept;
/// Test, if string list flag is defined
bool StringListFlagDefined (const std::string & name) const;
bool StringListFlagDefined (std::string_view name) const noexcept;
/// Test, if num list flag is defined
bool NumListFlagDefined (const std::string & name) const;
bool AnyFlagDefined (const std::string& name) const;
bool NumListFlagDefined (std::string_view name) const noexcept;
bool AnyFlagDefined (std::string_view name) const noexcept;
/// number of string flags
int GetNStringFlags () const { return strflags.Size(); }

View File

@ -0,0 +1,174 @@
functions = [
("double", "MPI_Wtime"),
("int", "MPI_Allgather", "void*", "int", "MPI_Datatype", "void*", "int", "MPI_Datatype", "MPI_Comm"),
("int", "MPI_Allreduce", "void*", "void*", "int", "MPI_Datatype", "MPI_Op", "MPI_Comm"),
("int", "MPI_Alltoall", "void*", "int", "MPI_Datatype", "void*", "int", "MPI_Datatype", "MPI_Comm"),
("int", "MPI_Barrier", "MPI_Comm"),
("int", "MPI_Bcast", "void*", "int", "MPI_Datatype", "int", "MPI_Comm"),
("int", "MPI_Ibcast", "void*", "int", "MPI_Datatype", "int", "MPI_Comm", "MPI_Request*"),
("int", "MPI_Comm_c2f", "MPI_Comm"),
("int", "MPI_Comm_create", "MPI_Comm", "MPI_Group", "MPI_Comm*"),
("int", "MPI_Comm_create_group", "MPI_Comm", "MPI_Group", "int", "MPI_Comm*"),
("int", "MPI_Comm_free", "MPI_Comm*"),
("int", "MPI_Comm_group", "MPI_Comm", "MPI_Group*"),
("int", "MPI_Comm_rank", "MPI_Comm", "int*"),
("int", "MPI_Comm_size", "MPI_Comm", "int*"),
("int", "MPI_Finalize"),
("int", "MPI_Gather", "void*", "int", "MPI_Datatype", "void*", "int", "MPI_Datatype", "int", "MPI_Comm"),
("int", "MPI_Gatherv", "void*", "int", "MPI_Datatype", "void*", "int*", "int*", "MPI_Datatype", "int", "MPI_Comm"),
("int", "MPI_Get_count", "MPI_Status*", "MPI_Datatype", "int*"),
("int", "MPI_Get_processor_name", "char*", "int*"),
("int", "MPI_Group_incl", "MPI_Group", "int", "int*", "MPI_Group*"),
("int", "MPI_Init", "int*", "char***"),
("int", "MPI_Init_thread", "int*", "char***", "int", "int*"),
("int", "MPI_Initialized", "int*"),
("int", "MPI_Iprobe", "int", "int", "MPI_Comm", "int*", "MPI_Status*"),
("int", "MPI_Irecv", "void*", "int", "MPI_Datatype", "int", "int", "MPI_Comm", "MPI_Request*"),
("int", "MPI_Isend", "void*", "int", "MPI_Datatype", "int", "int", "MPI_Comm", "MPI_Request*"),
("int", "MPI_Probe", "int", "int", "MPI_Comm", "MPI_Status*"),
("int", "MPI_Query_thread", "int*"),
("int", "MPI_Recv", "void*", "int", "MPI_Datatype", "int", "int", "MPI_Comm", "MPI_Status*"),
("int", "MPI_Recv_init", "void*", "int", "MPI_Datatype", "int", "int", "MPI_Comm", "MPI_Request*"),
("int", "MPI_Reduce", "void*", "void*", "int", "MPI_Datatype", "MPI_Op", "int", "MPI_Comm"),
("int", "MPI_Reduce_local", "void*", "void*", "int", "MPI_Datatype", "MPI_Op"),
("int", "MPI_Request_free", "MPI_Request*"),
("int", "MPI_Scatter", "void*", "int", "MPI_Datatype", "void*", "int", "MPI_Datatype", "int", "MPI_Comm"),
("int", "MPI_Send", "void*", "int", "MPI_Datatype", "int", "int", "MPI_Comm"),
("int", "MPI_Send_init", "void*", "int", "MPI_Datatype", "int", "int", "MPI_Comm", "MPI_Request*"),
("int", "MPI_Startall", "int", "MPI_Request*:0"),
("int", "MPI_Type_commit", "MPI_Datatype*"),
("int", "MPI_Type_contiguous", "int", "MPI_Datatype", "MPI_Datatype*"),
("int", "MPI_Type_create_resized", "MPI_Datatype", "MPI_Aint", "MPI_Aint", "MPI_Datatype*"),
("int", "MPI_Type_create_struct", "int", "int*:0", "MPI_Aint*:0", "MPI_Datatype*:0", "MPI_Datatype*"),
("int", "MPI_Type_free", "MPI_Datatype*"),
("int", "MPI_Type_get_extent", "MPI_Datatype", "MPI_Aint*", "MPI_Aint*"),
("int", "MPI_Type_indexed", "int", "int*:0", "int*:0", "MPI_Datatype", "MPI_Datatype*"),
("int", "MPI_Type_size", "MPI_Datatype", "int*"),
("int", "MPI_Wait", "MPI_Request*", "MPI_Status*"),
("int", "MPI_Waitall", "int", "MPI_Request*:0", "MPI_Status*"),
("int", "MPI_Waitany", "int", "MPI_Request*:0", "int*", "MPI_Status*"),
]
constants = [
("MPI_Comm", "MPI_COMM_NULL"),
("MPI_Comm", "MPI_COMM_WORLD"),
("MPI_Datatype", "MPI_CHAR"),
("MPI_Datatype", "MPI_CXX_DOUBLE_COMPLEX"),
("MPI_Datatype", "MPI_C_BOOL"),
("MPI_Datatype", "MPI_DATATYPE_NULL"),
("MPI_Datatype", "MPI_DOUBLE"),
("MPI_Datatype", "MPI_FLOAT"),
("MPI_Datatype", "MPI_INT"),
("MPI_Datatype", "MPI_SHORT"),
("MPI_Datatype", "MPI_UINT64_T"),
("MPI_Op", "MPI_LOR"),
("MPI_Op", "MPI_MAX"),
("MPI_Op", "MPI_MIN"),
("MPI_Op", "MPI_SUM"),
("MPI_Request", "MPI_REQUEST_NULL"),
("MPI_Status*", "MPI_STATUSES_IGNORE"),
("MPI_Status*", "MPI_STATUS_IGNORE"),
("int", "MPI_ANY_SOURCE"),
("int", "MPI_ANY_TAG"),
("int", "MPI_MAX_PROCESSOR_NAME"),
("int", "MPI_PROC_NULL"),
("int", "MPI_ROOT"),
("int", "MPI_SUBVERSION"),
("int", "MPI_THREAD_MULTIPLE"),
("int", "MPI_THREAD_SINGLE"),
("int", "MPI_VERSION"),
("void*", "MPI_IN_PLACE"),
]
def get_args(f, counts=False):
args = []
for arg in f[2:]:
has_count = ':' in arg
if has_count:
s, count = arg.split(':')
count = int(count)
else:
s = arg
count = None
if s.startswith("MPI_"):
s = "NG_" + s
if counts:
args.append((s, count))
else:
args.append(s)
return args
def generate_declarations():
code = ""
nowrapper_code = ""
for f in functions:
ret = f[0]
name = f[1]
args = ", ".join(get_args(f))
code += f"NGCORE_API extern {ret} (*NG_{name})({args});\n"
nowrapper_code += f"#define NG_{name} {name}\n"
for typ, name in constants:
if typ.startswith("MPI_"):
typ = "NG_" + typ
code += f"NGCORE_API extern {typ} NG_{name};\n"
nowrapper_code += f"#define NG_{name} {name}\n"
with open("ng_mpi_generated_declarations.hpp", "w") as f:
f.write("#ifdef NG_MPI_WRAPPER\n")
f.write(code)
f.write("#else // NG_MPI_WRAPPER\n")
f.write(nowrapper_code)
f.write("#endif // NG_MPI_WRAPPER\n")
def generate_dummy_init():
code = ""
for f in functions:
ret = f[0]
name = f[1]
args = ", ".join(get_args(f))
code += f"decltype(NG_{name}) NG_{name} = []({args})->{ret} {{ throw no_mpi(); }};\n"
for typ, name in constants:
if typ.startswith("MPI_"):
typ = "NG_" + typ
code += f"{typ} NG_{name} = 0;\n"
with open("ng_mpi_generated_dummy_init.hpp", "w") as f:
f.write(code)
def generate_init():
code = ""
for f in functions:
ret = f[0]
name = f[1]
args = get_args(f, counts=True)
in_args =''
call_args = ''
for i in range(len(args)):
arg, count = args[i]
if i > 0:
in_args += ', '
call_args += ', '
in_args += arg + f" arg{i}"
if not arg.startswith("NG_"):
# plain type (like int, int *, etc.), just pass the argument along
call_args += f" arg{i}"
elif count is None:
# MPI type (by value or pointer), but just one object, no arrays
call_args += f" ng2mpi(arg{i})"
else:
# arrays of MPI types, we need to copy them due to incompatible size
call_args += f" ng2mpi(arg{i}, arg{count})"
code += f"NG_{name} = []({in_args})->{ret} {{ return {name}({call_args}); }};\n"
for _, name in constants:
code += f"NG_{name} = mpi2ng({name});\n"
with open("ng_mpi_generated_init.hpp", "w") as f:
f.write(code)
if __name__ == "__main__":
generate_declarations()
generate_dummy_init()
generate_init()

View File

@ -9,8 +9,9 @@
#include <string>
#include <tuple>
#include <optional>
#include "mpi_wrapper.hpp"
// #include "mpi_wrapper.hpp"
#include "ngcore_api.hpp"
#include "table.hpp"
#include "utils.hpp"
@ -37,53 +38,68 @@ namespace ngcore
};
// feature check macro for transition from INT to IVec
#define NGCORE_HAS_IVEC
/// N integers
template <int N, typename T = int>
class INT
class IVec
{
/// data
T i[(N>0)?N:1];
// T i[(N>0)?N:1];
HTArray<N,T> i;
public:
///
NETGEN_INLINE INT () { }
constexpr NETGEN_INLINE IVec () = default;
constexpr NETGEN_INLINE IVec (const IVec & i1) : i(i1.i) { }
constexpr NETGEN_INLINE IVec (T ai1) : i(ai1) { }
template <class... T2,
std::enable_if_t<N==1+sizeof...(T2),bool> = true>
constexpr IVec (const T &v, T2... rest)
: i{v,rest...} { }
/*
/// init all
NETGEN_INLINE INT (T ai1)
NETGEN_INLINE IVec (T ai1)
{
for (int j = 0; j < N; j++) { i[j] = ai1; }
for (int j = 0; j < N; j++) { i[j] = ai1; }
}
/// init i[0], i[1]
constexpr NETGEN_INLINE INT (T ai1, T ai2)
constexpr NETGEN_INLINE IVec (T ai1, T ai2)
: i{ai1, ai2} { ; }
/// init i[0], i[1], i[2]
constexpr NETGEN_INLINE INT (T ai1, T ai2, T ai3)
constexpr NETGEN_INLINE IVec (T ai1, T ai2, T ai3)
: i{ai1, ai2, ai3} { ; }
/// init i[0], i[1], i[2]
constexpr NETGEN_INLINE INT (T ai1, T ai2, T ai3, T ai4)
constexpr NETGEN_INLINE IVec (T ai1, T ai2, T ai3, T ai4)
: i{ai1, ai2, ai3, ai4} { ; }
/// init i[0], i[1], i[2]
constexpr NETGEN_INLINE INT (T ai1, T ai2, T ai3, T ai4, T ai5)
constexpr NETGEN_INLINE IVec (T ai1, T ai2, T ai3, T ai4, T ai5)
: i{ai1, ai2, ai3, ai4, ai5} { ; }
/// init i[0], i[1], i[2]
NETGEN_INLINE INT (T ai1, T ai2, T ai3, T ai4, T ai5, T ai6, T ai7, T ai8, T ai9)
NETGEN_INLINE IVec (T ai1, T ai2, T ai3, T ai4, T ai5, T ai6, T ai7, T ai8, T ai9)
: i{ai1, ai2, ai3, ai4, ai5, ai6, ai7, ai8, ai9 } { ; }
*/
template <typename ARCHIVE>
void DoArchive(ARCHIVE& ar)
{
ar.Do(i, N);
// ar.Do(i.begin(), N);
ar.Do(i.Ptr(), N);
}
template <int N2, typename T2>
NETGEN_INLINE INT (const INT<N2,T2> & in2)
NETGEN_INLINE IVec (const IVec<N2,T2> & in2)
{
if (N2 <= N)
{
@ -100,7 +116,7 @@ namespace ngcore
}
template <typename T2>
NETGEN_INLINE INT (const BaseArrayObject<T2> & ao)
NETGEN_INLINE IVec (const BaseArrayObject<T2> & ao)
{
for (int j = 0; j < N; j++)
i[j] = ao.Spec()[j];
@ -108,7 +124,7 @@ namespace ngcore
NETGEN_INLINE size_t Size() const { return N; }
/// all ints equal ?
NETGEN_INLINE bool operator== (const INT & in2) const
NETGEN_INLINE bool operator== (const IVec & in2) const
{
for (int j = 0; j < N; j++)
if (i[j] != in2.i[j]) return 0;
@ -116,7 +132,7 @@ namespace ngcore
}
/// any ints unequal ?
NETGEN_INLINE bool operator!= (const INT & in2) const
NETGEN_INLINE bool operator!= (const IVec & in2) const
{
for (int j = 0; j < N; j++)
if (i[j] != in2.i[j]) return 1;
@ -124,7 +140,7 @@ namespace ngcore
}
/// sort integers
NETGEN_INLINE INT & Sort () &
NETGEN_INLINE IVec & Sort () &
{
for (int k = 0; k < N; k++)
for (int l = k+1; l < N; l++)
@ -133,7 +149,7 @@ namespace ngcore
return *this;
}
NETGEN_INLINE INT Sort () &&
NETGEN_INLINE IVec Sort () &&
{
for (int k = 0; k < N; k++)
for (int l = k+1; l < N; l++)
@ -155,7 +171,7 @@ namespace ngcore
operator FlatArray<T> () { return FlatArray<T> (N, &i[0]); }
NETGEN_INLINE INT<N,T> & operator= (T value)
NETGEN_INLINE IVec<N,T> & operator= (T value)
{
for (int j = 0; j < N; j++)
i[j] = value;
@ -163,7 +179,7 @@ namespace ngcore
}
template <typename T2>
NETGEN_INLINE INT<N,T> & operator= (INT<N,T2> v2)
NETGEN_INLINE IVec<N,T> & operator= (IVec<N,T2> v2)
{
for (int j = 0; j < N; j++)
i[j] = v2[j];
@ -186,14 +202,14 @@ namespace ngcore
/// sort 2 integers
template <>
NETGEN_INLINE INT<2> & INT<2>::Sort () &
NETGEN_INLINE IVec<2> & IVec<2>::Sort () &
{
if (i[0] > i[1]) Swap (i[0], i[1]);
return *this;
}
template <>
NETGEN_INLINE INT<2> INT<2>::Sort () &&
NETGEN_INLINE IVec<2> IVec<2>::Sort () &&
{
if (i[0] > i[1]) Swap (i[0], i[1]);
return *this;
@ -201,7 +217,7 @@ namespace ngcore
/// sort 3 integers
template <>
NETGEN_INLINE INT<3> INT<3>::Sort () &&
NETGEN_INLINE IVec<3> IVec<3>::Sort () &&
{
if (i[0] > i[1]) Swap (i[0], i[1]);
if (i[1] > i[2]) Swap (i[1], i[2]);
@ -211,7 +227,7 @@ namespace ngcore
/// Print integers
template <int N, typename T>
inline ostream & operator<<(ostream & s, const INT<N,T> & i2)
inline ostream & operator<<(ostream & s, const IVec<N,T> & i2)
{
for (int j = 0; j < N; j++)
s << (int) i2[j] << " ";
@ -219,15 +235,15 @@ namespace ngcore
}
template <int N, typename T>
auto begin(const INT<N,T> & ind)
auto begin(const IVec<N,T> & ind)
{
return AOWrapperIterator<INT<N,T>> (ind, 0);
return AOWrapperIterator<IVec<N,T>> (ind, 0);
}
template <int N, typename T>
auto end(const INT<N,T> & ind)
auto end(const IVec<N,T> & ind)
{
return AOWrapperIterator<INT<N,T>> (ind, N);
return AOWrapperIterator<IVec<N,T>> (ind, N);
}
@ -236,9 +252,9 @@ namespace ngcore
template <int N, typename TI>
NETGEN_INLINE size_t HashValue (const INT<N,TI> & ind, size_t size)
NETGEN_INLINE size_t HashValue (const IVec<N,TI> & ind, size_t size)
{
INT<N,size_t> lind = ind;
IVec<N,size_t> lind = ind;
size_t sum = 0;
for (int i = 0; i < N; i++)
sum += lind[i];
@ -247,24 +263,24 @@ namespace ngcore
/// hash value of 1 int
template <typename TI>
NETGEN_INLINE size_t HashValue (const INT<1,TI> & ind, size_t size)
NETGEN_INLINE size_t HashValue (const IVec<1,TI> & ind, size_t size)
{
return ind[0] % size;
}
/// hash value of 2 int
template <typename TI>
NETGEN_INLINE size_t HashValue (const INT<2,TI> & ind, size_t size)
NETGEN_INLINE size_t HashValue (const IVec<2,TI> & ind, size_t size)
{
INT<2,size_t> lind = ind;
IVec<2,size_t> lind = ind;
return (113*lind[0]+lind[1]) % size;
}
/// hash value of 3 int
template <typename TI>
NETGEN_INLINE size_t HashValue (const INT<3,TI> & ind, size_t size)
NETGEN_INLINE size_t HashValue (const IVec<3,TI> & ind, size_t size)
{
INT<3,size_t> lind = ind;
IVec<3,size_t> lind = ind;
return (113*lind[0]+59*lind[1]+lind[2]) % size;
}
@ -284,9 +300,9 @@ namespace ngcore
template <int N, typename TI>
NETGEN_INLINE size_t HashValue2 (const INT<N,TI> & ind, size_t mask)
NETGEN_INLINE constexpr size_t HashValue2 (const IVec<N,TI> & ind, size_t mask)
{
INT<N,size_t> lind = ind;
IVec<N,size_t> lind = ind;
size_t sum = 0;
for (int i = 0; i < N; i++)
sum += lind[i];
@ -295,32 +311,32 @@ namespace ngcore
/// hash value of 1 int
template <typename TI>
NETGEN_INLINE size_t HashValue2 (const INT<1,TI> & ind, size_t mask)
NETGEN_INLINE constexpr size_t HashValue2 (const IVec<1,TI> & ind, size_t mask)
{
return ind[0] & mask;
}
/// hash value of 2 int
template <typename TI>
NETGEN_INLINE size_t HashValue2 (const INT<2,TI> & ind, size_t mask)
NETGEN_INLINE constexpr size_t HashValue2 (const IVec<2,TI> & ind, size_t mask)
{
INT<2,size_t> lind = ind;
IVec<2,size_t> lind = ind;
return (113*lind[0]+lind[1]) & mask;
}
/// hash value of 3 int
template <typename TI>
NETGEN_INLINE size_t HashValue2 (const INT<3,TI> & ind, size_t mask)
NETGEN_INLINE constexpr size_t HashValue2 (const IVec<3,TI> & ind, size_t mask)
{
INT<3,size_t> lind = ind;
IVec<3,size_t> lind = ind;
return (113*lind[0]+59*lind[1]+lind[2]) & mask;
}
NETGEN_INLINE size_t HashValue2 (size_t ind, size_t mask)
NETGEN_INLINE constexpr size_t HashValue2 (size_t ind, size_t mask)
{
return ind & mask;
}
NETGEN_INLINE size_t HashValue2 (int ind, size_t mask)
NETGEN_INLINE constexpr size_t HashValue2 (int ind, size_t mask)
{
return size_t(ind) & mask;
}
@ -332,7 +348,7 @@ namespace ngcore
// using ngstd::max;
template <int D, typename T>
NETGEN_INLINE T Max (const INT<D,T> & i)
NETGEN_INLINE T Max (const IVec<D,T> & i)
{
if (D == 0) return 0;
T m = i[0];
@ -342,7 +358,7 @@ namespace ngcore
}
template <int D, typename T>
NETGEN_INLINE T Min (const INT<D,T> & i)
NETGEN_INLINE T Min (const IVec<D,T> & i)
{
if (D == 0) return 0;
T m = i[0];
@ -352,18 +368,18 @@ namespace ngcore
}
template <int D, typename T>
NETGEN_INLINE INT<D,T> Max (INT<D,T> i1, INT<D,T> i2)
NETGEN_INLINE IVec<D,T> Max (IVec<D,T> i1, IVec<D,T> i2)
{
INT<D,T> tmp;
IVec<D,T> tmp;
for (int i = 0; i < D; i++)
tmp[i] = std::max(i1[i], i2[i]);
return tmp;
}
template <int D, typename T>
NETGEN_INLINE INT<D,T> operator+ (INT<D,T> i1, INT<D,T> i2)
NETGEN_INLINE IVec<D,T> operator+ (IVec<D,T> i1, IVec<D,T> i2)
{
INT<D,T> tmp;
IVec<D,T> tmp;
for (int i = 0; i < D; i++)
tmp[i] = i1[i]+i2[i];
return tmp;
@ -575,7 +591,27 @@ namespace ngcore
return res;
}
template <typename T>
constexpr inline T InvalidHash() { return T(-1); }
template <typename T_HASH>
struct CHT_trait
{
constexpr static inline T_HASH Invalid() { return InvalidHash<T_HASH>(); }
constexpr static inline size_t HashValue (const T_HASH & hash, size_t mask) { return HashValue2(hash, mask); }
};
template <typename T1, typename T2>
struct CHT_trait<std::tuple<T1,T2>>
{
constexpr static inline std::tuple<T1,T2> Invalid() { return { CHT_trait<T1>::Invalid(), CHT_trait<T2>::Invalid() } ; }
constexpr static inline size_t HashValue (const std::tuple<T1,T2> & hash, size_t mask)
{
return (CHT_trait<T1>::HashValue(std::get<0>(hash), mask) + CHT_trait<T2>::HashValue(std::get<1>(hash),mask)) & mask;
}
};
/**
A closed hash-table.
@ -596,14 +632,18 @@ namespace ngcore
///
Array<T> cont;
///
T_HASH invalid = -1;
// T_HASH invalid = -1;
// static constexpr T_HASH invalid = InvalidHash<T_HASH>();
static constexpr T_HASH invalid = CHT_trait<T_HASH>::Invalid();
public:
///
ClosedHashTable (size_t asize = 128)
: size(RoundUp2(asize)), hash(size), cont(size)
{
mask = size-1;
hash = T_HASH(invalid);
// hash = T_HASH(invalid);
// hash = InvalidHash<T_HASH>();
hash = CHT_trait<T_HASH>::Invalid();
}
ClosedHashTable (ClosedHashTable && ht2) = default;
@ -612,7 +652,8 @@ namespace ngcore
ClosedHashTable (size_t asize, LocalHeap & lh)
: size(RoundUp2(asize)), mask(size-1), hash(size, lh), cont(size, lh)
{
hash = T_HASH(invalid);
// hash = T_HASH(invalid);
hash = InvalidHash<T_HASH>();
}
ClosedHashTable & operator= (ClosedHashTable && ht2) = default;
@ -637,7 +678,8 @@ namespace ngcore
size_t Position (const T_HASH ind) const
{
size_t i = HashValue2(ind, mask);
// size_t i = HashValue2(ind, mask);
size_t i = CHT_trait<T_HASH>::HashValue(ind, mask);
while (true)
{
if (hash[i] == ind) return i;
@ -659,7 +701,8 @@ namespace ngcore
{
if (UsedElements()*2 > Size()) DoubleSize();
size_t i = HashValue2 (ind, mask);
// size_t i = HashValue2 (ind, mask);
size_t i = CHT_trait<T_HASH>::HashValue (ind, mask);
while (true)
{
@ -704,6 +747,16 @@ namespace ngcore
return (Position (ahash) != size_t(-1));
}
inline std::optional<T> GetIfUsed (const T_HASH & ahash) const
{
size_t pos = Position (ahash);
if (pos != size_t(-1))
return cont[pos];
else
return std::nullopt;
}
void SetData (size_t pos, const T_HASH & ahash, const T & acont)
{
hash[pos] = ahash;
@ -781,6 +834,15 @@ namespace ngcore
hash = T_HASH(invalid);
used = 0;
}
template <typename ARCHIVE>
void DoArchive (ARCHIVE& ar)
{
ar & hash & cont;
ar & size & mask & used;
}
struct EndIterator { };
class Iterator
{
@ -798,24 +860,21 @@ namespace ngcore
while (nr < tab.Size() && !tab.UsedPos(nr)) nr++;
return *this;
}
bool operator!= (const Iterator & it2) { return nr != it2.nr; }
auto operator* () const
{
T_HASH hash;
T val;
tab.GetData(nr, hash,val);
return std::make_pair(hash,val);
}
bool operator!= (EndIterator it2) { return nr != tab.Size(); }
auto operator* () const { return tab.GetBoth(nr); }
};
Iterator begin() const { return Iterator(*this, 0); }
Iterator end() const { return Iterator(*this, Size()); }
EndIterator end() const { return EndIterator(); }
};
template <class T_HASH, class T>
ostream & operator<< (ostream & ost,
const ClosedHashTable<T_HASH,T> & tab)
{
/*
for (size_t i = 0; i < tab.Size(); i++)
if (tab.UsedPos(i))
{
@ -824,25 +883,28 @@ namespace ngcore
tab.GetData (i, key, val);
ost << key << ": " << val << ", ";
}
*/
for (auto [key,val] : tab)
ost << key << ": " << val << ", ";
return ost;
}
template <typename TI>
NETGEN_INLINE size_t HashValue (const INT<3,TI> ind)
NETGEN_INLINE size_t HashValue (const IVec<3,TI> ind)
{
INT<3,size_t> lind = ind;
IVec<3,size_t> lind = ind;
return 113*lind[0]+59*lind[1]+lind[2];
}
template <typename TI>
NETGEN_INLINE size_t HashValue (const INT<2,TI> ind)
NETGEN_INLINE size_t HashValue (const IVec<2,TI> ind)
{
INT<2,size_t> lind = ind;
IVec<2,size_t> lind = ind;
return 113*lind[0]+lind[1];
}
template <typename TI>
NETGEN_INLINE size_t HashValue (const INT<1,TI> ind)
NETGEN_INLINE size_t HashValue (const IVec<1,TI> ind)
{
return ind[0];
}
@ -1068,14 +1130,114 @@ namespace ngcore
return ost;
}
template <class T, class IndexType>
class CompressedTable
{
Table<T, size_t> table;
ClosedHashTable<IndexType, size_t> idmap;
public:
CompressedTable (Table<T, size_t> && atable, ClosedHashTable<IndexType, size_t> && aidmap)
: table(std::move(atable)), idmap(std::move(aidmap)) { }
FlatArray<T> operator[](IndexType id) const
{
if (auto nr = idmap.GetIfUsed(id))
return table[*nr];
else
return { 0, nullptr };
}
auto & GetTable() { return table; }
};
template <class T, typename IndexType>
class CompressedTableCreator
{
protected:
int mode; // 1 .. cnt, 2 .. cnt entries, 3 .. fill table
size_t nd; // number of entries;
ClosedHashTable<IndexType, size_t> idmap;
Array<int,size_t> cnt;
Table<T,size_t> table;
public:
CompressedTableCreator()
{ nd = 0; mode = 1; }
CompressedTable<T,IndexType> MoveTable()
{
return { std::move(table), std::move(idmap) };
}
bool Done () { return mode > 3; }
void operator++(int) { SetMode (mode+1); }
int GetMode () const { return mode; }
void SetMode (int amode)
{
mode = amode;
if (mode == 2)
{
cnt.SetSize(nd);
cnt = 0;
}
if (mode == 3)
{
table = Table<T,size_t> (cnt);
cnt = 0;
}
}
void Add (IndexType blocknr, const T & data)
{
switch (mode)
{
case 1:
{
if (!idmap.Used (blocknr))
idmap[blocknr] = nd++;
break;
}
case 2:
cnt[idmap.Get(blocknr)]++;
break;
case 3:
size_t cblock = idmap.Get(blocknr);
int ci = cnt[cblock]++;
table[cblock][ci] = data;
break;
}
}
};
} // namespace ngcore
/*
#ifdef PARALLEL
namespace ngcore {
template<int S, typename T>
class MPI_typetrait<ngcore::INT<S, T> >
class MPI_typetrait<ngcore::IVec<S, T> >
{
public:
/// gets the MPI datatype
@ -1092,6 +1254,19 @@ namespace ngcore {
};
}
#endif
*/
namespace ngcore
{
template<typename T> struct MPI_typetrait;
template<int S, typename T>
struct MPI_typetrait<IVec<S, T> > {
static auto MPIType () {
return MPI_typetrait<std::array<T,S>>::MPIType();
}
};
}
@ -1099,8 +1274,8 @@ namespace std
{
// structured binding support
template <auto N, typename T>
struct tuple_size<ngcore::INT<N,T>> : std::integral_constant<std::size_t, N> {};
template<size_t N, auto M, typename T> struct tuple_element<N,ngcore::INT<M,T>> { using type = T; };
struct tuple_size<ngcore::IVec<N,T>> : std::integral_constant<std::size_t, N> {};
template<size_t N, auto M, typename T> struct tuple_element<N,ngcore::IVec<M,T>> { using type = T; };
}
#endif

View File

@ -1,15 +1,6 @@
#include "logging.hpp"
#ifdef NETGEN_USE_SPDLOG
#include <spdlog/spdlog.h>
#include <spdlog/sinks/ansicolor_sink.h>
#include <spdlog/sinks/basic_file_sink.h>
#else // NETGEN_USE_SPDLOG
#include <iostream>
#endif // NETGEN_USE_SPDLOG
namespace ngcore
{
@ -19,94 +10,10 @@ namespace ngcore
void Logger::log(level::level_enum level, std::string && s)
{
#ifdef NETGEN_USE_SPDLOG
logger->log(spdlog::level::level_enum(level), s);
#else // NETGEN_USE_SPDLOG
if(level>=global_level)
std::clog << s << '\n';
#endif // NETGEN_USE_SPDLOG
}
#ifdef NETGEN_USE_SPDLOG
namespace detail
{
std::vector<std::shared_ptr<spdlog::sinks::sink>>& GetDefaultSinks()
{
static std::vector<std::shared_ptr<spdlog::sinks::sink>> sinks =
{ std::make_shared<spdlog::sinks::ansicolor_stdout_sink_mt>() };
return sinks;
}
std::shared_ptr<spdlog::logger> CreateDefaultLogger(const std::string& name)
{
auto& default_sinks = GetDefaultSinks();
auto logger = std::make_shared<spdlog::logger>(name, default_sinks.begin(), default_sinks.end());
spdlog::details::registry::instance().register_and_init(logger);
return logger;
}
} // namespace detail
std::shared_ptr<Logger> GetLogger(const std::string& name)
{
auto logger = spdlog::get(name);
if(!logger)
logger = detail::CreateDefaultLogger(name);
return std::make_shared<Logger>(logger);
}
void SetLoggingLevel(spdlog::level::level_enum level, const std::string& name)
{
if(!name.empty())
spdlog::get(name)->set_level(level);
else
spdlog::set_level(level);
}
void AddFileSink(const std::string& filename, spdlog::level::level_enum level, const std::string& logger)
{
auto sink = std::make_shared<spdlog::sinks::basic_file_sink_mt>(filename);
sink->set_level(level);
if(!logger.empty())
GetLogger(logger)->logger->sinks().push_back(sink);
else
{
detail::GetDefaultSinks().push_back(sink);
spdlog::details::registry::instance().apply_all([sink](auto logger) { logger->sinks().push_back(sink); });
}
}
void AddConsoleSink(spdlog::level::level_enum level, const std::string& logger)
{
auto sink = std::make_shared<spdlog::sinks::ansicolor_stdout_sink_mt>();
sink->set_level(level);
if(!logger.empty())
GetLogger(logger)->logger->sinks().push_back(sink);
else
{
detail::GetDefaultSinks().push_back(sink);
spdlog::details::registry::instance().apply_all([sink](auto logger) { logger->sinks().push_back(sink); });
}
}
void ClearLoggingSinks(const std::string& logger)
{
if(!logger.empty())
GetLogger(logger)->logger->sinks().clear();
else
{
detail::GetDefaultSinks().clear();
spdlog::details::registry::instance().apply_all([](auto logger) { logger->sinks().clear(); });
}
}
void FlushOnLoggingLevel(spdlog::level::level_enum level, const std::string& logger)
{
if(!logger.empty())
GetLogger(logger)->logger->flush_on(level);
else
spdlog::flush_on(level);
}
#else // NETGEN_USE_SPDLOG
} //namespace ngcore
namespace spdlog
@ -140,5 +47,3 @@ namespace ngcore
void ClearLoggingSinks(const std::string& /*unused*/) {}
void FlushOnLoggingLevel(level::level_enum /*unused*/, const std::string& /*unused*/) {}
} //namespace ngcore
#endif // NETGEN_USE_SPDLOG

View File

@ -1,7 +1,6 @@
#ifndef NETGEN_CORE_LOGGING_HPP
#define NETGEN_CORE_LOGGING_HPP
#undef NETGEN_USE_SPDLOG
#include <iostream>
#include <memory>
#include <string>
@ -11,15 +10,6 @@
#include "ngcore_api.hpp"
#include "utils.hpp"
#ifdef NETGEN_USE_SPDLOG
#include <spdlog/fmt/fmt.h>
#include <spdlog/fmt/ostr.h> // to be able to parse anything to logger that implements operator << ostream
#ifdef NETGEN_LOG_DEBUG
#define SPDLOG_DEBUG_ON
#define NETGEN_DEBUG_LOG(logger, ...) SPDLOG_DEBUG(logger, __VA_ARGS__)
#endif // NETGEN_LOG_DEBUG
#endif // NETGEN_USE_SPDLOG
#ifndef NETGEN_DEBUG_LOG
#define NETGEN_DEBUG_LOG(logger, ...)
#endif // NETGEN_DEBUG_LOG
@ -52,7 +42,12 @@ namespace ngcore
static NGCORE_API level::level_enum global_level;
public:
static void SetGlobalLoggingLevel( level::level_enum level ) { global_level = level; }
static auto SetGlobalLoggingLevel( level::level_enum level )
{
auto oldval = global_level;
global_level = level;
return oldval;
}
std::shared_ptr<spdlog::logger> logger;
@ -60,13 +55,6 @@ namespace ngcore
void NGCORE_API log( level::level_enum level, std::string && s);
#ifdef NETGEN_USE_SPDLOG
template<typename ... Args>
void log( level::level_enum level, const char* str, Args ... args)
{
log(level, fmt::format(str, args...));
}
#else // NETGEN_USE_SPDLOG
template<typename T>
std::string replace(std::string s, const T & t)
{
@ -100,7 +88,6 @@ namespace ngcore
{
log(level, log_helper(std::string(str), args...));
}
#endif // NETGEN_USE_SPDLOG
template<typename ... Args>
void trace( const char* str, Args ... args) { log(level::level_enum::trace, str, args...); }

View File

@ -35,11 +35,16 @@ namespace ngcore
class MemoryTracer
{
#ifdef NETGEN_TRACE_MEMORY
#if defined(NETGEN_TRACE_MEMORY) && !defined(__CUDA_ARCH__)
NGCORE_API static std::vector<std::string> names;
NGCORE_API static std::vector<int> parents;
static int CreateId(const std::string& name)
#if defined(NETGEN_CHECK_RANGE)
NGCORE_API static std::atomic<size_t> total_memory;
mutable size_t allocated_memory = 0;
#endif // NETGEN_CHECK_RANGE
static int CreateId(const std::string& name = "")
{
int id = names.size();
names.push_back(name);
@ -48,7 +53,7 @@ namespace ngcore
std::cerr << "Allocated " << id << " MemoryTracer objects" << std::endl;
return id;
}
int id;
mutable int id = 0;
public:
@ -57,8 +62,33 @@ namespace ngcore
id = CreateId(name);
}
// not tracing
MemoryTracer() : id(0) {}
MemoryTracer() { }
MemoryTracer(const MemoryTracer & tracer)
{
(*this) = tracer;
}
MemoryTracer(MemoryTracer && tracer)
{
(*this) = std::move(tracer);
}
MemoryTracer & operator=(const MemoryTracer & tracer) {
if(tracer.id)
id = CreateId(names[tracer.id]);
return *this;
}
MemoryTracer & operator=(MemoryTracer && tracer) {
ngcore::Swap(id, tracer.id);
#if defined(NETGEN_CHECK_RANGE)
ngcore::Swap(allocated_memory, tracer.allocated_memory);
#endif // NETGEN_CHECK_RANGE
return *this;
}
template <typename... TRest>
MemoryTracer( std::string name, TRest & ... rest )
@ -67,38 +97,48 @@ namespace ngcore
Track(rest...);
}
#if defined(NETGEN_CHECK_RANGE)
// check if all memory was freed when object is destroyed
~MemoryTracer()
{
NETGEN_CHECK_SAME(allocated_memory, 0);
}
#endif // NETGEN_CHECK_RANGE
NETGEN_INLINE void Alloc(size_t size) const
{
#if defined(NETGEN_CHECK_RANGE)
// Trace also nameless Memtracer objects if range checks are active
if(!id && size)
id = CreateId();
#endif // NETGEN_CHECK_RANGE
if(id && trace)
trace->AllocMemory(id, size);
#if defined(NETGEN_CHECK_RANGE)
if(id)
{
allocated_memory += size;
total_memory += size;
}
#endif // NETGEN_CHECK_RANGE
}
void Free(size_t size) const
{
if(id && trace)
trace->FreeMemory(id, size);
}
void Swap(size_t mysize, MemoryTracer& other, size_t other_size) const
{
if(!trace || (id == 0 && other.id == 0))
return;
if(id == 0)
return trace->ChangeMemory(other.id, mysize - other_size);
if(other.id == 0)
return trace->ChangeMemory(id, other_size - mysize);
// first decrease memory, otherwise have artificial/wrong high peak memory usage
if(mysize<other_size)
{
trace->ChangeMemory(other.id, mysize-other_size);
trace->ChangeMemory(id, other_size-mysize);
}
else
{
trace->ChangeMemory(id, other_size-mysize);
trace->ChangeMemory(other.id, mysize-other_size);
}
#if defined(NETGEN_CHECK_RANGE)
if(id)
{
// check if we have at least size bytes of memory currently allocated (such that allocated_memory doesn't get negative)
NETGEN_CHECK_RANGE(allocated_memory, static_cast<ptrdiff_t>(size), std::numeric_limits<ptrdiff_t>::max());
allocated_memory -= size;
total_memory -= size;
#endif // NETGEN_CHECK_RANGE
}
}
int GetId() const { return id; }
@ -148,7 +188,15 @@ namespace ngcore
static const std::vector<std::string> & GetNames() { return names; }
static const std::vector<int> & GetParents() { return parents; }
#else // NETGEN_TRACE_MEMORY
static size_t GetTotalMemory()
{
#if defined(NETGEN_CHECK_RANGE)
return total_memory;
#else
return 0;
#endif // NETGEN_CHECK_RANGE
}
#else // defined(NETGEN_TRACE_MEMORY) && !defined(__CUDA_ARCH__)
public:
MemoryTracer() {}
MemoryTracer( std::string /* name */ ) {}
@ -157,7 +205,6 @@ namespace ngcore
void Alloc(size_t /* size */) const {}
void Free(size_t /* size */) const {}
void Swap(...) const {}
int GetId() const { return 0; }
template <typename... TRest>
@ -166,6 +213,7 @@ namespace ngcore
static std::string GetName(int /* id */) { return ""; }
std::string GetName() const { return ""; }
void SetName(std::string /* name */) const {}
static size_t GetTotalMemory() { return 0; }
#endif // NETGEN_TRACE_MEMORY
};
} // namespace ngcore

245
libsrc/core/mpi4py_pycapi.h Normal file
View File

@ -0,0 +1,245 @@
/* Author: Lisandro Dalcin */
/* Contact: dalcinl@gmail.com */
#ifndef MPI4PY_PYCAPI_H
#define MPI4PY_PYCAPI_H
#include <mpi.h>
#include <Python.h>
#define _mpi4py_declare_pycapi(Type, star) \
static PyTypeObject *_mpi4py_PyMPI##Type = NULL; \
static PyObject *(*_mpi4py_PyMPI##Type##_New)(MPI_##Type star) = NULL; \
static MPI_##Type *(*_mpi4py_PyMPI##Type##_Get)(PyObject *) = NULL;
#ifndef MPI4PY_LIMITED_API_SKIP_DATATYPE
_mpi4py_declare_pycapi(Datatype,)
#define PyMPIDatatype_Type (*_mpi4py_PyMPIDatatype)
#define PyMPIDatatype_New _mpi4py_PyMPIDatatype_New
#define PyMPIDatatype_Get _mpi4py_PyMPIDatatype_Get
#endif
#ifndef MPI4PY_LIMITED_API_SKIP_STATUS
_mpi4py_declare_pycapi(Status,*)
#define PyMPIStatus_Type (*_mpi4py_PyMPIStatus)
#define PyMPIStatus_New _mpi4py_PyMPIStatus_New
#define PyMPIStatus_Get _mpi4py_PyMPIStatus_Get
#endif
#ifndef MPI4PY_LIMITED_API_SKIP_REQUEST
_mpi4py_declare_pycapi(Request,)
#define PyMPIRequest_Type (*_mpi4py_PyMPIRequest)
#define PyMPIRequest_New _mpi4py_PyMPIRequest_New
#define PyMPIRequest_Get _mpi4py_PyMPIRequest_Get
#endif
#ifndef MPI4PY_LIMITED_API_SKIP_MESSAGE
_mpi4py_declare_pycapi(Message,)
#define PyMPIMessage_Type (*_mpi4py_PyMPIMessage)
#define PyMPIMessage_New _mpi4py_PyMPIMessage_New
#define PyMPIMessage_Get _mpi4py_PyMPIMessage_Get
#endif
#ifndef MPI4PY_LIMITED_API_SKIP_OP
_mpi4py_declare_pycapi(Op,)
#define PyMPIOp_Type (*_mpi4py_PyMPIOp)
#define PyMPIOp_New _mpi4py_PyMPIOp_New
#define PyMPIOp_Get _mpi4py_PyMPIOp_Get
#endif
#ifndef MPI4PY_LIMITED_API_SKIP_GROUP
_mpi4py_declare_pycapi(Group,)
#define PyMPIGroup_Type (*_mpi4py_PyMPIGroup)
#define PyMPIGroup_New _mpi4py_PyMPIGroup_New
#define PyMPIGroup_Get _mpi4py_PyMPIGroup_Get
#endif
#ifndef MPI4PY_LIMITED_API_SKIP_INFO
_mpi4py_declare_pycapi(Info,)
#define PyMPIInfo_Type (*_mpi4py_PyMPIInfo)
#define PyMPIInfo_New _mpi4py_PyMPIInfo_New
#define PyMPIInfo_Get _mpi4py_PyMPIInfo_Get
#endif
#ifndef MPI4PY_LIMITED_API_SKIP_ERRHANDLER
_mpi4py_declare_pycapi(Errhandler,)
#define PyMPIErrhandler_Type (*_mpi4py_PyMPIErrhandler)
#define PyMPIErrhandler_New _mpi4py_PyMPIErrhandler_New
#define PyMPIErrhandler_Get _mpi4py_PyMPIErrhandler_Get
#endif
#ifndef MPI4PY_LIMITED_API_SKIP_SESSION
_mpi4py_declare_pycapi(Session,)
#define PyMPISession_Type (*_mpi4py_PyMPISession)
#define PyMPISession_New _mpi4py_PyMPISession_New
#define PyMPISession_Get _mpi4py_PyMPISession_Get
#endif
#ifndef MPI4PY_LIMITED_API_SKIP_COMM
_mpi4py_declare_pycapi(Comm,)
#define PyMPIComm_Type (*_mpi4py_PyMPIComm)
#define PyMPIComm_New _mpi4py_PyMPIComm_New
#define PyMPIComm_Get _mpi4py_PyMPIComm_Get
#endif
#ifndef MPI4PY_LIMITED_API_SKIP_WIN
_mpi4py_declare_pycapi(Win,)
#define PyMPIWin_Type (*_mpi4py_PyMPIWin)
#define PyMPIWin_New _mpi4py_PyMPIWin_New
#define PyMPIWin_Get _mpi4py_PyMPIWin_Get
#endif
#ifndef MPI4PY_LIMITED_API_SKIP_FILE
_mpi4py_declare_pycapi(File,)
#define PyMPIFile_Type (*_mpi4py_PyMPIFile)
#define PyMPIFile_New _mpi4py_PyMPIFile_New
#define PyMPIFile_Get _mpi4py_PyMPIFile_Get
#endif
#undef _mpi4py_define_pycapi
static int _mpi4py_ImportType(PyObject *module,
const char *type_name,
PyTypeObject **type)
{
PyObject *attr = NULL;
attr = PyObject_GetAttrString(module, type_name);
if (!attr)
goto fn_fail;
if (!PyType_Check(attr)) {
PyErr_Format(PyExc_TypeError,
"%.200s.%.200s is not a type object",
PyModule_GetName(module), type_name);
goto fn_fail;
}
*type = (PyTypeObject *)attr;
return 0;
fn_fail:
Py_DecRef(attr);
return -1;
}
static int _mpi4py_ImportFunc(PyObject *module,
const char *func_name,
const char *signature,
void (**func)(void))
{
PyObject *pyxcapi = NULL;
PyObject *capsule = NULL;
union { void *obj; void (*fcn)(void); } ptr;
pyxcapi = PyObject_GetAttrString(module, (char *)"__pyx_capi__");
if (!pyxcapi)
goto fn_fail;
capsule = PyDict_GetItemString(pyxcapi, func_name);
if (!capsule) {
PyErr_Format(PyExc_ImportError,
"%.200s does not export expected C function %.200s",
PyModule_GetName(module), func_name);
goto fn_fail;
}
if (!PyCapsule_CheckExact(capsule)) {
PyErr_Format(PyExc_TypeError,
"%.200s.%.200s is not a capsule",
PyModule_GetName(module), func_name);
}
if (!signature) {
signature = PyCapsule_GetName(capsule);
}
if (!PyCapsule_IsValid(capsule, signature)) {
PyErr_Format(PyExc_TypeError,
"C function %.200s.%.200s has wrong signature "
"(expected %.500s, got %.500s)",
PyModule_GetName(module), func_name,
signature, PyCapsule_GetName(capsule));
goto fn_fail;
}
ptr.obj = PyCapsule_GetPointer(capsule, signature);
if (!ptr.obj)
goto fn_fail;
*func = ptr.fcn;
Py_DecRef(pyxcapi);
return 0;
fn_fail:
Py_DecRef(pyxcapi);
return -1;
}
static int import_mpi4py_MPI(void)
{
PyObject *module = PyImport_ImportModule("mpi4py.MPI");
if (!module)
goto fn_fail;
#define _mpi4py_import_pycapi(Type) do { \
if (_mpi4py_ImportType(module, #Type, &_mpi4py_PyMPI##Type) < 0) \
goto fn_fail; \
if (_mpi4py_ImportFunc(module, "PyMPI" #Type "_New", NULL, \
(void (**)(void))&_mpi4py_PyMPI##Type##_New) < 0) \
goto fn_fail; \
if (_mpi4py_ImportFunc(module, "PyMPI" #Type "_Get", NULL, \
(void (**)(void))&_mpi4py_PyMPI##Type##_Get) < 0) \
goto fn_fail; \
} while (0)
#ifndef MPI4PY_LIMITED_API_SKIP_DATATYPE
_mpi4py_import_pycapi(Datatype);
#endif
#ifndef MPI4PY_LIMITED_API_SKIP_STATUS
_mpi4py_import_pycapi(Status);
#endif
#ifndef MPI4PY_LIMITED_API_SKIP_REQUEST
_mpi4py_import_pycapi(Request);
#endif
#ifndef MPI4PY_LIMITED_API_SKIP_MESSAGE
_mpi4py_import_pycapi(Message);
#endif
#ifndef MPI4PY_LIMITED_API_SKIP_OP
_mpi4py_import_pycapi(Op);
#endif
#ifndef MPI4PY_LIMITED_API_SKIP_GROUP
_mpi4py_import_pycapi(Group);
#endif
#ifndef MPI4PY_LIMITED_API_SKIP_INFO
_mpi4py_import_pycapi(Info);
#endif
#ifndef MPI4PY_LIMITED_API_SKIP_ERRHANDLER
_mpi4py_import_pycapi(Errhandler);
#endif
#ifndef MPI4PY_LIMITED_API_SKIP_SESSION
_mpi4py_import_pycapi(Session);
#endif
#ifndef MPI4PY_LIMITED_API_SKIP_COMM
_mpi4py_import_pycapi(Comm);
#endif
#ifndef MPI4PY_LIMITED_API_SKIP_WIN
_mpi4py_import_pycapi(Win);
#endif
#ifndef MPI4PY_LIMITED_API_SKIP_FILE
_mpi4py_import_pycapi(File);
#endif
#undef _mpi4py_import_pycapi
Py_DecRef(module);
return 0;
fn_fail:
Py_DecRef(module);
return -1;
}
#define __PYX_HAVE_API__mpi4py__MPI
#define import_mpi4py__MPI import_mpi4py_MPI
#endif /* MPI4PY_PYCAPI_H */

View File

@ -1,16 +1,16 @@
#ifndef NGCORE_MPIWRAPPER_HPP
#define NGCORE_MPIWRAPPER_HPP
#ifdef PARALLEL
#define OMPI_SKIP_MPICXX
#include <mpi.h>
#endif
#include <array>
#include <complex>
#include "array.hpp"
#include "table.hpp"
#include "exception.hpp"
#include "profiler.hpp"
#include "ngstream.hpp"
#include "ng_mpi.hpp"
namespace ngcore
{
@ -20,52 +20,124 @@ namespace ngcore
template <class T> struct MPI_typetrait { };
template <> struct MPI_typetrait<int> {
static MPI_Datatype MPIType () { return MPI_INT; } };
static NG_MPI_Datatype MPIType () { return NG_MPI_INT; } };
template <> struct MPI_typetrait<short> {
static MPI_Datatype MPIType () { return MPI_SHORT; } };
static NG_MPI_Datatype MPIType () { return NG_MPI_SHORT; } };
template <> struct MPI_typetrait<char> {
static MPI_Datatype MPIType () { return MPI_CHAR; } };
static NG_MPI_Datatype MPIType () { return NG_MPI_CHAR; } };
template <> struct MPI_typetrait<signed char> {
static MPI_Datatype MPIType () { return MPI_CHAR; } };
static NG_MPI_Datatype MPIType () { return NG_MPI_CHAR; } };
template <> struct MPI_typetrait<unsigned char> {
static MPI_Datatype MPIType () { return MPI_CHAR; } };
static NG_MPI_Datatype MPIType () { return NG_MPI_CHAR; } };
template <> struct MPI_typetrait<size_t> {
static MPI_Datatype MPIType () { return MPI_UINT64_T; } };
static NG_MPI_Datatype MPIType () { return NG_MPI_UINT64_T; } };
template <> struct MPI_typetrait<double> {
static MPI_Datatype MPIType () { return MPI_DOUBLE; } };
static NG_MPI_Datatype MPIType () { return NG_MPI_DOUBLE; } };
template <> struct MPI_typetrait<std::complex<double>> {
static NG_MPI_Datatype MPIType () { return NG_MPI_CXX_DOUBLE_COMPLEX; } };
template <> struct MPI_typetrait<bool> {
static MPI_Datatype MPIType () { return MPI_C_BOOL; } };
static NG_MPI_Datatype MPIType () { return NG_MPI_C_BOOL; } };
template<typename T, size_t S>
struct MPI_typetrait<std::array<T,S>>
{
static NG_MPI_Datatype MPIType ()
{
static NG_MPI_Datatype NG_MPI_T = 0;
if (!NG_MPI_T)
{
NG_MPI_Type_contiguous ( S, MPI_typetrait<T>::MPIType(), &NG_MPI_T);
NG_MPI_Type_commit ( &NG_MPI_T );
}
return NG_MPI_T;
}
};
template <class T, class T2 = decltype(MPI_typetrait<T>::MPIType())>
inline MPI_Datatype GetMPIType () {
inline NG_MPI_Datatype GetMPIType () {
return MPI_typetrait<T>::MPIType();
}
template <class T>
inline MPI_Datatype GetMPIType (T &) {
inline NG_MPI_Datatype GetMPIType (T &) {
return GetMPIType<T>();
}
class NgMPI_Request
{
NG_MPI_Request request;
public:
NgMPI_Request (NG_MPI_Request requ) : request{requ} { }
NgMPI_Request (const NgMPI_Request&) = delete;
NgMPI_Request (NgMPI_Request&&) = default;
~NgMPI_Request () { NG_MPI_Wait (&request, NG_MPI_STATUS_IGNORE); }
void Wait() { NG_MPI_Wait (&request, NG_MPI_STATUS_IGNORE); }
operator NG_MPI_Request() &&
{
auto tmp = request;
request = NG_MPI_REQUEST_NULL;
return tmp;
}
};
inline void MyMPI_WaitAll (FlatArray<MPI_Request> requests)
class NgMPI_Requests
{
Array<NG_MPI_Request> requests;
public:
NgMPI_Requests() = default;
~NgMPI_Requests() { WaitAll(); }
void Reset() { requests.SetSize0(); }
NgMPI_Requests & operator+= (NgMPI_Request && r)
{
requests += NG_MPI_Request(std::move(r));
return *this;
}
NgMPI_Requests & operator+= (NG_MPI_Request r)
{
requests += r;
return *this;
}
void WaitAll()
{
static Timer t("NgMPI - WaitAll"); RegionTimer reg(t);
if (!requests.Size()) return;
NG_MPI_Waitall (requests.Size(), requests.Data(), NG_MPI_STATUSES_IGNORE);
}
int WaitAny ()
{
int nr;
NG_MPI_Waitany (requests.Size(), requests.Data(), &nr, NG_MPI_STATUS_IGNORE);
return nr;
}
};
[[deprecated("use requests.WaitAll instread")]]
inline void MyMPI_WaitAll (FlatArray<NG_MPI_Request> requests)
{
static Timer t("MPI - WaitAll"); RegionTimer reg(t);
if (!requests.Size()) return;
MPI_Waitall (requests.Size(), requests.Data(), MPI_STATUSES_IGNORE);
NG_MPI_Waitall (requests.Size(), requests.Data(), NG_MPI_STATUSES_IGNORE);
}
inline int MyMPI_WaitAny (FlatArray<MPI_Request> requests)
[[deprecated("use requests.WaitAny instread")]]
inline int MyMPI_WaitAny (FlatArray<NG_MPI_Request> requests)
{
int nr;
MPI_Waitany (requests.Size(), requests.Data(), &nr, MPI_STATUS_IGNORE);
NG_MPI_Waitany (requests.Size(), requests.Data(), &nr, NG_MPI_STATUS_IGNORE);
return nr;
}
@ -74,7 +146,7 @@ namespace ngcore
class NgMPI_Comm
{
protected:
MPI_Comm comm;
NG_MPI_Comm comm;
bool valid_comm;
int * refcount;
int rank, size;
@ -83,11 +155,11 @@ namespace ngcore
: valid_comm(false), refcount(nullptr), rank(0), size(1)
{ ; }
NgMPI_Comm (MPI_Comm _comm, bool owns = false)
NgMPI_Comm (NG_MPI_Comm _comm, bool owns = false)
: comm(_comm), valid_comm(true)
{
int flag;
MPI_Initialized (&flag);
NG_MPI_Initialized (&flag);
if (!flag)
{
valid_comm = false;
@ -102,8 +174,8 @@ namespace ngcore
else
refcount = new int{1};
MPI_Comm_rank(comm, &rank);
MPI_Comm_size(comm, &size);
NG_MPI_Comm_rank(comm, &rank);
NG_MPI_Comm_size(comm, &size);
}
NgMPI_Comm (const NgMPI_Comm & c)
@ -124,7 +196,7 @@ namespace ngcore
{
if (refcount)
if (--(*refcount) == 0)
MPI_Comm_free(&comm);
NG_MPI_Comm_free(&comm);
}
bool ValidCommunicator() const
@ -136,7 +208,7 @@ namespace ngcore
{
if (refcount)
if (--(*refcount) == 0)
MPI_Comm_free(&comm);
NG_MPI_Comm_free(&comm);
refcount = c.refcount;
if (refcount) (*refcount)++;
@ -152,7 +224,7 @@ namespace ngcore
InvalidCommException() : Exception("Do not have a valid communicator") { ; }
};
operator MPI_Comm() const {
operator NG_MPI_Comm() const {
if (!valid_comm) throw InvalidCommException();
return comm;
}
@ -161,7 +233,7 @@ namespace ngcore
int Size() const { return size; }
void Barrier() const {
static Timer t("MPI - Barrier"); RegionTimer reg(t);
if (size > 1) MPI_Barrier (comm);
if (size > 1) NG_MPI_Barrier (comm);
}
@ -169,82 +241,82 @@ namespace ngcore
template<typename T, typename T2 = decltype(GetMPIType<T>())>
void Send (T & val, int dest, int tag) const {
MPI_Send (&val, 1, GetMPIType<T>(), dest, tag, comm);
NG_MPI_Send (&val, 1, GetMPIType<T>(), dest, tag, comm);
}
void Send (const std::string & s, int dest, int tag) const {
MPI_Send( const_cast<char*> (&s[0]), s.length(), MPI_CHAR, dest, tag, comm);
NG_MPI_Send( const_cast<char*> (&s[0]), s.length(), NG_MPI_CHAR, dest, tag, comm);
}
template<typename T, typename TI, typename T2 = decltype(GetMPIType<T>())>
void Send(FlatArray<T,TI> s, int dest, int tag) const {
MPI_Send (s.Data(), s.Size(), GetMPIType<T>(), dest, tag, comm);
NG_MPI_Send (s.Data(), s.Size(), GetMPIType<T>(), dest, tag, comm);
}
template<typename T, typename T2 = decltype(GetMPIType<T>())>
void Recv (T & val, int src, int tag) const {
MPI_Recv (&val, 1, GetMPIType<T>(), src, tag, comm, MPI_STATUS_IGNORE);
NG_MPI_Recv (&val, 1, GetMPIType<T>(), src, tag, comm, NG_MPI_STATUS_IGNORE);
}
void Recv (std::string & s, int src, int tag) const {
MPI_Status status;
NG_MPI_Status status;
int len;
MPI_Probe (src, tag, comm, &status);
MPI_Get_count (&status, MPI_CHAR, &len);
NG_MPI_Probe (src, tag, comm, &status);
NG_MPI_Get_count (&status, NG_MPI_CHAR, &len);
// s.assign (len, ' ');
s.resize (len);
MPI_Recv( &s[0], len, MPI_CHAR, src, tag, comm, MPI_STATUS_IGNORE);
NG_MPI_Recv( &s[0], len, NG_MPI_CHAR, src, tag, comm, NG_MPI_STATUS_IGNORE);
}
template <typename T, typename TI, typename T2 = decltype(GetMPIType<T>())>
void Recv (FlatArray <T,TI> s, int src, int tag) const {
MPI_Recv (s.Data(), s.Size(), GetMPIType<T> (), src, tag, comm, MPI_STATUS_IGNORE);
NG_MPI_Recv (s.Data(), s.Size(), GetMPIType<T> (), src, tag, comm, NG_MPI_STATUS_IGNORE);
}
template <typename T, typename TI, typename T2 = decltype(GetMPIType<T>())>
void Recv (Array <T,TI> & s, int src, int tag) const
{
MPI_Status status;
NG_MPI_Status status;
int len;
const MPI_Datatype MPI_T = GetMPIType<T> ();
MPI_Probe (src, tag, comm, &status);
MPI_Get_count (&status, MPI_T, &len);
const NG_MPI_Datatype NG_MPI_T = GetMPIType<T> ();
NG_MPI_Probe (src, tag, comm, &status);
NG_MPI_Get_count (&status, NG_MPI_T, &len);
s.SetSize (len);
MPI_Recv (s.Data(), len, MPI_T, src, tag, comm, MPI_STATUS_IGNORE);
NG_MPI_Recv (s.Data(), len, NG_MPI_T, src, tag, comm, NG_MPI_STATUS_IGNORE);
}
/** --- non-blocking P2P --- **/
template<typename T, typename T2 = decltype(GetMPIType<T>())>
MPI_Request ISend (T & val, int dest, int tag) const
{
MPI_Request request;
MPI_Isend (&val, 1, GetMPIType<T>(), dest, tag, comm, &request);
return request;
}
template<typename T, typename T2 = decltype(GetMPIType<T>())>
MPI_Request ISend (FlatArray<T> s, int dest, int tag) const
{
MPI_Request request;
MPI_Isend (s.Data(), s.Size(), GetMPIType<T>(), dest, tag, comm, &request);
return request;
}
template<typename T, typename T2 = decltype(GetMPIType<T>())>
MPI_Request IRecv (T & val, int dest, int tag) const
[[nodiscard]] NG_MPI_Request ISend (T & val, int dest, int tag) const
{
MPI_Request request;
MPI_Irecv (&val, 1, GetMPIType<T>(), dest, tag, comm, &request);
NG_MPI_Request request;
NG_MPI_Isend (&val, 1, GetMPIType<T>(), dest, tag, comm, &request);
return request;
}
template<typename T, typename T2 = decltype(GetMPIType<T>())>
MPI_Request IRecv (FlatArray<T> s, int src, int tag) const
[[nodiscard]] NG_MPI_Request ISend (FlatArray<T> s, int dest, int tag) const
{
NG_MPI_Request request;
NG_MPI_Isend (s.Data(), s.Size(), GetMPIType<T>(), dest, tag, comm, &request);
return request;
}
template<typename T, typename T2 = decltype(GetMPIType<T>())>
[[nodiscard]] NG_MPI_Request IRecv (T & val, int dest, int tag) const
{
NG_MPI_Request request;
NG_MPI_Irecv (&val, 1, GetMPIType<T>(), dest, tag, comm, &request);
return request;
}
template<typename T, typename T2 = decltype(GetMPIType<T>())>
[[nodiscard]] NG_MPI_Request IRecv (FlatArray<T> s, int src, int tag) const
{
MPI_Request request;
MPI_Irecv (s.Data(), s.Size(), GetMPIType<T>(), src, tag, comm, &request);
NG_MPI_Request request;
NG_MPI_Irecv (s.Data(), s.Size(), GetMPIType<T>(), src, tag, comm, &request);
return request;
}
@ -252,46 +324,55 @@ namespace ngcore
/** --- collectives --- **/
template <typename T, typename T2 = decltype(GetMPIType<T>())>
T Reduce (T d, const MPI_Op & op, int root = 0) const
T Reduce (T d, const NG_MPI_Op & op, int root = 0) const
{
static Timer t("MPI - Reduce"); RegionTimer reg(t);
if (size == 1) return d;
T global_d;
MPI_Reduce (&d, &global_d, 1, GetMPIType<T>(), op, root, comm);
NG_MPI_Reduce (&d, &global_d, 1, GetMPIType<T>(), op, root, comm);
return global_d;
}
template <typename T, typename T2 = decltype(GetMPIType<T>())>
T AllReduce (T d, const MPI_Op & op) const
T AllReduce (T d, const NG_MPI_Op & op) const
{
static Timer t("MPI - AllReduce"); RegionTimer reg(t);
if (size == 1) return d;
T global_d;
MPI_Allreduce ( &d, &global_d, 1, GetMPIType<T>(), op, comm);
NG_MPI_Allreduce ( &d, &global_d, 1, GetMPIType<T>(), op, comm);
return global_d;
}
template <typename T, typename T2 = decltype(GetMPIType<T>())>
void AllReduce (FlatArray<T> d, const MPI_Op & op) const
void AllReduce (FlatArray<T> d, const NG_MPI_Op & op) const
{
static Timer t("MPI - AllReduce Array"); RegionTimer reg(t);
if (size == 1) return;
MPI_Allreduce (MPI_IN_PLACE, d.Data(), d.Size(), GetMPIType<T>(), op, comm);
NG_MPI_Allreduce (NG_MPI_IN_PLACE, d.Data(), d.Size(), GetMPIType<T>(), op, comm);
}
template <typename T, typename T2 = decltype(GetMPIType<T>())>
void Bcast (T & s, int root = 0) const {
if (size == 1) return;
static Timer t("MPI - Bcast"); RegionTimer reg(t);
MPI_Bcast (&s, 1, GetMPIType<T>(), root, comm);
NG_MPI_Bcast (&s, 1, GetMPIType<T>(), root, comm);
}
template <class T, size_t S>
void Bcast (std::array<T,S> & d, int root = 0) const
{
if (size == 1) return;
if (S != 0)
NG_MPI_Bcast (&d[0], S, GetMPIType<T>(), root, comm);
}
template <class T>
void Bcast (Array<T> & d, int root = 0)
void Bcast (Array<T> & d, int root = 0) const
{
if (size == 1) return;
@ -299,7 +380,7 @@ namespace ngcore
Bcast (ds, root);
if (Rank() != root) d.SetSize (ds);
if (ds != 0)
MPI_Bcast (d.Data(), ds, GetMPIType<T>(), root, comm);
NG_MPI_Bcast (d.Data(), ds, GetMPIType<T>(), root, comm);
}
@ -309,14 +390,34 @@ namespace ngcore
int len = s.length();
Bcast (len, root);
if (rank != 0) s.resize (len);
MPI_Bcast (&s[0], len, MPI_CHAR, root, comm);
NG_MPI_Bcast (&s[0], len, NG_MPI_CHAR, root, comm);
}
template <class T, size_t S>
[[nodiscard]] NgMPI_Request IBcast (std::array<T,S> & d, int root = 0) const
{
NG_MPI_Request request;
NG_MPI_Ibcast (&d[0], S, GetMPIType<T>(), root, comm, &request);
return request;
}
template <class T>
[[nodiscard]] NgMPI_Request IBcast (FlatArray<T> d, int root = 0) const
{
NG_MPI_Request request;
int ds = d.Size();
NG_MPI_Ibcast (d.Data(), ds, GetMPIType<T>(), root, comm, &request);
return request;
}
template <typename T>
void AllToAll (FlatArray<T> send, FlatArray<T> recv) const
{
MPI_Alltoall (send.Data(), 1, GetMPIType<T>(),
recv.Data(), 1, GetMPIType<T>(), comm);
NG_MPI_Alltoall (send.Data(), 1, GetMPIType<T>(),
recv.Data(), 1, GetMPIType<T>(), comm);
}
@ -324,16 +425,16 @@ namespace ngcore
void ScatterRoot (FlatArray<T> send) const
{
if (size == 1) return;
MPI_Scatter (send.Data(), 1, GetMPIType<T>(),
MPI_IN_PLACE, -1, GetMPIType<T>(), 0, comm);
NG_MPI_Scatter (send.Data(), 1, GetMPIType<T>(),
NG_MPI_IN_PLACE, -1, GetMPIType<T>(), 0, comm);
}
template <typename T>
void Scatter (T & recv) const
{
if (size == 1) return;
MPI_Scatter (NULL, 0, GetMPIType<T>(),
&recv, 1, GetMPIType<T>(), 0, comm);
NG_MPI_Scatter (NULL, 0, GetMPIType<T>(),
&recv, 1, GetMPIType<T>(), 0, comm);
}
template <typename T>
@ -341,15 +442,15 @@ namespace ngcore
{
recv[0] = T(0);
if (size == 1) return;
MPI_Gather (MPI_IN_PLACE, 1, GetMPIType<T>(),
recv.Data(), 1, GetMPIType<T>(), 0, comm);
NG_MPI_Gather (NG_MPI_IN_PLACE, 1, GetMPIType<T>(),
recv.Data(), 1, GetMPIType<T>(), 0, comm);
}
template <typename T>
void Gather (T send) const
{
if (size == 1) return;
MPI_Gather (&send, 1, GetMPIType<T>(),
NG_MPI_Gather (&send, 1, GetMPIType<T>(),
NULL, 1, GetMPIType<T>(), 0, comm);
}
@ -362,7 +463,7 @@ namespace ngcore
recv[0] = val;
return;
}
MPI_Allgather (&val, 1, GetMPIType<T>(),
NG_MPI_Allgather (&val, 1, GetMPIType<T>(),
recv.Data(), 1, GetMPIType<T>(),
comm);
}
@ -383,16 +484,16 @@ namespace ngcore
recv_data = DynamicTable<T> (recv_sizes, true);
Array<MPI_Request> requests;
NgMPI_Requests requests;
for (int dest = 0; dest < size; dest++)
if (dest != rank && send_data[dest].Size())
requests.Append (ISend (FlatArray<T>(send_data[dest]), dest, tag));
requests += ISend (FlatArray<T>(send_data[dest]), dest, tag);
for (int dest = 0; dest < size; dest++)
if (dest != rank && recv_data[dest].Size())
requests.Append (IRecv (FlatArray<T>(recv_data[dest]), dest, tag));
requests += IRecv (FlatArray<T>(recv_data[dest]), dest, tag);
MyMPI_WaitAll (requests);
requests.WaitAll();
}
@ -401,86 +502,69 @@ namespace ngcore
NgMPI_Comm SubCommunicator (FlatArray<int> procs) const
{
MPI_Comm subcomm;
MPI_Group gcomm, gsubcomm;
MPI_Comm_group(comm, &gcomm);
MPI_Group_incl(gcomm, procs.Size(), procs.Data(), &gsubcomm);
MPI_Comm_create_group(comm, gsubcomm, 4242, &subcomm);
NG_MPI_Comm subcomm;
NG_MPI_Group gcomm, gsubcomm;
NG_MPI_Comm_group(comm, &gcomm);
NG_MPI_Group_incl(gcomm, procs.Size(), procs.Data(), &gsubcomm);
NG_MPI_Comm_create_group(comm, gsubcomm, 4242, &subcomm);
return NgMPI_Comm(subcomm, true);
}
}; // class NgMPI_Comm
class MyMPI
{
bool initialized_by_me;
public:
MyMPI(int argc, char ** argv)
{
int is_init = -1;
MPI_Initialized(&is_init);
if (!is_init)
{
MPI_Init (&argc, &argv);
initialized_by_me = true;
}
else
initialized_by_me = false;
NgMPI_Comm comm(MPI_COMM_WORLD);
NGSOStream::SetGlobalActive (comm.Rank() == 0);
if (comm.Size() > 1)
TaskManager::SetNumThreads (1);
}
~MyMPI()
{
if (initialized_by_me)
MPI_Finalize ();
}
};
#else // PARALLEL
class MPI_Comm {
class NG_MPI_Comm {
int nr;
public:
MPI_Comm (int _nr = 0) : nr(_nr) { ; }
NG_MPI_Comm (int _nr = 0) : nr(_nr) { ; }
operator int() const { return nr; }
bool operator== (MPI_Comm c2) const { return nr == c2.nr; }
bool operator== (NG_MPI_Comm c2) const { return nr == c2.nr; }
};
static MPI_Comm MPI_COMM_WORLD = 12345, MPI_COMM_NULL = 10000;
static NG_MPI_Comm NG_MPI_COMM_WORLD = 12345, NG_MPI_COMM_NULL = 10000;
typedef int MPI_Op;
typedef int MPI_Datatype;
typedef int MPI_Request;
typedef int NG_MPI_Op;
typedef int NG_MPI_Datatype;
typedef int NG_MPI_Request;
enum { MPI_SUM = 0, MPI_MIN = 1, MPI_MAX = 2, MPI_LOR = 4711 };
enum { NG_MPI_SUM = 0, NG_MPI_MIN = 1, NG_MPI_MAX = 2, NG_MPI_LOR = 4711 };
inline void MPI_Type_contiguous ( int, MPI_Datatype, MPI_Datatype*) { ; }
inline void MPI_Type_commit ( MPI_Datatype * ) { ; }
inline void NG_MPI_Type_contiguous ( int, NG_MPI_Datatype, NG_MPI_Datatype*) { ; }
inline void NG_MPI_Type_commit ( NG_MPI_Datatype * ) { ; }
template <class T> struct MPI_typetrait {
static NG_MPI_Datatype MPIType () { return -1; }
};
template <class T, class T2=void>
inline NG_MPI_Datatype GetMPIType () { return -1; }
class NgMPI_Request {
public:
NgMPI_Request() = default;
NgMPI_Request(NgMPI_Request &&) { ; }
NgMPI_Request(NG_MPI_Request &&) { ; }
};
class NgMPI_Requests
{
public:
NgMPI_Requests & operator+= (NgMPI_Request &&) { return *this; }
NgMPI_Requests & operator+= (NG_MPI_Request r) { return *this; }
void Reset() { ; }
void WaitAll() { ; }
int WaitAny() { return 0; }
};
class NgMPI_Comm
{
public:
NgMPI_Comm () { ; }
NgMPI_Comm (MPI_Comm _comm, bool owns = false) { ; }
NgMPI_Comm (NG_MPI_Comm _comm, bool owns = false) { ; }
size_t Rank() const { return 0; }
size_t Size() const { return 1; }
bool ValidCommunicator() const { return false; }
void Barrier() const { ; }
operator MPI_Comm() const { return MPI_Comm(); }
operator NG_MPI_Comm() const { return NG_MPI_Comm(); }
template<typename T>
void Send( T & val, int dest, int tag) const { ; }
@ -498,32 +582,41 @@ namespace ngcore
void Recv (Array <T> & s, int src, int tag) const { ; }
template<typename T>
MPI_Request ISend (T & val, int dest, int tag) const { return 0; }
NG_MPI_Request ISend (T & val, int dest, int tag) const { return 0; }
template<typename T>
MPI_Request ISend (FlatArray<T> s, int dest, int tag) const { return 0; }
NG_MPI_Request ISend (FlatArray<T> s, int dest, int tag) const { return 0; }
template<typename T>
MPI_Request IRecv (T & val, int dest, int tag) const { return 0; }
NG_MPI_Request IRecv (T & val, int dest, int tag) const { return 0; }
template<typename T>
MPI_Request IRecv (FlatArray<T> s, int src, int tag) const { return 0; }
NG_MPI_Request IRecv (FlatArray<T> s, int src, int tag) const { return 0; }
template <typename T>
T Reduce (T d, const MPI_Op & op, int root = 0) const { return d; }
T Reduce (T d, const NG_MPI_Op & op, int root = 0) const { return d; }
template <typename T>
T AllReduce (T d, const MPI_Op & op) const { return d; }
T AllReduce (T d, const NG_MPI_Op & op) const { return d; }
template <typename T>
void AllReduce (FlatArray<T> d, const MPI_Op & op) const { ; }
void AllReduce (FlatArray<T> d, const NG_MPI_Op & op) const { ; }
template <typename T>
void Bcast (T & s, int root = 0) const { ; }
template <class T, size_t S>
void Bcast (std::array<T,S> & d, int root = 0) const {}
template <class T>
void Bcast (Array<T> & d, int root = 0) { ; }
void Bcast (Array<T> & d, int root = 0) const { ; }
template <class T, size_t S>
NG_MPI_Request IBcast (std::array<T,S> & d, int root = 0) const { return 0; }
template <class T>
NG_MPI_Request IBcast (FlatArray<T> d, int root = 0) const { return 0; }
template <typename T>
void AllGather (T val, FlatArray<T> recv) const
{
@ -539,16 +632,9 @@ namespace ngcore
{ return *this; }
};
inline void MyMPI_WaitAll (FlatArray<MPI_Request> requests) { ; }
inline int MyMPI_WaitAny (FlatArray<MPI_Request> requests) { return 0; }
inline void MyMPI_WaitAll (FlatArray<NG_MPI_Request> requests) { ; }
inline int MyMPI_WaitAny (FlatArray<NG_MPI_Request> requests) { return 0; }
class MyMPI
{
public:
MyMPI(int argc, char ** argv) { ; }
};
#endif // PARALLEL
} // namespace ngcore

184
libsrc/core/ng_mpi.cpp Normal file
View File

@ -0,0 +1,184 @@
#define OMPI_SKIP_MPICXX
#include <mpi.h>
#include "ng_mpi.hpp"
#include <type_traits>
#include "array.hpp"
#include "ngcore_api.hpp"
#ifdef NG_PYTHON
#include "pybind11/pytypes.h"
#include "python_ngcore.hpp"
#define MPI4PY_LIMITED_API 1
#define MPI4PY_LIMITED_API_SKIP_MESSAGE 1
#define MPI4PY_LIMITED_API_SKIP_SESSION 1
#include "mpi4py_pycapi.h" // mpi4py < 4.0.0
#endif
#ifdef MSMPI_VER
int MPI_Comm_create_group(MPI_Comm arg0, MPI_Group arg1, int arg2,
MPI_Comm* arg3) {
throw std::runtime_error(
"MPI_Comm_create_group not supported on Microsoft MPI");
}
static MPI_Datatype MPI_CXX_DOUBLE_COMPLEX;
#endif // MSMPI_VER
namespace ngcore {
static_assert(sizeof(MPI_Status) <= sizeof(NG_MPI_Status), "Size mismatch");
static_assert(alignof(MPI_Status) <= alignof(NG_MPI_Status), "Size mismatch");
int mpi2ng(int value) { return value; }
void* mpi2ng(void* ptr) { return ptr; }
NG_MPI_Status* mpi2ng(MPI_Status* status) {
return reinterpret_cast<NG_MPI_Status*>(status);
}
#if !defined(MPICH) && !defined(MSMPI_VER)
NG_MPI_Comm mpi2ng(MPI_Comm comm) { return reinterpret_cast<uintptr_t>(comm); }
#endif
template <size_t size, size_t stride>
void gather_strided_array(size_t count, char* data) {
static_assert(size <= stride, "Size must be less than or equal to stride");
if constexpr (size < stride) {
char* dst = data;
char* src = data;
for ( [[maybe_unused]] auto i : Range(count)) {
memcpy(dst, src, size);
dst += size;
src += stride;
}
}
}
template <typename T>
T cast_ng2mpi(uintptr_t obj) {
if constexpr (std::is_pointer_v<T>)
return reinterpret_cast<T>(obj);
else
return static_cast<T>(obj);
}
template <typename T>
T cast_ng2mpi(uintptr_t* ptr) {
if constexpr (std::is_pointer_v<T>)
return reinterpret_cast<T>(ptr);
else
return static_cast<T>(ptr);
}
template <typename T, typename TSrc>
T* cast_ng2mpi(TSrc* ptr, int count) {
gather_strided_array<sizeof(T), sizeof(TSrc)>(count,
reinterpret_cast<char*>(ptr));
return reinterpret_cast<T*>(ptr);
}
MPI_Comm ng2mpi(NG_MPI_Comm comm) {
static_assert(sizeof(MPI_Comm) <= sizeof(comm.value), "Size mismatch");
static_assert(alignof(MPI_Comm) <= alignof(NG_MPI_Comm), "Size mismatch");
return cast_ng2mpi<MPI_Comm>(comm.value);
}
MPI_Group ng2mpi(NG_MPI_Group group) {
static_assert(sizeof(MPI_Group) <= sizeof(group.value), "Size mismatch");
static_assert(alignof(MPI_Group) <= alignof(NG_MPI_Group), "Size mismatch");
return cast_ng2mpi<MPI_Group>(group.value);
}
MPI_Comm* ng2mpi(NG_MPI_Comm* comm) {
return cast_ng2mpi<MPI_Comm*>(&comm->value);
}
MPI_Group* ng2mpi(NG_MPI_Group* group) {
return cast_ng2mpi<MPI_Group*>(&group->value);
}
MPI_Datatype* ng2mpi(NG_MPI_Datatype* type) {
return cast_ng2mpi<MPI_Datatype*>(&type->value);
}
MPI_Datatype* ng2mpi(NG_MPI_Datatype* type, int count) {
return cast_ng2mpi<MPI_Datatype>(&type->value, count);
}
MPI_Request* ng2mpi(NG_MPI_Request* request) {
return cast_ng2mpi<MPI_Request*>(&request->value);
}
MPI_Request* ng2mpi(NG_MPI_Request* request, int count) {
return cast_ng2mpi<MPI_Request>(&request->value, count);
}
MPI_Status* ng2mpi(NG_MPI_Status* status) {
return reinterpret_cast<MPI_Status*>(status);
}
MPI_Aint* ng2mpi(NG_MPI_Aint* aint) {
return reinterpret_cast<MPI_Aint*>(aint);
}
MPI_Aint* ng2mpi(NG_MPI_Aint* aint, int count) {
return cast_ng2mpi<MPI_Aint>(aint, count);
}
MPI_Datatype ng2mpi(NG_MPI_Datatype type) {
static_assert(sizeof(MPI_Datatype) <= sizeof(type.value), "Size mismatch");
return cast_ng2mpi<MPI_Datatype>(type.value);
}
MPI_Request ng2mpi(NG_MPI_Request request) {
static_assert(sizeof(MPI_Request) <= sizeof(request.value), "Size mismatch");
return cast_ng2mpi<MPI_Request>(request.value);
}
MPI_Op ng2mpi(NG_MPI_Op op) {
static_assert(sizeof(MPI_Op) <= sizeof(op.value), "Size mismatch");
return cast_ng2mpi<MPI_Op>(op.value);
}
MPI_Aint ng2mpi(NG_MPI_Aint aint) {
static_assert(sizeof(MPI_Aint) <= sizeof(aint.value), "Size mismatch");
return cast_ng2mpi<MPI_Aint>(aint.value);
}
void* ng2mpi(void* ptr) { return ptr; }
char* ng2mpi(char* ptr) { return ptr; }
char*** ng2mpi(char*** ptr) { return ptr; }
int* ng2mpi(int* ptr) { return ptr; }
int ng2mpi(int value) { return value; }
} // namespace ngcore
using namespace ngcore;
extern "C" {
NGCORE_API_EXPORT void ng_init_mpi();
}
static bool imported_mpi4py = false;
void ng_init_mpi() {
#ifdef NG_PYTHON
NG_MPI_CommFromMPI4Py = [](py::handle src, NG_MPI_Comm& dst) -> bool {
if (!imported_mpi4py) {
import_mpi4py__MPI();
imported_mpi4py = true;
}
PyObject* py_src = src.ptr();
[[maybe_unused]] auto type = Py_TYPE(py_src);
if (PyObject_TypeCheck(py_src, &PyMPIComm_Type)) {
dst = mpi2ng(*PyMPIComm_Get(py_src));
return !PyErr_Occurred();
}
return false;
};
NG_MPI_CommToMPI4Py = [](NG_MPI_Comm src) -> py::handle {
if (!imported_mpi4py) {
import_mpi4py__MPI();
imported_mpi4py = true;
}
return py::handle(PyMPIComm_New(ng2mpi(src)));
};
#endif // NG_PYTHON
#include "ng_mpi_generated_init.hpp"
}

94
libsrc/core/ng_mpi.hpp Normal file
View File

@ -0,0 +1,94 @@
#ifndef NG_MPI_HPP_INCLUDED
#define NG_MPI_HPP_INCLUDED
#ifdef PARALLEL
#include <cstdint>
#include <filesystem>
#include <optional>
#include "ngcore_api.hpp"
#ifndef NG_MPI_WRAPPER
#define OMPI_SKIP_MPICXX
#include <mpi.h>
#endif // NG_MPI_WRAPPER
namespace ngcore {
NGCORE_API bool MPI_Loaded();
NGCORE_API void InitMPI(
std::optional<std::filesystem::path> mpi_lib_path = std::nullopt);
#ifdef NG_MPI_WRAPPER
inline void not_implemented() { throw std::runtime_error("Not implemented"); }
struct NG_MPI_Status {
uintptr_t data[4];
};
struct NG_MPI_Comm {
uintptr_t value;
NG_MPI_Comm() { value = 0; }
NG_MPI_Comm(uintptr_t value_) : value(value_) {}
NG_MPI_Comm(const NG_MPI_Comm &comm) : value(comm.value) {}
void operator=(int value_) { value = value_; }
void operator=(uintptr_t value_) { value = value_; }
bool operator==(const NG_MPI_Comm &comm) const { return value == comm.value; }
bool operator!=(const NG_MPI_Comm &comm) const { return value != comm.value; }
};
struct NG_MPI_Datatype {
uintptr_t value = 0;
NG_MPI_Datatype() = default;
NG_MPI_Datatype(uintptr_t value_) : value(value_) {}
operator bool() const { return value != 0; }
void operator=(NG_MPI_Datatype type) { value = type.value; }
void operator=(uintptr_t value_) { value = value_; }
void operator=(void *value_) { value = reinterpret_cast<uintptr_t>(value_); }
};
struct NG_MPI_Request {
uintptr_t value = 0;
NG_MPI_Request() = default;
NG_MPI_Request(uintptr_t value_) : value(value_) {}
void operator=(uintptr_t value_) { value = value_; }
void operator=(void *value_) { value = reinterpret_cast<uintptr_t>(value_); }
};
struct NG_MPI_Op {
uintptr_t value;
NG_MPI_Op(uintptr_t value_) : value(value_) {}
void operator=(uintptr_t value_) { value = value_; }
void operator=(void *value_) { value = reinterpret_cast<uintptr_t>(value_); }
};
struct NG_MPI_Group {
uintptr_t value = 0;
NG_MPI_Group(uintptr_t value_) : value(value_) {}
NG_MPI_Group() = default;
};
struct NG_MPI_Aint {
intptr_t value = 0;
NG_MPI_Aint(intptr_t value_) : value(value_) {}
NG_MPI_Aint() = default;
};
#else // NG_MPI_WRAPPER
using NG_MPI_Comm = MPI_Comm;
using NG_MPI_Status = MPI_Status;
using NG_MPI_Datatype = MPI_Datatype;
using NG_MPI_Request = MPI_Request;
using NG_MPI_Op = MPI_Op;
using NG_MPI_Group = MPI_Group;
using NG_MPI_Aint = MPI_Aint;
#endif // NG_MPI_WRAPPER
#include "ng_mpi_generated_declarations.hpp"
} // namespace ngcore
#endif // PARALLEL
#endif // NG_MPI_HPP_INCLUDED

View File

@ -0,0 +1,155 @@
#ifdef NG_MPI_WRAPPER
NGCORE_API extern double (*NG_MPI_Wtime)();
NGCORE_API extern int (*NG_MPI_Allgather)(void*, int, NG_MPI_Datatype, void*, int, NG_MPI_Datatype, NG_MPI_Comm);
NGCORE_API extern int (*NG_MPI_Allreduce)(void*, void*, int, NG_MPI_Datatype, NG_MPI_Op, NG_MPI_Comm);
NGCORE_API extern int (*NG_MPI_Alltoall)(void*, int, NG_MPI_Datatype, void*, int, NG_MPI_Datatype, NG_MPI_Comm);
NGCORE_API extern int (*NG_MPI_Barrier)(NG_MPI_Comm);
NGCORE_API extern int (*NG_MPI_Bcast)(void*, int, NG_MPI_Datatype, int, NG_MPI_Comm);
NGCORE_API extern int (*NG_MPI_Ibcast)(void*, int, NG_MPI_Datatype, int, NG_MPI_Comm, NG_MPI_Request*);
NGCORE_API extern int (*NG_MPI_Comm_c2f)(NG_MPI_Comm);
NGCORE_API extern int (*NG_MPI_Comm_create)(NG_MPI_Comm, NG_MPI_Group, NG_MPI_Comm*);
NGCORE_API extern int (*NG_MPI_Comm_create_group)(NG_MPI_Comm, NG_MPI_Group, int, NG_MPI_Comm*);
NGCORE_API extern int (*NG_MPI_Comm_free)(NG_MPI_Comm*);
NGCORE_API extern int (*NG_MPI_Comm_group)(NG_MPI_Comm, NG_MPI_Group*);
NGCORE_API extern int (*NG_MPI_Comm_rank)(NG_MPI_Comm, int*);
NGCORE_API extern int (*NG_MPI_Comm_size)(NG_MPI_Comm, int*);
NGCORE_API extern int (*NG_MPI_Finalize)();
NGCORE_API extern int (*NG_MPI_Gather)(void*, int, NG_MPI_Datatype, void*, int, NG_MPI_Datatype, int, NG_MPI_Comm);
NGCORE_API extern int (*NG_MPI_Gatherv)(void*, int, NG_MPI_Datatype, void*, int*, int*, NG_MPI_Datatype, int, NG_MPI_Comm);
NGCORE_API extern int (*NG_MPI_Get_count)(NG_MPI_Status*, NG_MPI_Datatype, int*);
NGCORE_API extern int (*NG_MPI_Get_processor_name)(char*, int*);
NGCORE_API extern int (*NG_MPI_Group_incl)(NG_MPI_Group, int, int*, NG_MPI_Group*);
NGCORE_API extern int (*NG_MPI_Init)(int*, char***);
NGCORE_API extern int (*NG_MPI_Init_thread)(int*, char***, int, int*);
NGCORE_API extern int (*NG_MPI_Initialized)(int*);
NGCORE_API extern int (*NG_MPI_Iprobe)(int, int, NG_MPI_Comm, int*, NG_MPI_Status*);
NGCORE_API extern int (*NG_MPI_Irecv)(void*, int, NG_MPI_Datatype, int, int, NG_MPI_Comm, NG_MPI_Request*);
NGCORE_API extern int (*NG_MPI_Isend)(void*, int, NG_MPI_Datatype, int, int, NG_MPI_Comm, NG_MPI_Request*);
NGCORE_API extern int (*NG_MPI_Probe)(int, int, NG_MPI_Comm, NG_MPI_Status*);
NGCORE_API extern int (*NG_MPI_Query_thread)(int*);
NGCORE_API extern int (*NG_MPI_Recv)(void*, int, NG_MPI_Datatype, int, int, NG_MPI_Comm, NG_MPI_Status*);
NGCORE_API extern int (*NG_MPI_Recv_init)(void*, int, NG_MPI_Datatype, int, int, NG_MPI_Comm, NG_MPI_Request*);
NGCORE_API extern int (*NG_MPI_Reduce)(void*, void*, int, NG_MPI_Datatype, NG_MPI_Op, int, NG_MPI_Comm);
NGCORE_API extern int (*NG_MPI_Reduce_local)(void*, void*, int, NG_MPI_Datatype, NG_MPI_Op);
NGCORE_API extern int (*NG_MPI_Request_free)(NG_MPI_Request*);
NGCORE_API extern int (*NG_MPI_Scatter)(void*, int, NG_MPI_Datatype, void*, int, NG_MPI_Datatype, int, NG_MPI_Comm);
NGCORE_API extern int (*NG_MPI_Send)(void*, int, NG_MPI_Datatype, int, int, NG_MPI_Comm);
NGCORE_API extern int (*NG_MPI_Send_init)(void*, int, NG_MPI_Datatype, int, int, NG_MPI_Comm, NG_MPI_Request*);
NGCORE_API extern int (*NG_MPI_Startall)(int, NG_MPI_Request*);
NGCORE_API extern int (*NG_MPI_Type_commit)(NG_MPI_Datatype*);
NGCORE_API extern int (*NG_MPI_Type_contiguous)(int, NG_MPI_Datatype, NG_MPI_Datatype*);
NGCORE_API extern int (*NG_MPI_Type_create_resized)(NG_MPI_Datatype, NG_MPI_Aint, NG_MPI_Aint, NG_MPI_Datatype*);
NGCORE_API extern int (*NG_MPI_Type_create_struct)(int, int*, NG_MPI_Aint*, NG_MPI_Datatype*, NG_MPI_Datatype*);
NGCORE_API extern int (*NG_MPI_Type_free)(NG_MPI_Datatype*);
NGCORE_API extern int (*NG_MPI_Type_get_extent)(NG_MPI_Datatype, NG_MPI_Aint*, NG_MPI_Aint*);
NGCORE_API extern int (*NG_MPI_Type_indexed)(int, int*, int*, NG_MPI_Datatype, NG_MPI_Datatype*);
NGCORE_API extern int (*NG_MPI_Type_size)(NG_MPI_Datatype, int*);
NGCORE_API extern int (*NG_MPI_Wait)(NG_MPI_Request*, NG_MPI_Status*);
NGCORE_API extern int (*NG_MPI_Waitall)(int, NG_MPI_Request*, NG_MPI_Status*);
NGCORE_API extern int (*NG_MPI_Waitany)(int, NG_MPI_Request*, int*, NG_MPI_Status*);
NGCORE_API extern NG_MPI_Comm NG_MPI_COMM_NULL;
NGCORE_API extern NG_MPI_Comm NG_MPI_COMM_WORLD;
NGCORE_API extern NG_MPI_Datatype NG_MPI_CHAR;
NGCORE_API extern NG_MPI_Datatype NG_MPI_CXX_DOUBLE_COMPLEX;
NGCORE_API extern NG_MPI_Datatype NG_MPI_C_BOOL;
NGCORE_API extern NG_MPI_Datatype NG_MPI_DATATYPE_NULL;
NGCORE_API extern NG_MPI_Datatype NG_MPI_DOUBLE;
NGCORE_API extern NG_MPI_Datatype NG_MPI_FLOAT;
NGCORE_API extern NG_MPI_Datatype NG_MPI_INT;
NGCORE_API extern NG_MPI_Datatype NG_MPI_SHORT;
NGCORE_API extern NG_MPI_Datatype NG_MPI_UINT64_T;
NGCORE_API extern NG_MPI_Op NG_MPI_LOR;
NGCORE_API extern NG_MPI_Op NG_MPI_MAX;
NGCORE_API extern NG_MPI_Op NG_MPI_MIN;
NGCORE_API extern NG_MPI_Op NG_MPI_SUM;
NGCORE_API extern NG_MPI_Request NG_MPI_REQUEST_NULL;
NGCORE_API extern NG_MPI_Status* NG_MPI_STATUSES_IGNORE;
NGCORE_API extern NG_MPI_Status* NG_MPI_STATUS_IGNORE;
NGCORE_API extern int NG_MPI_ANY_SOURCE;
NGCORE_API extern int NG_MPI_ANY_TAG;
NGCORE_API extern int NG_MPI_MAX_PROCESSOR_NAME;
NGCORE_API extern int NG_MPI_PROC_NULL;
NGCORE_API extern int NG_MPI_ROOT;
NGCORE_API extern int NG_MPI_SUBVERSION;
NGCORE_API extern int NG_MPI_THREAD_MULTIPLE;
NGCORE_API extern int NG_MPI_THREAD_SINGLE;
NGCORE_API extern int NG_MPI_VERSION;
NGCORE_API extern void* NG_MPI_IN_PLACE;
#else // NG_MPI_WRAPPER
#define NG_MPI_Wtime MPI_Wtime
#define NG_MPI_Allgather MPI_Allgather
#define NG_MPI_Allreduce MPI_Allreduce
#define NG_MPI_Alltoall MPI_Alltoall
#define NG_MPI_Barrier MPI_Barrier
#define NG_MPI_Bcast MPI_Bcast
#define NG_MPI_Ibcast MPI_Ibcast
#define NG_MPI_Comm_c2f MPI_Comm_c2f
#define NG_MPI_Comm_create MPI_Comm_create
#define NG_MPI_Comm_create_group MPI_Comm_create_group
#define NG_MPI_Comm_free MPI_Comm_free
#define NG_MPI_Comm_group MPI_Comm_group
#define NG_MPI_Comm_rank MPI_Comm_rank
#define NG_MPI_Comm_size MPI_Comm_size
#define NG_MPI_Finalize MPI_Finalize
#define NG_MPI_Gather MPI_Gather
#define NG_MPI_Gatherv MPI_Gatherv
#define NG_MPI_Get_count MPI_Get_count
#define NG_MPI_Get_processor_name MPI_Get_processor_name
#define NG_MPI_Group_incl MPI_Group_incl
#define NG_MPI_Init MPI_Init
#define NG_MPI_Init_thread MPI_Init_thread
#define NG_MPI_Initialized MPI_Initialized
#define NG_MPI_Iprobe MPI_Iprobe
#define NG_MPI_Irecv MPI_Irecv
#define NG_MPI_Isend MPI_Isend
#define NG_MPI_Probe MPI_Probe
#define NG_MPI_Query_thread MPI_Query_thread
#define NG_MPI_Recv MPI_Recv
#define NG_MPI_Recv_init MPI_Recv_init
#define NG_MPI_Reduce MPI_Reduce
#define NG_MPI_Reduce_local MPI_Reduce_local
#define NG_MPI_Request_free MPI_Request_free
#define NG_MPI_Scatter MPI_Scatter
#define NG_MPI_Send MPI_Send
#define NG_MPI_Send_init MPI_Send_init
#define NG_MPI_Startall MPI_Startall
#define NG_MPI_Type_commit MPI_Type_commit
#define NG_MPI_Type_contiguous MPI_Type_contiguous
#define NG_MPI_Type_create_resized MPI_Type_create_resized
#define NG_MPI_Type_create_struct MPI_Type_create_struct
#define NG_MPI_Type_free MPI_Type_free
#define NG_MPI_Type_get_extent MPI_Type_get_extent
#define NG_MPI_Type_indexed MPI_Type_indexed
#define NG_MPI_Type_size MPI_Type_size
#define NG_MPI_Wait MPI_Wait
#define NG_MPI_Waitall MPI_Waitall
#define NG_MPI_Waitany MPI_Waitany
#define NG_MPI_COMM_NULL MPI_COMM_NULL
#define NG_MPI_COMM_WORLD MPI_COMM_WORLD
#define NG_MPI_CHAR MPI_CHAR
#define NG_MPI_CXX_DOUBLE_COMPLEX MPI_CXX_DOUBLE_COMPLEX
#define NG_MPI_C_BOOL MPI_C_BOOL
#define NG_MPI_DATATYPE_NULL MPI_DATATYPE_NULL
#define NG_MPI_DOUBLE MPI_DOUBLE
#define NG_MPI_FLOAT MPI_FLOAT
#define NG_MPI_INT MPI_INT
#define NG_MPI_SHORT MPI_SHORT
#define NG_MPI_UINT64_T MPI_UINT64_T
#define NG_MPI_LOR MPI_LOR
#define NG_MPI_MAX MPI_MAX
#define NG_MPI_MIN MPI_MIN
#define NG_MPI_SUM MPI_SUM
#define NG_MPI_REQUEST_NULL MPI_REQUEST_NULL
#define NG_MPI_STATUSES_IGNORE MPI_STATUSES_IGNORE
#define NG_MPI_STATUS_IGNORE MPI_STATUS_IGNORE
#define NG_MPI_ANY_SOURCE MPI_ANY_SOURCE
#define NG_MPI_ANY_TAG MPI_ANY_TAG
#define NG_MPI_MAX_PROCESSOR_NAME MPI_MAX_PROCESSOR_NAME
#define NG_MPI_PROC_NULL MPI_PROC_NULL
#define NG_MPI_ROOT MPI_ROOT
#define NG_MPI_SUBVERSION MPI_SUBVERSION
#define NG_MPI_THREAD_MULTIPLE MPI_THREAD_MULTIPLE
#define NG_MPI_THREAD_SINGLE MPI_THREAD_SINGLE
#define NG_MPI_VERSION MPI_VERSION
#define NG_MPI_IN_PLACE MPI_IN_PLACE
#endif // NG_MPI_WRAPPER

View File

@ -0,0 +1,76 @@
decltype(NG_MPI_Wtime) NG_MPI_Wtime = []()->double { throw no_mpi(); };
decltype(NG_MPI_Allgather) NG_MPI_Allgather = [](void*, int, NG_MPI_Datatype, void*, int, NG_MPI_Datatype, NG_MPI_Comm)->int { throw no_mpi(); };
decltype(NG_MPI_Allreduce) NG_MPI_Allreduce = [](void*, void*, int, NG_MPI_Datatype, NG_MPI_Op, NG_MPI_Comm)->int { throw no_mpi(); };
decltype(NG_MPI_Alltoall) NG_MPI_Alltoall = [](void*, int, NG_MPI_Datatype, void*, int, NG_MPI_Datatype, NG_MPI_Comm)->int { throw no_mpi(); };
decltype(NG_MPI_Barrier) NG_MPI_Barrier = [](NG_MPI_Comm)->int { throw no_mpi(); };
decltype(NG_MPI_Bcast) NG_MPI_Bcast = [](void*, int, NG_MPI_Datatype, int, NG_MPI_Comm)->int { throw no_mpi(); };
decltype(NG_MPI_Ibcast) NG_MPI_Ibcast = [](void*, int, NG_MPI_Datatype, int, NG_MPI_Comm, NG_MPI_Request*)->int { throw no_mpi(); };
decltype(NG_MPI_Comm_c2f) NG_MPI_Comm_c2f = [](NG_MPI_Comm)->int { throw no_mpi(); };
decltype(NG_MPI_Comm_create) NG_MPI_Comm_create = [](NG_MPI_Comm, NG_MPI_Group, NG_MPI_Comm*)->int { throw no_mpi(); };
decltype(NG_MPI_Comm_create_group) NG_MPI_Comm_create_group = [](NG_MPI_Comm, NG_MPI_Group, int, NG_MPI_Comm*)->int { throw no_mpi(); };
decltype(NG_MPI_Comm_free) NG_MPI_Comm_free = [](NG_MPI_Comm*)->int { throw no_mpi(); };
decltype(NG_MPI_Comm_group) NG_MPI_Comm_group = [](NG_MPI_Comm, NG_MPI_Group*)->int { throw no_mpi(); };
decltype(NG_MPI_Comm_rank) NG_MPI_Comm_rank = [](NG_MPI_Comm, int*)->int { throw no_mpi(); };
decltype(NG_MPI_Comm_size) NG_MPI_Comm_size = [](NG_MPI_Comm, int*)->int { throw no_mpi(); };
decltype(NG_MPI_Finalize) NG_MPI_Finalize = []()->int { throw no_mpi(); };
decltype(NG_MPI_Gather) NG_MPI_Gather = [](void*, int, NG_MPI_Datatype, void*, int, NG_MPI_Datatype, int, NG_MPI_Comm)->int { throw no_mpi(); };
decltype(NG_MPI_Gatherv) NG_MPI_Gatherv = [](void*, int, NG_MPI_Datatype, void*, int*, int*, NG_MPI_Datatype, int, NG_MPI_Comm)->int { throw no_mpi(); };
decltype(NG_MPI_Get_count) NG_MPI_Get_count = [](NG_MPI_Status*, NG_MPI_Datatype, int*)->int { throw no_mpi(); };
decltype(NG_MPI_Get_processor_name) NG_MPI_Get_processor_name = [](char*, int*)->int { throw no_mpi(); };
decltype(NG_MPI_Group_incl) NG_MPI_Group_incl = [](NG_MPI_Group, int, int*, NG_MPI_Group*)->int { throw no_mpi(); };
decltype(NG_MPI_Init) NG_MPI_Init = [](int*, char***)->int { throw no_mpi(); };
decltype(NG_MPI_Init_thread) NG_MPI_Init_thread = [](int*, char***, int, int*)->int { throw no_mpi(); };
decltype(NG_MPI_Initialized) NG_MPI_Initialized = [](int*)->int { throw no_mpi(); };
decltype(NG_MPI_Iprobe) NG_MPI_Iprobe = [](int, int, NG_MPI_Comm, int*, NG_MPI_Status*)->int { throw no_mpi(); };
decltype(NG_MPI_Irecv) NG_MPI_Irecv = [](void*, int, NG_MPI_Datatype, int, int, NG_MPI_Comm, NG_MPI_Request*)->int { throw no_mpi(); };
decltype(NG_MPI_Isend) NG_MPI_Isend = [](void*, int, NG_MPI_Datatype, int, int, NG_MPI_Comm, NG_MPI_Request*)->int { throw no_mpi(); };
decltype(NG_MPI_Probe) NG_MPI_Probe = [](int, int, NG_MPI_Comm, NG_MPI_Status*)->int { throw no_mpi(); };
decltype(NG_MPI_Query_thread) NG_MPI_Query_thread = [](int*)->int { throw no_mpi(); };
decltype(NG_MPI_Recv) NG_MPI_Recv = [](void*, int, NG_MPI_Datatype, int, int, NG_MPI_Comm, NG_MPI_Status*)->int { throw no_mpi(); };
decltype(NG_MPI_Recv_init) NG_MPI_Recv_init = [](void*, int, NG_MPI_Datatype, int, int, NG_MPI_Comm, NG_MPI_Request*)->int { throw no_mpi(); };
decltype(NG_MPI_Reduce) NG_MPI_Reduce = [](void*, void*, int, NG_MPI_Datatype, NG_MPI_Op, int, NG_MPI_Comm)->int { throw no_mpi(); };
decltype(NG_MPI_Reduce_local) NG_MPI_Reduce_local = [](void*, void*, int, NG_MPI_Datatype, NG_MPI_Op)->int { throw no_mpi(); };
decltype(NG_MPI_Request_free) NG_MPI_Request_free = [](NG_MPI_Request*)->int { throw no_mpi(); };
decltype(NG_MPI_Scatter) NG_MPI_Scatter = [](void*, int, NG_MPI_Datatype, void*, int, NG_MPI_Datatype, int, NG_MPI_Comm)->int { throw no_mpi(); };
decltype(NG_MPI_Send) NG_MPI_Send = [](void*, int, NG_MPI_Datatype, int, int, NG_MPI_Comm)->int { throw no_mpi(); };
decltype(NG_MPI_Send_init) NG_MPI_Send_init = [](void*, int, NG_MPI_Datatype, int, int, NG_MPI_Comm, NG_MPI_Request*)->int { throw no_mpi(); };
decltype(NG_MPI_Startall) NG_MPI_Startall = [](int, NG_MPI_Request*)->int { throw no_mpi(); };
decltype(NG_MPI_Type_commit) NG_MPI_Type_commit = [](NG_MPI_Datatype*)->int { throw no_mpi(); };
decltype(NG_MPI_Type_contiguous) NG_MPI_Type_contiguous = [](int, NG_MPI_Datatype, NG_MPI_Datatype*)->int { throw no_mpi(); };
decltype(NG_MPI_Type_create_resized) NG_MPI_Type_create_resized = [](NG_MPI_Datatype, NG_MPI_Aint, NG_MPI_Aint, NG_MPI_Datatype*)->int { throw no_mpi(); };
decltype(NG_MPI_Type_create_struct) NG_MPI_Type_create_struct = [](int, int*, NG_MPI_Aint*, NG_MPI_Datatype*, NG_MPI_Datatype*)->int { throw no_mpi(); };
decltype(NG_MPI_Type_free) NG_MPI_Type_free = [](NG_MPI_Datatype*)->int { throw no_mpi(); };
decltype(NG_MPI_Type_get_extent) NG_MPI_Type_get_extent = [](NG_MPI_Datatype, NG_MPI_Aint*, NG_MPI_Aint*)->int { throw no_mpi(); };
decltype(NG_MPI_Type_indexed) NG_MPI_Type_indexed = [](int, int*, int*, NG_MPI_Datatype, NG_MPI_Datatype*)->int { throw no_mpi(); };
decltype(NG_MPI_Type_size) NG_MPI_Type_size = [](NG_MPI_Datatype, int*)->int { throw no_mpi(); };
decltype(NG_MPI_Wait) NG_MPI_Wait = [](NG_MPI_Request*, NG_MPI_Status*)->int { throw no_mpi(); };
decltype(NG_MPI_Waitall) NG_MPI_Waitall = [](int, NG_MPI_Request*, NG_MPI_Status*)->int { throw no_mpi(); };
decltype(NG_MPI_Waitany) NG_MPI_Waitany = [](int, NG_MPI_Request*, int*, NG_MPI_Status*)->int { throw no_mpi(); };
NG_MPI_Comm NG_MPI_COMM_NULL = 0;
NG_MPI_Comm NG_MPI_COMM_WORLD = 0;
NG_MPI_Datatype NG_MPI_CHAR = 0;
NG_MPI_Datatype NG_MPI_CXX_DOUBLE_COMPLEX = 0;
NG_MPI_Datatype NG_MPI_C_BOOL = 0;
NG_MPI_Datatype NG_MPI_DATATYPE_NULL = 0;
NG_MPI_Datatype NG_MPI_DOUBLE = 0;
NG_MPI_Datatype NG_MPI_FLOAT = 0;
NG_MPI_Datatype NG_MPI_INT = 0;
NG_MPI_Datatype NG_MPI_SHORT = 0;
NG_MPI_Datatype NG_MPI_UINT64_T = 0;
NG_MPI_Op NG_MPI_LOR = 0;
NG_MPI_Op NG_MPI_MAX = 0;
NG_MPI_Op NG_MPI_MIN = 0;
NG_MPI_Op NG_MPI_SUM = 0;
NG_MPI_Request NG_MPI_REQUEST_NULL = 0;
NG_MPI_Status* NG_MPI_STATUSES_IGNORE = 0;
NG_MPI_Status* NG_MPI_STATUS_IGNORE = 0;
int NG_MPI_ANY_SOURCE = 0;
int NG_MPI_ANY_TAG = 0;
int NG_MPI_MAX_PROCESSOR_NAME = 0;
int NG_MPI_PROC_NULL = 0;
int NG_MPI_ROOT = 0;
int NG_MPI_SUBVERSION = 0;
int NG_MPI_THREAD_MULTIPLE = 0;
int NG_MPI_THREAD_SINGLE = 0;
int NG_MPI_VERSION = 0;
void* NG_MPI_IN_PLACE = 0;

View File

@ -0,0 +1,76 @@
NG_MPI_Wtime = []()->double { return MPI_Wtime(); };
NG_MPI_Allgather = [](void* arg0, int arg1, NG_MPI_Datatype arg2, void* arg3, int arg4, NG_MPI_Datatype arg5, NG_MPI_Comm arg6)->int { return MPI_Allgather( arg0, arg1, ng2mpi(arg2), arg3, arg4, ng2mpi(arg5), ng2mpi(arg6)); };
NG_MPI_Allreduce = [](void* arg0, void* arg1, int arg2, NG_MPI_Datatype arg3, NG_MPI_Op arg4, NG_MPI_Comm arg5)->int { return MPI_Allreduce( arg0, arg1, arg2, ng2mpi(arg3), ng2mpi(arg4), ng2mpi(arg5)); };
NG_MPI_Alltoall = [](void* arg0, int arg1, NG_MPI_Datatype arg2, void* arg3, int arg4, NG_MPI_Datatype arg5, NG_MPI_Comm arg6)->int { return MPI_Alltoall( arg0, arg1, ng2mpi(arg2), arg3, arg4, ng2mpi(arg5), ng2mpi(arg6)); };
NG_MPI_Barrier = [](NG_MPI_Comm arg0)->int { return MPI_Barrier( ng2mpi(arg0)); };
NG_MPI_Bcast = [](void* arg0, int arg1, NG_MPI_Datatype arg2, int arg3, NG_MPI_Comm arg4)->int { return MPI_Bcast( arg0, arg1, ng2mpi(arg2), arg3, ng2mpi(arg4)); };
NG_MPI_Ibcast = [](void* arg0, int arg1, NG_MPI_Datatype arg2, int arg3, NG_MPI_Comm arg4, NG_MPI_Request* arg5)->int { return MPI_Ibcast( arg0, arg1, ng2mpi(arg2), arg3, ng2mpi(arg4), ng2mpi(arg5)); };
NG_MPI_Comm_c2f = [](NG_MPI_Comm arg0)->int { return MPI_Comm_c2f( ng2mpi(arg0)); };
NG_MPI_Comm_create = [](NG_MPI_Comm arg0, NG_MPI_Group arg1, NG_MPI_Comm* arg2)->int { return MPI_Comm_create( ng2mpi(arg0), ng2mpi(arg1), ng2mpi(arg2)); };
NG_MPI_Comm_create_group = [](NG_MPI_Comm arg0, NG_MPI_Group arg1, int arg2, NG_MPI_Comm* arg3)->int { return MPI_Comm_create_group( ng2mpi(arg0), ng2mpi(arg1), arg2, ng2mpi(arg3)); };
NG_MPI_Comm_free = [](NG_MPI_Comm* arg0)->int { return MPI_Comm_free( ng2mpi(arg0)); };
NG_MPI_Comm_group = [](NG_MPI_Comm arg0, NG_MPI_Group* arg1)->int { return MPI_Comm_group( ng2mpi(arg0), ng2mpi(arg1)); };
NG_MPI_Comm_rank = [](NG_MPI_Comm arg0, int* arg1)->int { return MPI_Comm_rank( ng2mpi(arg0), arg1); };
NG_MPI_Comm_size = [](NG_MPI_Comm arg0, int* arg1)->int { return MPI_Comm_size( ng2mpi(arg0), arg1); };
NG_MPI_Finalize = []()->int { return MPI_Finalize(); };
NG_MPI_Gather = [](void* arg0, int arg1, NG_MPI_Datatype arg2, void* arg3, int arg4, NG_MPI_Datatype arg5, int arg6, NG_MPI_Comm arg7)->int { return MPI_Gather( arg0, arg1, ng2mpi(arg2), arg3, arg4, ng2mpi(arg5), arg6, ng2mpi(arg7)); };
NG_MPI_Gatherv = [](void* arg0, int arg1, NG_MPI_Datatype arg2, void* arg3, int* arg4, int* arg5, NG_MPI_Datatype arg6, int arg7, NG_MPI_Comm arg8)->int { return MPI_Gatherv( arg0, arg1, ng2mpi(arg2), arg3, arg4, arg5, ng2mpi(arg6), arg7, ng2mpi(arg8)); };
NG_MPI_Get_count = [](NG_MPI_Status* arg0, NG_MPI_Datatype arg1, int* arg2)->int { return MPI_Get_count( ng2mpi(arg0), ng2mpi(arg1), arg2); };
NG_MPI_Get_processor_name = [](char* arg0, int* arg1)->int { return MPI_Get_processor_name( arg0, arg1); };
NG_MPI_Group_incl = [](NG_MPI_Group arg0, int arg1, int* arg2, NG_MPI_Group* arg3)->int { return MPI_Group_incl( ng2mpi(arg0), arg1, arg2, ng2mpi(arg3)); };
NG_MPI_Init = [](int* arg0, char*** arg1)->int { return MPI_Init( arg0, arg1); };
NG_MPI_Init_thread = [](int* arg0, char*** arg1, int arg2, int* arg3)->int { return MPI_Init_thread( arg0, arg1, arg2, arg3); };
NG_MPI_Initialized = [](int* arg0)->int { return MPI_Initialized( arg0); };
NG_MPI_Iprobe = [](int arg0, int arg1, NG_MPI_Comm arg2, int* arg3, NG_MPI_Status* arg4)->int { return MPI_Iprobe( arg0, arg1, ng2mpi(arg2), arg3, ng2mpi(arg4)); };
NG_MPI_Irecv = [](void* arg0, int arg1, NG_MPI_Datatype arg2, int arg3, int arg4, NG_MPI_Comm arg5, NG_MPI_Request* arg6)->int { return MPI_Irecv( arg0, arg1, ng2mpi(arg2), arg3, arg4, ng2mpi(arg5), ng2mpi(arg6)); };
NG_MPI_Isend = [](void* arg0, int arg1, NG_MPI_Datatype arg2, int arg3, int arg4, NG_MPI_Comm arg5, NG_MPI_Request* arg6)->int { return MPI_Isend( arg0, arg1, ng2mpi(arg2), arg3, arg4, ng2mpi(arg5), ng2mpi(arg6)); };
NG_MPI_Probe = [](int arg0, int arg1, NG_MPI_Comm arg2, NG_MPI_Status* arg3)->int { return MPI_Probe( arg0, arg1, ng2mpi(arg2), ng2mpi(arg3)); };
NG_MPI_Query_thread = [](int* arg0)->int { return MPI_Query_thread( arg0); };
NG_MPI_Recv = [](void* arg0, int arg1, NG_MPI_Datatype arg2, int arg3, int arg4, NG_MPI_Comm arg5, NG_MPI_Status* arg6)->int { return MPI_Recv( arg0, arg1, ng2mpi(arg2), arg3, arg4, ng2mpi(arg5), ng2mpi(arg6)); };
NG_MPI_Recv_init = [](void* arg0, int arg1, NG_MPI_Datatype arg2, int arg3, int arg4, NG_MPI_Comm arg5, NG_MPI_Request* arg6)->int { return MPI_Recv_init( arg0, arg1, ng2mpi(arg2), arg3, arg4, ng2mpi(arg5), ng2mpi(arg6)); };
NG_MPI_Reduce = [](void* arg0, void* arg1, int arg2, NG_MPI_Datatype arg3, NG_MPI_Op arg4, int arg5, NG_MPI_Comm arg6)->int { return MPI_Reduce( arg0, arg1, arg2, ng2mpi(arg3), ng2mpi(arg4), arg5, ng2mpi(arg6)); };
NG_MPI_Reduce_local = [](void* arg0, void* arg1, int arg2, NG_MPI_Datatype arg3, NG_MPI_Op arg4)->int { return MPI_Reduce_local( arg0, arg1, arg2, ng2mpi(arg3), ng2mpi(arg4)); };
NG_MPI_Request_free = [](NG_MPI_Request* arg0)->int { return MPI_Request_free( ng2mpi(arg0)); };
NG_MPI_Scatter = [](void* arg0, int arg1, NG_MPI_Datatype arg2, void* arg3, int arg4, NG_MPI_Datatype arg5, int arg6, NG_MPI_Comm arg7)->int { return MPI_Scatter( arg0, arg1, ng2mpi(arg2), arg3, arg4, ng2mpi(arg5), arg6, ng2mpi(arg7)); };
NG_MPI_Send = [](void* arg0, int arg1, NG_MPI_Datatype arg2, int arg3, int arg4, NG_MPI_Comm arg5)->int { return MPI_Send( arg0, arg1, ng2mpi(arg2), arg3, arg4, ng2mpi(arg5)); };
NG_MPI_Send_init = [](void* arg0, int arg1, NG_MPI_Datatype arg2, int arg3, int arg4, NG_MPI_Comm arg5, NG_MPI_Request* arg6)->int { return MPI_Send_init( arg0, arg1, ng2mpi(arg2), arg3, arg4, ng2mpi(arg5), ng2mpi(arg6)); };
NG_MPI_Startall = [](int arg0, NG_MPI_Request* arg1)->int { return MPI_Startall( arg0, ng2mpi(arg1, arg0)); };
NG_MPI_Type_commit = [](NG_MPI_Datatype* arg0)->int { return MPI_Type_commit( ng2mpi(arg0)); };
NG_MPI_Type_contiguous = [](int arg0, NG_MPI_Datatype arg1, NG_MPI_Datatype* arg2)->int { return MPI_Type_contiguous( arg0, ng2mpi(arg1), ng2mpi(arg2)); };
NG_MPI_Type_create_resized = [](NG_MPI_Datatype arg0, NG_MPI_Aint arg1, NG_MPI_Aint arg2, NG_MPI_Datatype* arg3)->int { return MPI_Type_create_resized( ng2mpi(arg0), ng2mpi(arg1), ng2mpi(arg2), ng2mpi(arg3)); };
NG_MPI_Type_create_struct = [](int arg0, int* arg1, NG_MPI_Aint* arg2, NG_MPI_Datatype* arg3, NG_MPI_Datatype* arg4)->int { return MPI_Type_create_struct( arg0, arg1, ng2mpi(arg2, arg0), ng2mpi(arg3, arg0), ng2mpi(arg4)); };
NG_MPI_Type_free = [](NG_MPI_Datatype* arg0)->int { return MPI_Type_free( ng2mpi(arg0)); };
NG_MPI_Type_get_extent = [](NG_MPI_Datatype arg0, NG_MPI_Aint* arg1, NG_MPI_Aint* arg2)->int { return MPI_Type_get_extent( ng2mpi(arg0), ng2mpi(arg1), ng2mpi(arg2)); };
NG_MPI_Type_indexed = [](int arg0, int* arg1, int* arg2, NG_MPI_Datatype arg3, NG_MPI_Datatype* arg4)->int { return MPI_Type_indexed( arg0, arg1, arg2, ng2mpi(arg3), ng2mpi(arg4)); };
NG_MPI_Type_size = [](NG_MPI_Datatype arg0, int* arg1)->int { return MPI_Type_size( ng2mpi(arg0), arg1); };
NG_MPI_Wait = [](NG_MPI_Request* arg0, NG_MPI_Status* arg1)->int { return MPI_Wait( ng2mpi(arg0), ng2mpi(arg1)); };
NG_MPI_Waitall = [](int arg0, NG_MPI_Request* arg1, NG_MPI_Status* arg2)->int { return MPI_Waitall( arg0, ng2mpi(arg1, arg0), ng2mpi(arg2)); };
NG_MPI_Waitany = [](int arg0, NG_MPI_Request* arg1, int* arg2, NG_MPI_Status* arg3)->int { return MPI_Waitany( arg0, ng2mpi(arg1, arg0), arg2, ng2mpi(arg3)); };
NG_MPI_COMM_NULL = mpi2ng(MPI_COMM_NULL);
NG_MPI_COMM_WORLD = mpi2ng(MPI_COMM_WORLD);
NG_MPI_CHAR = mpi2ng(MPI_CHAR);
NG_MPI_CXX_DOUBLE_COMPLEX = mpi2ng(MPI_CXX_DOUBLE_COMPLEX);
NG_MPI_C_BOOL = mpi2ng(MPI_C_BOOL);
NG_MPI_DATATYPE_NULL = mpi2ng(MPI_DATATYPE_NULL);
NG_MPI_DOUBLE = mpi2ng(MPI_DOUBLE);
NG_MPI_FLOAT = mpi2ng(MPI_FLOAT);
NG_MPI_INT = mpi2ng(MPI_INT);
NG_MPI_SHORT = mpi2ng(MPI_SHORT);
NG_MPI_UINT64_T = mpi2ng(MPI_UINT64_T);
NG_MPI_LOR = mpi2ng(MPI_LOR);
NG_MPI_MAX = mpi2ng(MPI_MAX);
NG_MPI_MIN = mpi2ng(MPI_MIN);
NG_MPI_SUM = mpi2ng(MPI_SUM);
NG_MPI_REQUEST_NULL = mpi2ng(MPI_REQUEST_NULL);
NG_MPI_STATUSES_IGNORE = mpi2ng(MPI_STATUSES_IGNORE);
NG_MPI_STATUS_IGNORE = mpi2ng(MPI_STATUS_IGNORE);
NG_MPI_ANY_SOURCE = mpi2ng(MPI_ANY_SOURCE);
NG_MPI_ANY_TAG = mpi2ng(MPI_ANY_TAG);
NG_MPI_MAX_PROCESSOR_NAME = mpi2ng(MPI_MAX_PROCESSOR_NAME);
NG_MPI_PROC_NULL = mpi2ng(MPI_PROC_NULL);
NG_MPI_ROOT = mpi2ng(MPI_ROOT);
NG_MPI_SUBVERSION = mpi2ng(MPI_SUBVERSION);
NG_MPI_THREAD_MULTIPLE = mpi2ng(MPI_THREAD_MULTIPLE);
NG_MPI_THREAD_SINGLE = mpi2ng(MPI_THREAD_SINGLE);
NG_MPI_VERSION = mpi2ng(MPI_VERSION);
NG_MPI_IN_PLACE = mpi2ng(MPI_IN_PLACE);

View File

@ -0,0 +1,21 @@
#ifndef NG_MPI_NATIVE_HPP
#define NG_MPI_NATIVE_HPP
#include <mpi.h>
#include "mpi_wrapper.hpp"
#include "ng_mpi.hpp"
namespace ngcore {
MPI_Comm NG_MPI_Native(NG_MPI_Comm comm) {
return reinterpret_cast<MPI_Comm>(comm.value);
}
MPI_Comm NG_MPI_Native(NgMPI_Comm comm) {
return reinterpret_cast<MPI_Comm>(static_cast<NG_MPI_Comm>(comm).value);
}
} // namespace ngcore
#endif // NG_MPI_NATIVE_HPP

View File

@ -0,0 +1,206 @@
#ifdef PARALLEL
#include <filesystem>
#include <iostream>
#include <stdexcept>
#include "ng_mpi.hpp"
#include "ngstream.hpp"
#ifdef NG_PYTHON
#include "python_ngcore.hpp"
#endif // NG_PYTHON
#include "utils.hpp"
using std::cerr;
using std::cout;
using std::endl;
#ifndef NG_MPI_WRAPPER
#ifdef NG_PYTHON
#define MPI4PY_LIMITED_API 1
#define MPI4PY_LIMITED_API_SKIP_MESSAGE 1
#define MPI4PY_LIMITED_API_SKIP_SESSION 1
#include "mpi4py_pycapi.h" // mpi4py < 4.0.0
#endif // NG_PYTHON
#endif // NG_MPI_WRAPPER
namespace ngcore {
#ifdef NG_MPI_WRAPPER
static std::unique_ptr<SharedLibrary> mpi_lib, ng_mpi_lib;
static bool need_mpi_finalize = false;
struct MPIFinalizer {
~MPIFinalizer() {
if (need_mpi_finalize) {
cout << IM(5) << "Calling MPI_Finalize" << endl;
NG_MPI_Finalize();
}
}
} mpi_finalizer;
bool MPI_Loaded() { return ng_mpi_lib != nullptr; }
void InitMPI(std::optional<std::filesystem::path> mpi_lib_path) {
if (ng_mpi_lib) return;
cout << IM(3) << "InitMPI" << endl;
std::string vendor = "";
std::string mpi4py_lib_file = "";
if (mpi_lib_path) {
// Dynamic load of given shared MPI library
// Then call MPI_Init, read the library version and set the vender name
try {
typedef int (*init_handle)(int *, char ***);
typedef int (*mpi_initialized_handle)(int *);
mpi_lib =
std::make_unique<SharedLibrary>(*mpi_lib_path, std::nullopt, true);
auto mpi_init = mpi_lib->GetSymbol<init_handle>("MPI_Init");
auto mpi_initialized =
mpi_lib->GetSymbol<mpi_initialized_handle>("MPI_Initialized");
int flag = 0;
mpi_initialized(&flag);
if (!flag) {
typedef const char *pchar;
int argc = 1;
pchar args[] = {"netgen", nullptr};
pchar *argv = &args[0];
cout << IM(5) << "Calling MPI_Init" << endl;
mpi_init(&argc, (char ***)argv);
need_mpi_finalize = true;
}
char c_version_string[65536];
c_version_string[0] = '\0';
int result_len = 0;
typedef void (*get_version_handle)(char *, int *);
auto get_version =
mpi_lib->GetSymbol<get_version_handle>("MPI_Get_library_version");
get_version(c_version_string, &result_len);
std::string version = c_version_string;
if (version.substr(0, 8) == "Open MPI")
vendor = "Open MPI";
else if (version.substr(0, 5) == "MPICH")
vendor = "MPICH";
else if (version.substr(0, 13) == "Microsoft MPI")
vendor = "Microsoft MPI";
else if (version.substr(0, 12) == "Intel(R) MPI")
vendor = "Intel MPI";
else
throw std::runtime_error(
std::string("Unknown MPI version: " + version));
} catch (std::runtime_error &e) {
cerr << "Could not load MPI: " << e.what() << endl;
throw e;
}
} else {
#ifdef NG_PYTHON
// Use mpi4py to init MPI library and get the vendor name
auto mpi4py = py::module::import("mpi4py.MPI");
vendor = mpi4py.attr("get_vendor")()[py::int_(0)].cast<std::string>();
#ifndef WIN32
// Load mpi4py library (it exports all MPI symbols) to have all MPI symbols
// available before the ng_mpi wrapper is loaded This is not necessary on
// windows as the matching mpi dll is linked to the ng_mpi wrapper directly
mpi4py_lib_file = mpi4py.attr("__file__").cast<std::string>();
mpi_lib =
std::make_unique<SharedLibrary>(mpi4py_lib_file, std::nullopt, true);
#endif // WIN32
#endif // NG_PYTHON
}
std::string ng_lib_name = "";
if (vendor == "Open MPI")
ng_lib_name = "ng_openmpi";
else if (vendor == "MPICH")
ng_lib_name = "ng_mpich";
else if (vendor == "Microsoft MPI")
ng_lib_name = "ng_microsoft_mpi";
else if (vendor == "Intel MPI")
ng_lib_name = "ng_intel_mpi";
else
throw std::runtime_error("Unknown MPI vendor: " + vendor);
ng_lib_name += NETGEN_SHARED_LIBRARY_SUFFIX;
// Load the ng_mpi wrapper and call ng_init_mpi to set all function pointers
typedef void (*ng_init_handle)();
ng_mpi_lib = std::make_unique<SharedLibrary>(ng_lib_name);
ng_mpi_lib->GetSymbol<ng_init_handle>("ng_init_mpi")();
std::cout << IM(3) << "MPI wrapper loaded, vendor: " << vendor << endl;
}
static std::runtime_error no_mpi() {
return std::runtime_error("MPI not enabled");
}
#ifdef NG_PYTHON
decltype(NG_MPI_CommFromMPI4Py) NG_MPI_CommFromMPI4Py =
[](py::handle py_obj, NG_MPI_Comm &ng_comm) -> bool {
// If this gets called, it means that we want to convert an mpi4py
// communicator to a Netgen MPI communicator, but the Netgen MPI wrapper
// runtime was not yet initialized.
// store the current address of this function
auto old_converter_address = NG_MPI_CommFromMPI4Py;
// initialize the MPI wrapper runtime, this sets all the function pointers
InitMPI();
// if the initialization was successful, the function pointer should have
// changed
// -> call the actual conversion function
if (NG_MPI_CommFromMPI4Py != old_converter_address)
return NG_MPI_CommFromMPI4Py(py_obj, ng_comm);
// otherwise, something strange happened
throw no_mpi();
};
decltype(NG_MPI_CommToMPI4Py) NG_MPI_CommToMPI4Py =
[](NG_MPI_Comm) -> py::handle { throw no_mpi(); };
#endif // NG_PYTHON
#include "ng_mpi_generated_dummy_init.hpp"
#else // NG_MPI_WRAPPER
static bool imported_mpi4py = false;
#ifdef NG_PYTHON
decltype(NG_MPI_CommFromMPI4Py) NG_MPI_CommFromMPI4Py =
[](py::handle src, NG_MPI_Comm &dst) -> bool {
if (!imported_mpi4py) {
import_mpi4py__MPI();
imported_mpi4py = true;
}
PyObject *py_src = src.ptr();
auto type = Py_TYPE(py_src);
if (PyObject_TypeCheck(py_src, &PyMPIComm_Type)) {
dst = *PyMPIComm_Get(py_src);
return !PyErr_Occurred();
}
return false;
};
decltype(NG_MPI_CommToMPI4Py) NG_MPI_CommToMPI4Py =
[](NG_MPI_Comm src) -> py::handle {
if (!imported_mpi4py) {
import_mpi4py__MPI();
imported_mpi4py = true;
}
return py::handle(PyMPIComm_New(src));
};
#endif // NG_PYTHON
bool MPI_Loaded() { return true; }
void InitMPI(std::optional<std::filesystem::path>) {}
#endif // NG_MPI_WRAPPER
} // namespace ngcore
#endif // PARALLEL

View File

@ -10,15 +10,18 @@
#include "hashtable.hpp"
#include "localheap.hpp"
#include "logging.hpp"
#include "mpi_wrapper.hpp"
// #include "mpi_wrapper.hpp"
#include "profiler.hpp"
#include "signal.hpp"
#include "simd.hpp"
#include "autodiff.hpp"
#include "autodiffdiff.hpp"
#include "symboltable.hpp"
#include "taskmanager.hpp"
#include "version.hpp"
#include "xbool.hpp"
#include "ngstream.hpp"
#include "utils.hpp"
#include "ranges.hpp"
#endif // NETGEN_CORE_NGCORE_HPP

View File

@ -1,6 +1,8 @@
#ifndef NETGEN_CORE_NGCORE_API_HPP
#define NETGEN_CORE_NGCORE_API_HPP
#include "netgen_config.hpp"
#ifdef WIN32
// This function or variable may be unsafe. Consider using _ftime64_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.

View File

@ -7,12 +7,14 @@
#include "archive.hpp" // for Demangle
#include "paje_trace.hpp"
#include "ng_mpi.hpp"
#include "profiler.hpp"
#include "mpi_wrapper.hpp"
extern const char *header;
constexpr int MPI_PAJE_WRITER = 1;
constexpr int ASSUMED_MPI_MAX_PROCESSOR_NAME = 256;
namespace ngcore
{
@ -24,7 +26,7 @@ namespace ngcore
if(id<NgProfiler::SIZE)
return NgProfiler::GetName(id);
NgMPI_Comm comm(MPI_COMM_WORLD);
NgMPI_Comm comm(NG_MPI_COMM_WORLD);
return NgProfiler::GetName(id-NgProfiler::SIZE*comm.Rank());
#endif // PARALLEL
}
@ -39,6 +41,7 @@ namespace ngcore
bool PajeTrace::trace_thread_counter = false;
bool PajeTrace::trace_threads = true;
bool PajeTrace::mem_tracing_enabled = true;
bool PajeTrace::write_paje_file = true;
PajeTrace :: PajeTrace(int anthreads, std::string aname)
{
@ -70,9 +73,12 @@ namespace ngcore
// sync start time when running in parallel
#ifdef PARALLEL
NgMPI_Comm comm(MPI_COMM_WORLD);
for(auto i : Range(5))
comm.Barrier();
if(MPI_Loaded())
{
NgMPI_Comm comm(NG_MPI_COMM_WORLD);
for([[maybe_unused]] auto i : Range(5))
comm.Barrier();
}
#endif // PARALLEL
start_time = GetTimeCounter();
@ -112,11 +118,14 @@ namespace ngcore
for(auto i : IntRange(n_memory_events_at_start, memory_events.size()))
memory_events[i].time -= start_time;
NgMPI_Comm comm(MPI_COMM_WORLD);
NgMPI_Comm comm;
#ifdef PARALLEL
if(MPI_Loaded())
comm = NgMPI_Comm(NG_MPI_COMM_WORLD);
#endif
if(comm.Size()==1)
{
Write(tracefile_name);
Write();
}
else
{
@ -128,7 +137,7 @@ namespace ngcore
event.timer_id += NgProfiler::SIZE*comm.Rank();
if(comm.Rank() == MPI_PAJE_WRITER)
Write(tracefile_name);
Write();
else
SendData();
}
@ -199,7 +208,7 @@ namespace ngcore
{ }
PajeEvent( int aevent_type, double atime, int atype, int acontainer, std::string as_value, int aid = 0 )
: time(atime), event_type(aevent_type), type(atype), container(acontainer), id(aid), s_value(as_value), value_is_alias(false), value_is_int(false)
: time(atime), event_type(aevent_type), type(atype), container(acontainer), s_value(as_value), id(aid), value_is_alias(false), value_is_int(false)
{ }
PajeEvent( int aevent_type, double atime, int atype, int acontainer, int avalue, int astart_container, int akey )
@ -435,7 +444,16 @@ namespace ngcore
NGCORE_API PajeTrace *trace;
void PajeTrace::Write( const std::string & filename )
void PajeTrace::Write( )
{
if(write_paje_file) WritePajeFile( tracefile_name );
WriteTimingChart();
#ifdef NETGEN_TRACE_MEMORY
WriteMemoryChart("");
#endif // NETGEN_TRACE_MEMORY
}
void PajeTrace::WritePajeFile( const std::string & filename )
{
auto n_events = jobs.size() + timer_events.size();
for(auto & vtasks : tasks)
@ -486,25 +504,25 @@ namespace ngcore
std::vector <int> thread_aliases;
std::vector<int> container_nodes;
#ifdef PARALLEL
// Hostnames
NgMPI_Comm comm(MPI_COMM_WORLD);
auto rank = comm.Rank();
auto nranks = comm.Size();
if(nranks>1)
NgMPI_Comm comm;
#ifdef PARALLEL
if(MPI_Loaded())
comm = NgMPI_Comm(NG_MPI_COMM_WORLD);
if(comm.Size()>1)
{
nthreads = nranks;
auto comm = NgMPI_Comm(NG_MPI_COMM_WORLD);
nthreads = comm.Size();
thread_aliases.reserve(nthreads);
std::array<char, MPI_MAX_PROCESSOR_NAME+1> ahostname;
std::array<char, ASSUMED_MPI_MAX_PROCESSOR_NAME+1> ahostname;
int len;
MPI_Get_processor_name(ahostname.data(), &len);
NG_MPI_Get_processor_name(ahostname.data(), &len);
std::string hostname = ahostname.data();
std::map<std::string, int> host_map;
std::string name;
for(auto i : IntRange(0, nranks))
for(auto i : IntRange(0, comm.Size()))
{
if(i!=MPI_PAJE_WRITER)
comm.Recv(name, i, 0);
@ -519,7 +537,7 @@ namespace ngcore
}
}
else
#endif // PARALLEL
#endif
{
container_nodes.reserve(num_nodes);
for(int i=0; i<num_nodes; i++)
@ -595,10 +613,9 @@ namespace ngcore
for(auto id : timer_ids)
timer_names[id] = GetTimerName(id);
#ifdef PARALLEL
if(nranks>1)
if(comm.Size()>1)
{
for(auto src : IntRange(0, nranks))
for(auto src : IntRange(0, comm.Size()))
{
if(src==MPI_PAJE_WRITER)
continue;
@ -608,7 +625,7 @@ namespace ngcore
int id;
std::string name;
for(auto i : IntRange(n_timers))
for([[maybe_unused]]auto i : IntRange(n_timers))
{
comm.Recv (id, src, 0);
comm.Recv (name, src, 0);
@ -617,7 +634,6 @@ namespace ngcore
}
}
}
#endif // PARALLEL
for(auto id : timer_ids)
timer_aliases[id] = paje.DefineEntityValue( state_type_timer, timer_names[id], -1 );
@ -742,7 +758,7 @@ namespace ngcore
}
#ifdef PARALLEL
if(nranks>1)
if(comm.Size()>1)
{
for(auto & event : timer_events)
{
@ -758,7 +774,7 @@ namespace ngcore
Array<bool> is_start;
Array<int> thread_id;
for(auto src : IntRange(0, nranks))
for(auto src : IntRange(0, comm.Size()))
{
if(src==MPI_PAJE_WRITER)
continue;
@ -843,10 +859,6 @@ namespace ngcore
}
}
}
WriteTimingChart();
#ifdef NETGEN_TRACE_MEMORY
WriteMemoryChart("");
#endif // NETGEN_TRACE_MEMORY
paje.WriteEvents();
}
@ -854,15 +866,15 @@ namespace ngcore
{
#ifdef PARALLEL
// Hostname
NgMPI_Comm comm(MPI_COMM_WORLD);
auto rank = comm.Rank();
auto nranks = comm.Size();
NgMPI_Comm comm(NG_MPI_COMM_WORLD);
// auto rank = comm.Rank();
// auto nranks = comm.Size();
std::string hostname;
{
std::array<char, MPI_MAX_PROCESSOR_NAME+1> ahostname;
std::array<char, ASSUMED_MPI_MAX_PROCESSOR_NAME+1> ahostname;
int len;
MPI_Get_processor_name(ahostname.data(), &len);
NG_MPI_Get_processor_name(ahostname.data(), &len);
hostname = ahostname.data();
}
@ -955,10 +967,18 @@ namespace ngcore
f.precision(4);
f << R"CODE_(
<head>
<script src="https://d3js.org/d3.v5.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/d3@7"></script>
<script src="https://unpkg.com/sunburst-chart"></script>
<style>body { margin: 0 }</style>
<style>
body { margin: 0 }
.tooltip {
white-space: pre-line !important;
max-width: 800px !important;
word-wrap: break-word !important;
padding: 10px !important;
}
</style>
)CODE_";
if(!time_or_memory)
f << "<title>Maximum Memory Consumption</title>\n";

View File

@ -25,6 +25,7 @@ namespace ngcore
NGCORE_API static bool trace_thread_counter;
NGCORE_API static bool trace_threads;
NGCORE_API static bool mem_tracing_enabled;
NGCORE_API static bool write_paje_file;
bool tracing_enabled;
TTimePoint start_time;
@ -32,6 +33,8 @@ namespace ngcore
size_t n_memory_events_at_start;
public:
NGCORE_API void Write();
NGCORE_API void WritePajeFile( const std::string & filename );
NGCORE_API void WriteTimingChart();
#ifdef NETGEN_TRACE_MEMORY
NGCORE_API void WriteMemoryChart( std::string fname );
@ -61,6 +64,11 @@ namespace ngcore
max_tracefile_size = max_size;
}
static void SetWritePajeFile( bool write )
{
write_paje_file = write;
}
std::string tracefile_name;
struct Job
@ -262,8 +270,6 @@ namespace ngcore
links[thread_id].push_back( ThreadLink{thread_id, key, GetTimeCounter(), false} );
}
void Write( const std::string & filename );
void SendData(); // MPI parallel data reduction
};

View File

@ -116,6 +116,7 @@ namespace ngcore
#ifdef NETGEN_TRACE_MEMORY
std::vector<std::string> MemoryTracer::names{"all"};
std::vector<int> MemoryTracer::parents{-1};
std::atomic<size_t> MemoryTracer::total_memory{0};
#endif // NETGEN_TRACE_MEMORY
} // namespace ngcore

View File

@ -14,13 +14,11 @@ namespace ngcore
{
if (py::isinstance<py::dict>(value))
{
py::dict vdd(value);
// call recursively to set dictionary
for (auto item : vdd) {
string name = item.first.cast<string>();
py::object val = py::reinterpret_borrow<py::object>(item.second);
SetFlag(flags, name, val);
}
Flags nested_flags;
for(auto item : value.cast<py::dict>())
SetFlag(nested_flags, item.first.cast<string>(),
item.second.cast<py::object>());
flags.SetFlag(s, nested_flags);
return;
}
@ -103,7 +101,9 @@ namespace ngcore
}
}
auto flags = py::cast<Flags>(flags_dict);
Flags flags;
for(auto item : flags_dict)
SetFlag(flags, item.first.cast<string>(), item.second.cast<py::object>());
for (auto item : kwargs)
{

View File

@ -13,11 +13,17 @@
#include "archive.hpp"
#include "flags.hpp"
#include "ngcore_api.hpp"
#include "profiler.hpp"
#include "ng_mpi.hpp"
namespace py = pybind11;
namespace ngcore
{
#ifdef PARALLEL
NGCORE_API extern bool (*NG_MPI_CommFromMPI4Py)(py::handle, NG_MPI_Comm &);
NGCORE_API extern py::handle (*NG_MPI_CommToMPI4Py)(NG_MPI_Comm);
#endif // PARALLEL
namespace detail
{
template<typename T>
@ -31,6 +37,16 @@ namespace ngcore
static constexpr bool value = decltype(check((T*) nullptr))::value;
};
} // namespace detail
#ifdef PARALLEL
struct mpi4py_comm {
mpi4py_comm() = default;
mpi4py_comm(NG_MPI_Comm value) : value(value) {}
operator NG_MPI_Comm () { return value; }
NG_MPI_Comm value;
};
#endif // PARALLEL
} // namespace ngcore
@ -39,6 +55,27 @@ namespace ngcore
namespace pybind11 {
namespace detail {
#ifdef PARALLEL
template <> struct type_caster<ngcore::mpi4py_comm> {
public:
PYBIND11_TYPE_CASTER(ngcore::mpi4py_comm, _("mpi4py_comm"));
// Python -> C++
bool load(handle src, bool) {
return ngcore::NG_MPI_CommFromMPI4Py(src, value.value);
}
// C++ -> Python
static handle cast(ngcore::mpi4py_comm src,
return_value_policy /* policy */,
handle /* parent */)
{
// Create an mpi4py handle
return ngcore::NG_MPI_CommToMPI4Py(src.value);
}
};
#endif // PARALLEL
template <typename Type, typename Value> struct ngcore_list_caster {
using value_conv = make_caster<Value>;
@ -156,30 +193,6 @@ namespace ngcore
{ return std::string("sp_")+GetPyName<T>(); }
};
// *************** Archiving functionality **************
template<typename T>
Archive& Archive :: Shallow(T& val)
{
static_assert(detail::is_any_pointer<T>, "ShallowArchive must be given pointer type!");
#ifdef NETGEN_PYTHON
if(shallow_to_python)
{
if(is_output)
ShallowOutPython(pybind11::cast(val));
else
{
pybind11::object obj;
ShallowInPython(obj);
val = pybind11::cast<T>(obj);
}
}
else
#endif // NETGEN_PYTHON
*this & val;
return *this;
}
template<typename ARCHIVE>
class NGCORE_API_EXPORT PyArchive : public ARCHIVE
{
@ -190,7 +203,6 @@ namespace ngcore
protected:
using ARCHIVE::stream;
using ARCHIVE::version_map;
using ARCHIVE::logger;
public:
PyArchive(const pybind11::object& alst = pybind11::none()) :
ARCHIVE(std::make_shared<std::stringstream>()),
@ -202,7 +214,6 @@ namespace ngcore
stream = std::make_shared<std::stringstream>
(pybind11::cast<pybind11::bytes>(lst[pybind11::len(lst)-1]));
*this & version_needed;
logger->debug("versions needed for unpickling = {}", version_needed);
for(auto& libversion : version_needed)
if(libversion.second > GetLibraryVersion(libversion.first))
throw Exception("Error in unpickling data:\nLibrary " + libversion.first +
@ -219,7 +230,6 @@ namespace ngcore
{
if(Output())
{
logger->debug("Need version {} of library {}.", version, library);
version_needed[library] = version_needed[library] > version ? version_needed[library] : version;
}
}
@ -243,7 +253,6 @@ namespace ngcore
FlushBuffer();
lst.append(pybind11::bytes(std::static_pointer_cast<std::stringstream>(stream)->str()));
stream = std::make_shared<std::stringstream>();
logger->debug("Writeout version needed = {}", version_needed);
*this & version_needed;
FlushBuffer();
lst.append(pybind11::bytes(std::static_pointer_cast<std::stringstream>(stream)->str()));
@ -286,6 +295,16 @@ namespace ngcore
return arr;
}
template <typename T>
// py::object makePyTuple (FlatArray<T> ar)
py::object makePyTuple (const BaseArrayObject<T> & ar)
{
py::tuple res(ar.Size());
for (auto i : Range(ar))
res[i] = py::cast(ar[i]);
return res;
}
template <typename T, typename TIND=typename FlatArray<T>::index_type>
void ExportArray (py::module &m)
{
@ -300,8 +319,9 @@ namespace ngcore
.def ("__getitem__",
[](TFlat & self, TIND i) -> T&
{
static constexpr int base = IndexBASE<TIND>();
if (i < base || i >= self.Size()+base)
// static constexpr int base = IndexBASE<TIND>();
auto reli = i - IndexBASE<TIND>();
if (reli < 0 || reli >= self.Size())
throw py::index_error();
return self[i];
},
@ -309,8 +329,9 @@ namespace ngcore
.def ("__setitem__",
[](TFlat & self, TIND i, T val) -> T&
{
static constexpr int base = IndexBASE<TIND>();
if (i < base || i >= self.Size()+base)
// static constexpr int base = IndexBASE<TIND>();
auto reli = i - IndexBASE<TIND>();
if (reli < 0 || reli >= self.Size())
throw py::index_error();
self[i] = val;
return self[i];

View File

@ -1,11 +1,18 @@
#include "python_ngcore.hpp"
#include "bitarray.hpp"
#include "taskmanager.hpp"
#include "mpi_wrapper.hpp"
using namespace ngcore;
using namespace std;
using namespace pybind11::literals;
namespace pybind11 { namespace detail {
}} // namespace pybind11::detail
PYBIND11_MODULE(pyngcore, m) // NOLINT
{
try
@ -24,8 +31,18 @@ PYBIND11_MODULE(pyngcore, m) // NOLINT
ExportArray<unsigned short>(m);
ExportArray<unsigned char>(m);
// Compiler dependent implementation of size_t
if constexpr(!is_same_v<size_t, uint64_t>)
ExportArray<uint64_t>(m);
ExportTable<int>(m);
#ifdef PARALLEL
py::class_<NG_MPI_Comm> (m, "_NG_MPI_Comm")
;
m.def("InitMPI", &InitMPI, py::arg("mpi_library_path")=nullopt);
#endif // PARALLEL
py::class_<BitArray, shared_ptr<BitArray>> (m, "BitArray")
.def(py::init([] (size_t n) { return make_shared<BitArray>(n); }),py::arg("n"))
.def(py::init([] (const BitArray& a) { return make_shared<BitArray>(a); } ), py::arg("ba"))
@ -124,20 +141,34 @@ PYBIND11_MODULE(pyngcore, m) // NOLINT
.def(py::self | py::self)
.def(py::self & py::self)
#ifdef __clang__
// see https://github.com/pybind/pybind11/issues/1893
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wself-assign-overloaded"
#endif
.def(py::self |= py::self)
.def(py::self &= py::self)
#ifdef __clang__
#pragma GCC diagnostic pop
#endif
.def(~py::self)
;
py::class_<Flags>(m, "Flags")
.def(py::init<>())
.def("__str__", &ToString<Flags>)
.def(py::init([](py::object & obj) {
.def(py::init([](py::dict kwargs) {
Flags flags;
py::dict d(obj);
SetFlag (flags, "", d);
for (auto d : kwargs)
SetFlag(flags, d.first.cast<string>(), d.second.cast<py::object>());
return flags;
}), py::arg("obj"), "Create Flags by given object")
}), "Create flags from dict")
.def(py::init([](py::kwargs kwargs) {
Flags flags;
for (auto d : kwargs)
SetFlag(flags, d.first.cast<string>(), d.second.cast<py::object>());
return flags;
}), "Create flags from kwargs")
.def(py::pickle([] (const Flags& self)
{
std::stringstream str;
@ -165,6 +196,9 @@ PYBIND11_MODULE(pyngcore, m) // NOLINT
return self;
}, py::arg("akey"), py::arg("value"), "Set flag by given value.")
.def("keys", [](Flags & self) -> py::list {
return CreateDictFromFlags(self).attr("keys")();
})
.def("__getitem__", [](Flags & self, const string& name) -> py::object {
if(self.NumListFlagDefined(name))
@ -188,6 +222,10 @@ PYBIND11_MODULE(pyngcore, m) // NOLINT
{
return CreateDictFromFlags(flags);
})
.def("items", [](const Flags& flags)
{
return CreateDictFromFlags(flags).attr("items")();
})
;
py::implicitly_convertible<py::dict, Flags>();
@ -286,5 +324,70 @@ threads : int
#endif // NETGEN_TRACE_MEMORY
;
m.def("GetTotalMemory", MemoryTracer::GetTotalMemory);
py::class_<Timer<>> (m, "Timer")
.def(py::init<const string&>())
.def("Start", static_cast<void (Timer<>::*)()const>(&Timer<>::Start), "start timer")
.def("Stop", static_cast<void (Timer<>::*)()const>(&Timer<>::Stop), "stop timer")
.def_property_readonly("time", &Timer<>::GetTime, "returns time")
.def("__enter__", static_cast<void (Timer<>::*)()const>(&Timer<>::Start))
.def("__exit__", [](Timer<>& t, py::object, py::object, py::object)
{
t.Stop();
})
;
m.def("Timers",
[]()
{
py::list timers;
for (int i = 0; i < NgProfiler::SIZE; i++)
if (!NgProfiler::timers[i].name.empty())
{
py::dict timer;
timer["name"] = py::str(NgProfiler::timers[i].name);
timer["time"] = py::float_(NgProfiler::GetTime(i));
timer["counts"] = py::int_(NgProfiler::GetCounts(i));
timer["flops"] = py::float_(NgProfiler::GetFlops(i));
timer["Gflop/s"] = py::float_(NgProfiler::GetFlops(i)/NgProfiler::GetTime(i)*1e-9);
timers.append(timer);
}
return timers;
}, "Returns list of timers"
);
m.def("ResetTimers", &NgProfiler::Reset);
py::class_<NgMPI_Comm> (m, "MPI_Comm")
#ifdef PARALLEL
.def(py::init([] (mpi4py_comm comm) { return NgMPI_Comm(comm); }))
.def("WTime", [](NgMPI_Comm & c) { return NG_MPI_Wtime(); })
.def_property_readonly ("mpi4py", [](NgMPI_Comm & self) { return NG_MPI_CommToMPI4Py(self); })
#endif // PARALLEL
.def_property_readonly ("rank", &NgMPI_Comm::Rank)
.def_property_readonly ("size", &NgMPI_Comm::Size)
.def("Barrier", &NgMPI_Comm::Barrier)
.def("Sum", [](NgMPI_Comm & c, double x) { return c.AllReduce(x, NG_MPI_SUM); })
.def("Min", [](NgMPI_Comm & c, double x) { return c.AllReduce(x, NG_MPI_MIN); })
.def("Max", [](NgMPI_Comm & c, double x) { return c.AllReduce(x, NG_MPI_MAX); })
.def("Sum", [](NgMPI_Comm & c, int x) { return c.AllReduce(x, NG_MPI_SUM); })
.def("Min", [](NgMPI_Comm & c, int x) { return c.AllReduce(x, NG_MPI_MIN); })
.def("Max", [](NgMPI_Comm & c, int x) { return c.AllReduce(x, NG_MPI_MAX); })
.def("Sum", [](NgMPI_Comm & c, size_t x) { return c.AllReduce(x, NG_MPI_SUM); })
.def("Min", [](NgMPI_Comm & c, size_t x) { return c.AllReduce(x, NG_MPI_MIN); })
.def("Max", [](NgMPI_Comm & c, size_t x) { return c.AllReduce(x, NG_MPI_MAX); })
.def("SubComm", [](NgMPI_Comm & c, std::vector<int> proc_list) {
Array<int> procs(proc_list.size());
for (int i = 0; i < procs.Size(); i++)
{ procs[i] = proc_list[i]; }
if (!procs.Contains(c.Rank()))
{ throw Exception("rank "+ToString(c.Rank())+" not in subcomm"); }
return c.SubCommunicator(procs);
}, py::arg("procs"));
;
#ifdef PARALLEL
py::implicitly_convertible<mpi4py_comm, NgMPI_Comm>();
#endif // PARALLEL
}

View File

@ -2,38 +2,91 @@
#define NETGEN_REGISTER_ARCHIVE_HPP
#ifdef NETGEN_PYTHON
#include <memory>
#include <pybind11/pybind11.h>
#include <pybind11/cast.h>
#endif // NETGEN_PYTHON
#include <tuple>
#include "archive.hpp"
namespace ngcore {
// *************** Archiving functionality **************
template<typename T, typename ... Bases>
#ifdef NETGEN_PYTHON
template<typename T>
Archive& Archive :: Shallow(T& val)
{
static_assert(detail::is_any_pointer<T>, "ShallowArchive must be given pointer type!");
if(shallow_to_python)
{
if(is_output)
ShallowOutPython(pybind11::cast(val));
else
{
pybind11::object obj;
ShallowInPython(obj);
val = pybind11::cast<T>(obj);
}
}
else
*this & val;
return *this;
}
/*
// now using has_shared_from_this2 in archive.hpp
template <typename T>
struct has_shared_from_this
{
template <typename C> static std::true_type check( decltype( sizeof(&C::shared_from_this )) ) { return std::true_type(); }
template <typename> static std::false_type check(...) { return std::false_type(); }
typedef decltype( check<T>(sizeof(char)) ) type;
static constexpr type value = type();
};
*/
#endif // NETGEN_PYTHON
template<typename T, typename Bases=std::tuple<>>
class RegisterClassForArchive
{
public:
RegisterClassForArchive()
{
static_assert(detail::all_of_tmpl<std::is_base_of<Bases,T>::value...>,
"Variadic template arguments must be base classes of T");
static_assert(std::is_base_of<Bases, T>::value ||
detail::is_base_of_tuple<T, Bases>,
"Second argument must be base class or tuple of base classes of T");
detail::ClassArchiveInfo info {};
info.creator = [](const std::type_info& ti) -> void*
{ return typeid(T) == ti ? detail::constructIfPossible<T>()
: Archive::Caster<T, Bases...>::tryUpcast(ti, detail::constructIfPossible<T>()); };
info.upcaster = [/*this*/](const std::type_info& ti, void* p) -> void*
{ return typeid(T) == ti ? p : Archive::Caster<T, Bases...>::tryUpcast(ti, static_cast<T*>(p)); };
info.downcaster = [/*this*/](const std::type_info& ti, void* p) -> void*
{ return typeid(T) == ti ? p : Archive::Caster<T, Bases...>::tryDowncast(ti, p); };
#ifdef NETGEN_PYTHON
info.anyToPyCaster = [](const std::any& a)
info.creator = [](const std::type_info& ti, Archive& ar) -> void*
{
detail::TCargs<T> args;
ar &args;
auto nT = detail::constructIfPossible<T>(std::move(args));
return typeid(T) == ti ? nT
: Archive::Caster<T, Bases>::tryUpcast(ti, nT);
};
info.upcaster = [](const std::type_info& ti, void* p) -> void*
{ return typeid(T) == ti ? p : Archive::Caster<T, Bases>::tryUpcast(ti, static_cast<T*>(p)); };
info.downcaster = [](const std::type_info& ti, void* p) -> void*
{ return typeid(T) == ti ? p : Archive::Caster<T, Bases>::tryDowncast(ti, p); };
info.cargs_archiver = [](Archive &ar, void* p) {
if constexpr(detail::has_GetCArgs_v<T>)
ar << static_cast<T*>(p)->GetCArgs();
};
#ifdef NETGEN_PYTHON
info.anyToPyCaster = [](const std::any &a) {
if constexpr(has_shared_from_this2<T>::value) {
std::shared_ptr<T> val = std::any_cast<std::shared_ptr<T>>(a);
return pybind11::cast(val);
} else {
const T* val = std::any_cast<T>(&a);
return pybind11::cast(val); };
return pybind11::cast(val);
}
};
#endif // NETGEN_PYTHON
Archive::SetArchiveRegister(std::string(Demangle(typeid(T).name())),info);
}
};
Archive::SetArchiveRegister(std::string(Demangle(typeid(T).name())),info);
}
};
} // namespace ngcore
#endif // NETGEN_REGISTER_ARCHIVE_HPP

View File

@ -2,6 +2,7 @@
#define NGCORE_SIGNALS_HPP
#include <list>
#include <map>
#include <functional>
namespace ngcore
@ -43,6 +44,39 @@ namespace ngcore
}
inline bool GetEmitting() const { return is_emitting; }
};
class SimpleSignal
{
private:
// std::map<void*,std::function<void()>> funcs;
std::list<std::pair<void*,std::function<void()>>> funcs;
public:
SimpleSignal() = default;
template<typename FUNC>
void Connect(void* var, FUNC f)
{
// funcs[var] = f;
funcs.push_back ( { var, f } );
}
void Remove(void* var)
{
// funcs.erase(var);
funcs.remove_if([&] (auto var_f) { return var_f.first==var; });
}
inline void Emit()
{
for (auto [key,f] : funcs)
f();
}
};
} // namespace ngcore
#endif // NGCORE_SIGNALS_HPP

View File

@ -126,8 +126,14 @@ namespace ngcore
return SIMD<double,4> (HSum(a,b), HSum(c,d));
}
NETGEN_INLINE SIMD<double,2> SwapPairs (SIMD<double,2> a)
{
return __builtin_shufflevector(a.Data(), a.Data(), 1, 0);
}
// a*b+c
NETGEN_INLINE SIMD<double,2> FMA (SIMD<double,2> a, SIMD<double,2> b, SIMD<double,2> c)
{
@ -148,6 +154,16 @@ namespace ngcore
return FNMA(SIMD<double,2> (a), b, c);
}
// ARM complex mult:
// https://arxiv.org/pdf/1901.07294.pdf
// c += a*b (a0re, a0im, a1re, a1im, ...),
NETGEN_INLINE void FMAComplex (SIMD<double,2> a, SIMD<double,2> b, SIMD<double,2> & c)
{
auto tmp = vcmlaq_f64(c.Data(), a.Data(), b.Data()); // are * b
c = vcmlaq_rot90_f64(tmp, a.Data(), b.Data()); // += i*aim * b
}
NETGEN_INLINE SIMD<double,2> operator+ (SIMD<double,2> a, SIMD<double,2> b)
{ return a.Data()+b.Data(); }

View File

@ -61,6 +61,7 @@ namespace ngcore
NETGEN_INLINE auto operator[] (int i) const { return ((int64_t*)(&data))[i]; }
NETGEN_INLINE auto & operator[] (int i) { return ((int64_t*)(&data))[i]; }
NETGEN_INLINE __m512i Data() const { return data; }
NETGEN_INLINE __m512i & Data() { return data; }
static SIMD FirstInt() { return { 0, 1, 2, 3, 4, 5, 6, 7 }; }
@ -111,7 +112,7 @@ namespace ngcore
template <typename Function>
void SIMD_function (const Function & func, std::true_type)
{
data = (__m512){ func(7), func(6), func(5), func(4),
data = (__m512d){ func(7), func(6), func(5), func(4),
func(3), func(2), func(1), func(0) };
}
@ -132,6 +133,7 @@ namespace ngcore
}
NETGEN_INLINE double operator[] (int i) const { return ((double*)(&data))[i]; }
NETGEN_INLINE double & operator[] (int i) { return ((double*)(&data))[i]; }
NETGEN_INLINE __m512d Data() const { return data; }
NETGEN_INLINE __m512d & Data() { return data; }

View File

@ -18,16 +18,10 @@ namespace ngcore
{
#if defined __AVX512F__
#define NETGEN_DEFAULT_SIMD_SIZE 8
#define NETGEN_NATIVE_SIMD_SIZE 8
#elif defined __AVX__
#define NETGEN_DEFAULT_SIMD_SIZE 4
#define NETGEN_NATIVE_SIMD_SIZE 4
#elif defined NETGEN_ARCH_AMD64
#define NETGEN_DEFAULT_SIMD_SIZE 2
#define NETGEN_NATIVE_SIMD_SIZE 2
#else
#define NETGEN_DEFAULT_SIMD_SIZE 2
#define NETGEN_NATIVE_SIMD_SIZE 1
#endif
constexpr int GetDefaultSIMDSize() {
@ -36,9 +30,7 @@ namespace ngcore
constexpr bool IsNativeSIMDSize(int n) {
if(n==1) return true;
#if defined NETGEN_ARCH_AMD64 || defined __SSE__ || defined __aarch64__
if(n==2) return true;
#endif
#if defined __AVX__
if(n==4) return true;
#endif
@ -567,6 +559,15 @@ namespace ngcore
sum = FNMA(a,b,sum);
}
// c += a*b (a0re, a0im, a1re, a1im, ...),
template <int N>
void FMAComplex (SIMD<double,N> a, SIMD<double,N> b, SIMD<double,N> & c)
{
auto [are, aim] = Unpack(a, a);
SIMD<double,N> bswap = SwapPairs(b);
SIMD<double,N> aim_bswap = aim*bswap;
c += FMAddSub (are, b, aim_bswap);
}
template <int i, typename T, int N>
T get(SIMD<T,N> a) { return a.template Get<i>(); }

View File

@ -45,7 +45,7 @@ namespace ngcore
}
/// INDEX of symbol name, throws exception if unused
size_t Index (const std::string & name) const
size_t Index (std::string_view name) const
{
for (size_t i = 0; i < names.size(); i++)
if (names[i] == name) return i;
@ -53,7 +53,7 @@ namespace ngcore
}
/// Index of symbol name, returns -1 if unused
int CheckIndex (const std::string & name) const
int CheckIndex (std::string_view name) const
{
for (int i = 0; i < names.size(); i++)
if (names[i] == name) return i;
@ -67,12 +67,12 @@ namespace ngcore
}
/// Returns reference to element. exception for unused identifier
reference operator[] (const std::string & name)
reference operator[] (std::string_view name)
{
return data[Index (name)];
}
const_reference operator[] (const std::string & name) const
const_reference operator[] (std::string_view name) const
{
return data[Index (name)];
}
@ -99,7 +99,7 @@ namespace ngcore
}
/// Associates el to the string name, overrides if name is used
void Set (const std::string & name, const T & el)
void Set (std::string_view name, const T & el)
{
int i = CheckIndex (name);
if (i >= 0)
@ -107,15 +107,24 @@ namespace ngcore
else
{
data.push_back(el);
names.push_back(name);
names.push_back(std::string(name));
}
}
/*
bool Used (const std::string & name) const
{
return CheckIndex(name) >= 0;
}
*/
bool Used (std::string_view name) const
{
return CheckIndex(name) >= 0;
}
/// Deletes symboltable
inline void DeleteAll ()
{

View File

@ -62,9 +62,9 @@ namespace ngcore
return index;
}
NGCORE_API size_t * TablePrefixSum32 (FlatArray<unsigned int> entrysize)
NGCORE_API size_t * TablePrefixSum32 (FlatArray<uint32_t> entrysize)
{ return TablePrefixSum2 (entrysize); }
NGCORE_API size_t * TablePrefixSum64 (FlatArray<size_t> entrysize)
NGCORE_API size_t * TablePrefixSum64 (FlatArray<uint64_t> entrysize)
{ return TablePrefixSum2 (entrysize); }
/*

View File

@ -17,6 +17,7 @@
#include "ngcore_api.hpp"
#include "profiler.hpp"
namespace ngcore
{
@ -93,6 +94,7 @@ namespace ngcore
Iterator end() const { return Iterator(*this, BASE+size); }
};
/*
NGCORE_API extern size_t * TablePrefixSum32 (FlatArray<unsigned int> entrysize);
NGCORE_API extern size_t * TablePrefixSum64 (FlatArray<size_t> entrysize);
@ -105,7 +107,20 @@ namespace ngcore
{ return TablePrefixSum32 (FlatArray<unsigned> (entrysize.Size(), (unsigned int*)(std::atomic<int>*)entrysize.Addr(0))); }
NETGEN_INLINE size_t * TablePrefixSum (FlatArray<size_t> entrysize)
{ return TablePrefixSum64 (entrysize); }
*/
NGCORE_API extern size_t * TablePrefixSum32 (FlatArray<uint32_t> entrysize);
NGCORE_API extern size_t * TablePrefixSum64 (FlatArray<uint64_t> entrysize);
template <typename T> // TODO: enable_if T is integral
NETGEN_INLINE size_t * TablePrefixSum (FlatArray<T> entrysize)
{
if constexpr (sizeof(T) == 4)
return TablePrefixSum32 ( { entrysize.Size(), (uint32_t*)(void*)entrysize.Addr(0) });
else
return TablePrefixSum64 ( { entrysize.Size(), (uint64_t*)(void*)entrysize.Addr(0) });
}
/**
A compact Table container.
@ -130,6 +145,7 @@ namespace ngcore
{
for (size_t i : IntRange(size+1))
index[i] = i*entrysize;
mt.Alloc(GetMemUsage());
}
/// Construct table of variable entrysize
@ -141,6 +157,7 @@ namespace ngcore
index = TablePrefixSum (FlatArray<TI> (entrysize.Size(), entrysize.Data()));
size_t cnt = index[size];
data = new T[cnt];
mt.Alloc(GetMemUsage());
}
explicit NETGEN_INLINE Table (const FlatTable<T,IndexType> & tab2)
@ -157,6 +174,7 @@ namespace ngcore
size_t cnt = index[size];
data = new T[cnt];
this->AsArray() = tab2.AsArray();
mt.Alloc(GetMemUsage());
/*
for (size_t i = 0; i < cnt; i++)
data[i] = tab2.data[i];
@ -177,12 +195,14 @@ namespace ngcore
data = new T[cnt];
for (size_t i = 0; i < cnt; i++)
data[i] = tab2.data[i];
mt.Alloc(GetMemUsage());
}
NETGEN_INLINE Table (Table && tab2)
: FlatTable<T,IndexType>(0, nullptr, nullptr)
{
tab2.mt.Free(tab2.GetMemUsage());
mt = std::move(tab2.mt);
Swap (size, tab2.size);
Swap (index, tab2.index);
Swap (data, tab2.data);
@ -210,7 +230,7 @@ namespace ngcore
NETGEN_INLINE Table & operator= (Table && tab2)
{
mt.Swap(GetMemUsage(), tab2.mt, tab2.GetMemUsage());
mt = std::move(tab2.mt);
Swap (size, tab2.size);
Swap (index, tab2.index);
Swap (data, tab2.data);
@ -324,8 +344,8 @@ namespace ngcore
case 1:
{
size_t oldval = nd;
while (blocknr+1>nd) {
nd.compare_exchange_weak (oldval, blocknr+1);
while (blocknr-IndexBASE<IndexType>()+1>nd) {
nd.compare_exchange_weak (oldval, blocknr-IndexBASE<IndexType>()+1);
oldval = nd;
}
break;
@ -401,7 +421,7 @@ namespace ngcore
pcreator = std::make_unique<TableCreator<TEntry, TIndex>>(*cnt);
else
pcreator = std::make_unique<TableCreator<TEntry, TIndex>>();
auto & creator = *pcreator;
for ( ; !creator.Done(); creator++)
@ -447,7 +467,9 @@ namespace ngcore
void Add (size_t blocknr, FlatArray<int> dofs);
};
/**
A dynamic table class.

View File

@ -76,14 +76,14 @@ namespace ngcore
numa_run_on_node (0);
#endif
#ifndef WIN32
#if !defined(WIN32) && !defined(EMSCRIPTEN)
// master has maximal priority !
int policy;
struct sched_param param;
pthread_getschedparam(pthread_self(), &policy, &param);
param.sched_priority = sched_get_priority_max(policy);
pthread_setschedparam(pthread_self(), policy, &param);
#endif // WIN32
#endif // !defined(WIN32) && !defined(EMSCRIPTEN)
task_manager->StartWorkers();
@ -168,6 +168,12 @@ namespace ngcore
trace = nullptr;
}
num_threads = 1;
#ifdef USE_NUMA
for (int j = 0; j < num_nodes; j++)
numa_free (nodedata[j], sizeof(NodeData));
#else
delete nodedata[0];
#endif
}
#ifdef WIN32
@ -412,7 +418,7 @@ namespace ngcore
}
}
catch (Exception e)
catch (Exception & e)
{
{
lock_guard<mutex> guard(copyex_mutex);
@ -548,7 +554,7 @@ namespace ngcore
}
}
catch (Exception e)
catch (Exception & e)
{
{
// cout << "got exception in TM" << endl;

View File

@ -10,6 +10,7 @@
#include <atomic>
#include <functional>
#include <list>
#include <cmath>
#include <ostream>
#include <thread>
@ -316,6 +317,7 @@ namespace ngcore
public:
SharedLoop (IntRange ar) : r(ar) { cnt = r.begin(); }
SharedLoop (size_t s) : SharedLoop (IntRange{s}) { ; }
SharedIterator begin() { return SharedIterator (cnt, r.end(), true); }
SharedIterator end() { return SharedIterator (cnt, r.end(), false); }
};
@ -622,6 +624,8 @@ public:
Reset (r);
}
SharedLoop2 (size_t s) : SharedLoop2 (IntRange{s}) { }
void Reset (IntRange r)
{
for (size_t i = 0; i < ranges.Size(); i++)
@ -631,6 +635,9 @@ public:
participants.store(0, std::memory_order_relaxed);
processed.store(0, std::memory_order_release);
}
void Reset (size_t s) { Reset(IntRange{s}); }
SharedIterator begin()
{
@ -1010,7 +1017,7 @@ public:
int num_nodes = numa_num_configured_nodes();
size_t pagesize = numa_pagesize();
int npages = ceil ( double(s)*sizeof(T) / pagesize );
int npages = std::ceil ( double(s)*sizeof(T) / pagesize );
// cout << "size = " << numa_size << endl;
// cout << "npages = " << npages << endl;

View File

@ -16,6 +16,15 @@ namespace ngcore
template<typename T>
struct is_any_pointer_impl : std::false_type {};
// check if second template argument is tuple of base classes to first
// template argument, return constexpr bool
template<typename T, typename Tuple>
constexpr bool is_base_of_tuple = false;
template<typename T, typename... Ts>
constexpr bool is_base_of_tuple<T, std::tuple<Ts...>> =
all_of_tmpl<std::is_base_of<Ts, T>::value...>;
template<typename T>
struct is_any_pointer_impl<T*> : std::true_type {};

View File

@ -3,16 +3,25 @@
#include "logging.hpp"
#include "simd_generic.hpp"
#ifndef WIN32
#ifdef WIN32
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#undef WIN32_LEAN_AND_MEAN
#else // WIN32
#include <cxxabi.h>
#endif
#include <dlfcn.h>
#endif //WIN32
//
#include <array>
#include <filesystem>
#include <iostream>
#include <regex>
#include <string>
#include <thread>
#include "ngstream.hpp"
namespace ngcore
{
namespace detail
@ -43,8 +52,16 @@ namespace ngcore
*/
std::string CleanupDemangledName( std::string s )
{
//for(const auto & [r, sub] : demangle_regexes)
// s = std::regex_replace (s,r,sub);
for(const auto & [r, sub] : demangle_regexes)
s = std::regex_replace (s,r,sub);
#ifdef EMSCRIPTEN
// for some reason regex_replace is not working at all
std::string temp = s;
s = "";
for(auto c : temp)
if(c!=' ')
s+=c;
#endif // EMSCRIPTEN
return s;
}
@ -103,7 +120,7 @@ namespace ngcore
const std::chrono::time_point<TClock> wall_time_start = TClock::now();
int printmessage_importance = 0;
int printmessage_importance = getenv("NG_MESSAGE_LEVEL") ? atoi(getenv("NG_MESSAGE_LEVEL")) : 0;
bool NGSOStream :: glob_active = true;
NGCORE_API int GetCompiledSIMDSize()
@ -128,5 +145,91 @@ namespace ngcore
return path;
}
SharedLibrary :: SharedLibrary(const std::filesystem::path & lib_name_, std::optional<std::filesystem::path> directory_to_delete_, bool global )
: lib_name(lib_name_),directory_to_delete(directory_to_delete_)
{
Load(lib_name, global);
}
SharedLibrary :: ~SharedLibrary()
{
Unload();
if(directory_to_delete)
for([[maybe_unused]] auto i : Range(5))
{
// on Windows, a (detached?) child process of the compiler/linker might still block the directory
// wait for it to finish (up to a second)
try
{
std::filesystem::remove_all(*directory_to_delete);
directory_to_delete = std::nullopt;
break;
}
catch(const std::exception &e)
{
std::this_thread::sleep_for(std::chrono::milliseconds(200));
}
}
if(directory_to_delete)
std::cerr << "Could not delete " << directory_to_delete->string() << std::endl;
}
void SharedLibrary :: Load( const std::filesystem::path & lib_name_, bool global )
{
Unload();
lib_name = lib_name_;
#ifdef WIN32
lib = LoadLibraryW(lib_name.wstring().c_str());
if (!lib) throw std::runtime_error(std::string("Could not load library ") + lib_name.string());
#else // WIN32
auto flags = RTLD_NOW;
if (global) flags |= RTLD_GLOBAL;
lib = dlopen(lib_name.c_str(), flags);
if(lib == nullptr) throw std::runtime_error(dlerror());
#endif // WIN32
}
void SharedLibrary :: Unload() {
if(lib)
{
#ifdef WIN32
FreeLibrary((HMODULE)lib);
#else // WIN32
int rc = dlclose(lib);
if(rc != 0) std::cerr << "Failed to close library " << lib_name << std::endl;
#endif // WIN32
}
}
void* SharedLibrary :: GetRawSymbol( std::string func_name )
{
#ifdef WIN32
void* func = GetProcAddress((HMODULE)lib, func_name.c_str());
if(func == nullptr)
throw std::runtime_error(std::string("Could not find function ") + func_name + " in library " + lib_name.string());
#else // WIN32
void* func = dlsym(lib, func_name.c_str());
if(func == nullptr)
throw std::runtime_error(dlerror());
#endif // WIN32
return func;
}
void* GetRawSymbol( std::string func_name )
{
void * func = nullptr;
#ifdef WIN32
throw std::runtime_error("GetRawSymbol not implemented on WIN32");
#else // WIN32
func = dlsym(RTLD_DEFAULT, func_name.c_str());
if(func == nullptr)
throw std::runtime_error(dlerror());
#endif // WIN32
return func;
}
} // namespace ngcore

View File

@ -6,6 +6,7 @@
#include <filesystem>
#include <map>
#include <ostream>
#include <optional>
#include <sstream>
#include <string>
@ -71,6 +72,8 @@ namespace ngcore
unsigned long long tics;
__asm __volatile("mrs %0, CNTVCT_EL0" : "=&r" (tics));
return tics;
#elif defined(__EMSCRIPTEN__)
return std::chrono::high_resolution_clock::now().time_since_epoch().count();
#else
#warning "Unsupported CPU architecture"
return 0;
@ -179,7 +182,7 @@ namespace ngcore
/// square element
template <class T>
NETGEN_INLINE T sqr (const T a)
NETGEN_INLINE constexpr T sqr (const T a)
{
return a * a;
}
@ -251,6 +254,27 @@ namespace ngcore
template <int N> using IC = std::integral_constant<int,N>; // needed for Iterate
namespace detail {
template <typename T, typename Enable = int>
struct IsIC_trait {
static constexpr auto check() { return false; }
};
template <typename T>
struct IsIC_trait<T, std::enable_if_t<std::is_same_v<T, IC<T::value>> == true, int> > {
static constexpr auto check() { return true; }
};
}
template <typename T>
constexpr bool is_IC() {
return detail::IsIC_trait<T>::check();
}
template <int NUM, typename FUNC>
NETGEN_INLINE void Iterate (FUNC f)
@ -324,6 +348,41 @@ namespace ngcore
NGCORE_API std::filesystem::path GetTempFilename();
NGCORE_API void* GetRawSymbol( std::string func_name );
template <typename TFunc>
TFunc GetSymbol( std::string func_name )
{
return reinterpret_cast<TFunc>(GetRawSymbol(func_name));
}
// Class to handle/load shared libraries
class NGCORE_API SharedLibrary
{
std::filesystem::path lib_name;
std::optional<std::filesystem::path> directory_to_delete = std::nullopt;
void *lib = nullptr;
public:
SharedLibrary() = default;
SharedLibrary(const std::filesystem::path & lib_name_, std::optional<std::filesystem::path> directory_to_delete_ = std::nullopt, bool global = false );
SharedLibrary(const SharedLibrary &) = delete;
SharedLibrary & operator =(const SharedLibrary &) = delete;
~SharedLibrary();
template <typename TFunc>
TFunc GetSymbol( std::string func_name )
{
return reinterpret_cast<TFunc>(GetRawSymbol(func_name));
}
void Load( const std::filesystem::path & lib_name_, bool global = true);
void Unload();
void* GetRawSymbol( std::string func_name );
};
} // namespace ngcore
#endif // NETGEN_CORE_UTILS_HPP

View File

@ -1211,7 +1211,7 @@ namespace netgen
PrintMessage (2, "Object ", i, " has ", tams->GetNT(), " triangles");
}
}
catch (exception)
catch (const std::exception &)
{
cerr << "*************************************************************" << endl
<< "**** out of memory problem in CSG visualization ****" << endl

View File

@ -18,7 +18,6 @@ namespace netgen
class TriangleApproximation;
class TATriangle;
/**
A top level object is an entity to be meshed.
I can be either a solid, or one surface patch of a solid.

View File

@ -567,7 +567,7 @@ namespace netgen
{
// int i, j;
SegmentIndex si;
PointIndex pi;
// PointIndex pi;
NgArray<int> osedges(cntedge);
INDEX_2_HASHTABLE<int> osedgesht (cntedge+1);
@ -610,7 +610,7 @@ namespace netgen
for (int i = 1; i <= osedgesht.GetNBags(); i++)
for (int j = 1; j <= osedgesht.GetBagSize(i); j++)
{
INDEX_2 i2;
PointIndices<2> i2;
int val;
osedgesht.GetData (i, j, i2, val);
@ -619,8 +619,8 @@ namespace netgen
Vec<3> v = p2 - p1;
double vlen = v.Length();
v /= vlen;
for (pi = PointIndex::BASE;
pi < mesh.GetNP()+PointIndex::BASE; pi++)
for (PointIndex pi = IndexBASE<PointIndex>();
pi < mesh.GetNP()+IndexBASE<PointIndex>(); pi++)
if (pi != i2.I1() && pi != i2.I2())
{
@ -1371,8 +1371,8 @@ namespace netgen
lastpi = PointIndex::INVALID;
/*
for (pi = PointIndex::BASE;
pi < mesh.GetNP()+PointIndex::BASE; pi++)
for (pi = IndexBASE<PointIndex>();
pi < mesh.GetNP()+IndexBASE<PointIndex>(); pi++)
if (Dist (mesh[pi], p) < 1e-6)
{
lastpi = pi;
@ -1414,8 +1414,8 @@ namespace netgen
if (i == ne)
{
/*
for (pi = PointIndex::BASE;
pi < mesh.GetNP()+PointIndex::BASE; pi++)
for (pi = IndexBASE<PointIndex>();
pi < mesh.GetNP()+IndexBASE<PointIndex>(); pi++)
if (Dist(mesh[pi], np) < 1e-6)
thispi = pi;
*/
@ -1539,8 +1539,8 @@ namespace netgen
// generate initial point
Point<3> p = edgepoints[0];
PointIndex pi1 = PointIndex::INVALID;
for (pi = PointIndex::BASE;
pi < mesh.GetNP()+PointIndex::BASE; pi++)
for (PointIndex pi = IndexBASE<PointIndex>();
pi < mesh.GetNP()+IndexBASE<PointIndex>(); pi++)
if (Dist (mesh[pi], p) < 1e-6*geometry.MaxSize())
{
@ -1557,8 +1557,8 @@ namespace netgen
p = edgepoints.Last();
PointIndex pi2 = PointIndex::INVALID;
for (pi = PointIndex::BASE;
pi < mesh.GetNP()+PointIndex::BASE; pi++)
for (pi = IndexBASE<PointIndex>();
pi < mesh.GetNP()+IndexBASE<PointIndex>(); pi++)
if (Dist (mesh[pi], p) < 1e-6*geometry.MaxSize())
{
@ -1646,7 +1646,7 @@ namespace netgen
Mesh & mesh)
{
int k;
PointIndex pi;
// PointIndex pi;
double size = geometry.MaxSize();
@ -1660,8 +1660,8 @@ namespace netgen
PointIndex frompi = PointIndex::INVALID;
PointIndex topi = PointIndex::INVALID;
for (pi = PointIndex::BASE;
pi < mesh.GetNP()+PointIndex::BASE; pi++)
for (PointIndex pi = IndexBASE<PointIndex>();
pi < mesh.GetNP()+IndexBASE<PointIndex>(); pi++)
{
if (Dist2 (mesh[pi], fromp) <= 1e-16*size)
frompi = pi;
@ -1714,12 +1714,12 @@ namespace netgen
if (oldseg.seginfo == 0)
continue;
int pi1 = oldseg[0];
int pi2 = oldseg[1];
PointIndex pi1 = oldseg[0];
PointIndex pi2 = oldseg[1];
int npi1 = geometry.identifications.Get(copyedgeidentification)
PointIndex npi1 = geometry.identifications.Get(copyedgeidentification)
-> GetIdentifiedPoint (mesh, pi1);
int npi2 = geometry.identifications.Get(copyedgeidentification)
PointIndex npi2 = geometry.identifications.Get(copyedgeidentification)
-> GetIdentifiedPoint (mesh, pi2);
//(*testout) << "copy edge, pts = " << npi1 << " - " << npi2 << endl;
@ -1885,12 +1885,10 @@ namespace netgen
if (seg1.domin != -1 || seg1.domout != -1)
{
mesh.AddPoint (p1, layer, EDGEPOINT);
mesh.AddPoint (p2, layer, EDGEPOINT);
seg1[0] = mesh.GetNP()-1;
seg1[1] = mesh.GetNP();
seg2[1] = mesh.GetNP()-1;
seg2[0] = mesh.GetNP();
seg1[0] = mesh.AddPoint (p1, layer, EDGEPOINT);
seg1[1] = mesh.AddPoint (p2, layer, EDGEPOINT);
seg2[0] = seg1[1];
seg2[1] = seg1[0];
seg1.geominfo[0].trignum = 1;
seg1.geominfo[1].trignum = 1;
seg2.geominfo[0].trignum = 1;

View File

@ -35,7 +35,7 @@ namespace netgen
auto up = geom.GetUserPoint(i);
auto pnum = mesh.AddPoint(up);
mesh.Points().Last().Singularity (geom.GetUserPointRefFactor(i));
mesh.AddLockedPoint (PointIndex (i+1));
mesh.AddLockedPoint (pnum);
int index = up.GetIndex();
if (index == -1)
index = mesh.AddCD3Name (up.GetName())+1;
@ -443,7 +443,7 @@ namespace netgen
meshing.SetStartTime (starttime);
double eps = 1e-8 * geom.MaxSize();
for (PointIndex pi = PointIndex::BASE; pi < noldp+PointIndex::BASE; pi++)
for (PointIndex pi = IndexBASE<PointIndex>(); pi < noldp+IndexBASE<PointIndex>(); pi++)
{
// if(surf->PointOnSurface(mesh[pi]))
meshing.AddPoint (mesh[pi], pi, NULL,
@ -473,8 +473,8 @@ namespace netgen
{
PointGeomInfo gi;
gi.trignum = k;
meshing.AddBoundaryElement (segments[si][0] + 1 - PointIndex::BASE,
segments[si][1] + 1 - PointIndex::BASE,
meshing.AddBoundaryElement (segments[si][0] + 1 - IndexBASE<PointIndex>(),
segments[si][1] + 1 - IndexBASE<PointIndex>(),
gi, gi);
}
@ -718,7 +718,7 @@ namespace netgen
mesh -> LoadLocalMeshSize (mparam.meshsizefilename);
for (auto mspnt : mparam.meshsize_points)
mesh -> RestrictLocalH (mspnt.pnt, mspnt.h);
mesh -> RestrictLocalH (mspnt.pnt, mspnt.h, mspnt.layer);
}
spoints.SetSize(0);
@ -826,6 +826,9 @@ namespace netgen
{
multithread.task = "Volume meshing";
for (int i = 0; i < geom.GetNTopLevelObjects(); i++)
mesh->SetMaterial (i+1, geom.GetTopLevelObject(i)->GetMaterial().c_str());
MESHING3_RESULT res =
MeshVolume (mparam, *mesh);
@ -838,10 +841,6 @@ namespace netgen
MeshQuality3d (*mesh);
for (int i = 0; i < geom.GetNTopLevelObjects(); i++)
mesh->SetMaterial (i+1, geom.GetTopLevelObject(i)->GetMaterial().c_str());
#ifdef STAT_STREAM
(*statout) << GetTime() << " & ";
#endif

View File

@ -65,10 +65,10 @@ ShortEdge (const SpecialPoint & sp1, const SpecialPoint & sp2) const
return 0;
}
int Identification :: GetIdentifiedPoint (class Mesh & mesh, int pi)
PointIndex Identification :: GetIdentifiedPoint (class Mesh & mesh, PointIndex pi)
{
cout << "Identification::GetIdentifiedPoint called for base-class" << endl;
return -1;
return PointIndex::INVALID;
}
void Identification :: IdentifyPoints (Mesh & mesh)
@ -261,8 +261,8 @@ Identifiable (const Point<3> & p1, const Point<3> & p2) const
int PeriodicIdentification ::
GetIdentifiedPoint (class Mesh & mesh, int pi)
PointIndex PeriodicIdentification ::
GetIdentifiedPoint (class Mesh & mesh, PointIndex pi)
{
const Surface *snew;
const Point<3> & p = mesh.Point (pi);
@ -289,14 +289,14 @@ GetIdentifiedPoint (class Mesh & mesh, int pi)
// project to other surface
snew->Project (hp);
int newpi = 0;
for (int i = 1; i <= mesh.GetNP(); i++)
if (Dist2 (mesh.Point(i), hp) < 1e-12)
PointIndex newpi(PointIndex::INVALID);
for (PointIndex pi : Range(mesh.Points()))
if (Dist2 (mesh.Point(pi), hp) < 1e-12)
{
newpi = i;
newpi = pi;
break;
}
if (!newpi)
if (!newpi.IsValid())
newpi = mesh.AddPoint (hp);
if (snew == s2)
@ -322,6 +322,7 @@ void PeriodicIdentification :: IdentifyPoints (class Mesh & mesh)
mesh.GetBox(p1, p2);
auto eps = 1e-6 * (p2-p1).Length();
/*
for (int i = 1; i <= mesh.GetNP(); i++)
{
Point<3> p = mesh.Point(i);
@ -334,13 +335,24 @@ void PeriodicIdentification :: IdentifyPoints (class Mesh & mesh)
if (Dist2(mesh.Point(j), pp) < eps)
{
mesh.GetIdentifications().Add (i, j, nr);
/*
(*testout) << "Identify points(periodic:), nr = " << nr << ": "
<< mesh.Point(i) << " - " << mesh.Point(j) << endl;
*/
}
}
}
*/
for (auto pi : Range(mesh.Points()))
{
Point<3> p = mesh[pi];
if (s1->PointOnSurface (p))
{
Point<3> pp = p;
pp = trafo(pp);
s2->Project (pp);
for (PointIndex pj : Range(mesh.Points()))
if (Dist2(mesh[pj], pp) < eps)
mesh.GetIdentifications().Add (pi, pj, nr);
}
}
mesh.GetIdentifications().SetType(nr,Identifications::PERIODIC);
}
@ -396,15 +408,15 @@ void PeriodicIdentification :: IdentifyFaces (class Mesh & mesh)
if (side == 1)
{
if (mesh.GetIdentifications().Get (seg1[0], seg2[0]) &&
mesh.GetIdentifications().Get (seg1[1], seg2[1]))
if (mesh.GetIdentifications().Used (seg1[0], seg2[0]) &&
mesh.GetIdentifications().Used (seg1[1], seg2[1]))
{
foundother = 1;
break;
}
if (mesh.GetIdentifications().Get (seg1[0], seg2[1]) &&
mesh.GetIdentifications().Get (seg1[1], seg2[0]))
if (mesh.GetIdentifications().Used (seg1[0], seg2[1]) &&
mesh.GetIdentifications().Used (seg1[1], seg2[0]))
{
foundother = 1;
break;
@ -412,15 +424,15 @@ void PeriodicIdentification :: IdentifyFaces (class Mesh & mesh)
}
else
{
if (mesh.GetIdentifications().Get (seg2[0], seg1[0]) &&
mesh.GetIdentifications().Get (seg2[1], seg1[1]))
if (mesh.GetIdentifications().Used (seg2[0], seg1[0]) &&
mesh.GetIdentifications().Used (seg2[1], seg1[1]))
{
foundother = 1;
break;
}
if (mesh.GetIdentifications().Get (seg2[0], seg1[1]) &&
mesh.GetIdentifications().Get (seg2[1], seg1[0]))
if (mesh.GetIdentifications().Used (seg2[0], seg1[1]) &&
mesh.GetIdentifications().Used (seg2[1], seg1[0]))
{
foundother = 1;
break;
@ -885,17 +897,21 @@ ShortEdge (const SpecialPoint & sp1, const SpecialPoint & sp2) const
int CloseSurfaceIdentification ::
GetIdentifiedPoint (class Mesh & mesh, int pi)
PointIndex CloseSurfaceIdentification ::
GetIdentifiedPoint (class Mesh & mesh, PointIndex pi)
{
const Surface *snew;
const Point<3> & p = mesh.Point (pi);
NgArray<int,PointIndex::BASE> identmap(mesh.GetNP());
idmap_type identmap(mesh.GetNP());
mesh.GetIdentifications().GetMap (nr, identmap);
/*
if (identmap.Get(pi))
return identmap.Get(pi);
*/
if (identmap[pi].IsValid())
return identmap[pi];
if (s1->PointOnSurface (p))
snew = s2;
@ -1168,15 +1184,15 @@ void CloseSurfaceIdentification :: IdentifyFaces (class Mesh & mesh)
if (side == 1)
{
if (mesh.GetIdentifications().Get (seg1[0], seg2[0]) &&
mesh.GetIdentifications().Get (seg1[1], seg2[1]))
if (mesh.GetIdentifications().Used (seg1[0], seg2[0]) &&
mesh.GetIdentifications().Used (seg1[1], seg2[1]))
{
foundother = 1;
break;
}
if (mesh.GetIdentifications().Get (seg1[0], seg2[1]) &&
mesh.GetIdentifications().Get (seg1[1], seg2[0]))
if (mesh.GetIdentifications().Used (seg1[0], seg2[1]) &&
mesh.GetIdentifications().Used (seg1[1], seg2[0]))
{
foundother = 1;
break;
@ -1184,15 +1200,15 @@ void CloseSurfaceIdentification :: IdentifyFaces (class Mesh & mesh)
}
else
{
if (mesh.GetIdentifications().Get (seg2[0], seg1[0]) &&
mesh.GetIdentifications().Get (seg2[1], seg1[1]))
if (mesh.GetIdentifications().Used (seg2[0], seg1[0]) &&
mesh.GetIdentifications().Used (seg2[1], seg1[1]))
{
foundother = 1;
break;
}
if (mesh.GetIdentifications().Get (seg2[0], seg1[1]) &&
mesh.GetIdentifications().Get (seg2[1], seg1[0]))
if (mesh.GetIdentifications().Used (seg2[0], seg1[1]) &&
mesh.GetIdentifications().Used (seg2[1], seg1[0]))
{
foundother = 1;
break;
@ -1229,7 +1245,7 @@ BuildSurfaceElements (NgArray<Segment> & segs,
bool found = 0;
int cntquads = 0;
NgArray<int,PointIndex::BASE> identmap;
idmap_type identmap;
identmap = 0;
mesh.GetIdentifications().GetMap (nr, identmap);
@ -1650,8 +1666,8 @@ BuildSurfaceElements (NgArray<Segment> & segs,
{
const Segment & s1 = segs.Get(i1);
const Segment & s2 = segs.Get(i2);
if (mesh.GetIdentifications().Get (s1[0], s2[1]) &&
mesh.GetIdentifications().Get (s1[1], s2[0]))
if (mesh.GetIdentifications().Used (s1[0], s2[1]) &&
mesh.GetIdentifications().Used (s1[1], s2[0]))
{
Element2d el(QUAD);
el.PNum(1) = s1[0];

View File

@ -56,7 +56,7 @@ namespace netgen
virtual void IdentifyFaces (class Mesh & mesh);
/// get point on other surface, add entry in mesh identifications
virtual int GetIdentifiedPoint (class Mesh & mesh, int pi1);
virtual PointIndex GetIdentifiedPoint (class Mesh & mesh, PointIndex pi1);
/// copy surfaces, or fill rectangles
virtual void BuildSurfaceElements (NgArray<class Segment> & segs,
@ -97,7 +97,7 @@ namespace netgen
const TABLE<int> & specpoint2surface) const override;
virtual int Identifiable (const Point<3> & p1, const Point<3> & sp2) const override;
virtual int GetIdentifiedPoint (class Mesh & mesh, int pi1) override;
virtual PointIndex GetIdentifiedPoint (class Mesh & mesh, PointIndex pi1) override;
virtual void IdentifyPoints (class Mesh & mesh) override;
virtual void IdentifyFaces (class Mesh & mesh) override;
virtual void BuildSurfaceElements (NgArray<class Segment> & segs,
@ -153,7 +153,7 @@ namespace netgen
virtual int Identifiable (const Point<3> & p1, const Point<3> & sp2) const;
virtual int IdentifiableCandidate (const SpecialPoint & sp1) const;
virtual int ShortEdge (const SpecialPoint & sp1, const SpecialPoint & sp2) const;
virtual int GetIdentifiedPoint (class Mesh & mesh, int pi1);
virtual PointIndex GetIdentifiedPoint (class Mesh & mesh, PointIndex pi1);
const Array<double> & GetSlices () const { return slices; }
virtual void IdentifyPoints (class Mesh & mesh);
virtual void IdentifyFaces (class Mesh & mesh);

View File

@ -583,8 +583,8 @@ However, when r = 0, the top part becomes a point(tip) and meshing fails!
NgArray<int> si1, si2;
s1->GetSolid()->GetSurfaceIndices (si1);
s2->GetSolid()->GetSurfaceIndices (si2);
cout << "surface ids1 = " << si1 << endl;
cout << "surface ids2 = " << si2 << endl;
cout << IM(3) << "surface ids1 = " << si1 << endl;
cout << IM(3) << "surface ids2 = " << si2 << endl;
Flags flags;
const TopLevelObject * domain = nullptr;
@ -756,10 +756,8 @@ However, when r = 0, the top part becomes a point(tip) and meshing fails!
{
MeshingParameters mp;
if(pars) mp = *pars;
{
py::gil_scoped_acquire aq;
CreateMPfromKwargs(mp, kwargs);
}
CreateMPfromKwargs(mp, kwargs);
py::gil_scoped_release gil_rel;
auto mesh = make_shared<Mesh>();
SetGlobalMesh (mesh);
mesh->SetGeometry(geo);
@ -770,8 +768,7 @@ However, when r = 0, the top part becomes a point(tip) and meshing fails!
throw Exception("Meshing failed!");
return mesh;
}, py::arg("mp") = nullptr,
meshingparameter_description.c_str(),
py::call_guard<py::gil_scoped_release>())
meshingparameter_description.c_str())
;
m.def("Save", FunctionPointer

View File

@ -781,7 +781,7 @@ namespace netgen
Point<2> p2d;
faces[0]->CalcProj(p,p2d);
int intersections_before(0), intersections_after(0);
[[maybe_unused]] int intersections_before(0), intersections_after(0);
double randomx = 7.42357;
double randomy = 1.814756;
double randomlen = sqrt(randomx*randomx+randomy*randomy);

View File

@ -53,7 +53,7 @@ void SingularEdge :: FindPointsOnEdge (class Mesh & mesh)
for (SegmentIndex si = 0; si < mesh.GetNSeg(); si++)
{
INDEX_2 i2 (mesh[si][0], mesh[si][1]);
PointIndices<2> i2 (mesh[si][0], mesh[si][1]);
/*
bool onedge = 1;
@ -93,8 +93,8 @@ void SingularEdge :: FindPointsOnEdge (class Mesh & mesh)
{
segms.Append (i2);
// PrintMessage (5, "sing segment ", i2.I1(), " - ", i2.I2());
points.Append (mesh[ PointIndex (i2.I1())]);
points.Append (mesh[ PointIndex (i2.I2())]);
points.Append (mesh[i2.I1()]);
points.Append (mesh[i2.I2()]);
mesh[si].singedge_left = factor;
mesh[si].singedge_right = factor;
}
@ -153,8 +153,8 @@ void SingularPoint :: FindPoints (class Mesh & mesh)
NgArray<int> surfk, surf;
for (PointIndex pi = PointIndex::BASE;
pi < mesh.GetNP()+PointIndex::BASE; pi++)
for (PointIndex pi = IndexBASE<PointIndex>();
pi < mesh.GetNP()+IndexBASE<PointIndex>(); pi++)
{
if (mesh[pi].Type() != FIXEDPOINT) continue;
const Point<3> p = mesh[pi];

View File

@ -580,5 +580,5 @@ void ProjectToEdge (const Surface * f1, const Surface * f2, Point<3> & hp)
RegisterClassForArchive<Surface> regsurf;
RegisterClassForArchive<Primitive> regprim;
RegisterClassForArchive<OneSurfacePrimitive, Surface, Primitive> regosf;
RegisterClassForArchive<OneSurfacePrimitive, tuple<Surface, Primitive>> regosf;
}

View File

@ -343,7 +343,7 @@ namespace netgen
const Point3d p = Center (p1, p2);
glRasterPos3d (p.X(), p.Y(), p.Z());
sprintf (buf, "%d", seg.edgenr);
snprintf (buf, sizeof(buf), "%d", seg.edgenr);
// glCallLists (GLsizei(strlen (buf)), GL_UNSIGNED_BYTE, buf);
MyOpenGLText (buf);
}
@ -393,9 +393,9 @@ namespace netgen
glBitmap (7, 7, 3, 3, 0, 0, &knoedel[0]);
}
*/
for (const Point3d & p : mesh->Points())
for (Point<3> p : mesh->Points())
{
glRasterPos3d (p.X(), p.Y(), p.Z());
glRasterPos3d (p(0), p(1), p(2));
glBitmap (7, 7, 3, 3, 0, 0, &knoedel[0]);
}
}
@ -418,7 +418,7 @@ namespace netgen
const Point3d & p = mesh->Point(i);
glRasterPos3d (p.X(), p.Y(), p.Z());
sprintf (buf, "%d", int(i));
snprintf (buf, sizeof(buf), "%d", int(i));
// glCallLists (GLsizei(strlen (buf)), GL_UNSIGNED_BYTE, buf);
MyOpenGLText (buf);
}
@ -472,7 +472,8 @@ namespace netgen
box = Box3d (Point3d (0,0,0), Point3d (1,1,1));
}
if (zoomall == 2 && ((vispar.centerpoint >= 1 && vispar.centerpoint <= mesh->GetNP()) ||
if (zoomall == 2 && ((vispar.centerpoint-IndexBASE<PointIndex>() >= 0 &&
vispar.centerpoint-IndexBASE<PointIndex>() < mesh->GetNP()) ||
vispar.use_center_coords))
{
if (vispar.use_center_coords)

View File

@ -45,9 +45,10 @@ namespace netgen
void MakePrismsSingEdge (Mesh & mesh, INDEX_2_HASHTABLE<int> & singedges)
{
// volume elements
for (int i = 1; i <= mesh.GetNE(); i++)
// for (int i = 1; i <= mesh.GetNE(); i++)
for (ElementIndex ei = 0; ei < mesh.GetNE(); ei++)
{
Element & el = mesh.VolumeElement(i);
Element & el = mesh.VolumeElement(ei);
if (el.GetType() != TET) continue;
for (int j = 1; j <= 3; j++)
@ -76,9 +77,9 @@ namespace netgen
}
// surface elements
for (int i = 1; i <= mesh.GetNSE(); i++)
for (SurfaceElementIndex sei = 0; sei < mesh.GetNSE(); sei++)
{
Element2d & el = mesh.SurfaceElement(i);
Element2d & el = mesh.SurfaceElement(sei);
if (el.GetType() != TRIG) continue;
for (int j = 1; j <= 3; j++)
@ -110,18 +111,18 @@ namespace netgen
*/
void MakePrismsClosePoints (Mesh & mesh)
{
int i, j, k;
for (i = 1; i <= mesh.GetNE(); i++)
// int i, j, k;
for (ElementIndex ei = 0; ei < mesh.GetNE(); ei++)
{
Element & el = mesh.VolumeElement(i);
Element & el = mesh.VolumeElement(ei);
if (el.GetType() == TET)
{
for (j = 1; j <= 3; j++)
for (k = j+1; k <= 4; k++)
for (int j = 1; j <= 3; j++)
for (int k = j+1; k <= 4; k++)
{
INDEX_2 edge(el.PNum(j), el.PNum(k));
edge.Sort();
if (mesh.GetIdentifications().GetSymmetric (el.PNum(j), el.PNum(k)))
if (mesh.GetIdentifications().UsedSymmetric (el.PNum(j), el.PNum(k)))
{
int pi3 = 1, pi4 = 1;
while (pi3 == j || pi3 == k) pi3++;
@ -145,7 +146,7 @@ namespace netgen
{
// pyramid, base face = 1,2,3,4
for (j = 0; j <= 1; j++)
for (int j = 0; j <= 1; j++)
{
PointIndex pi1 = el.PNum( (j+0) % 4 + 1);
PointIndex pi2 = el.PNum( (j+1) % 4 + 1);
@ -157,8 +158,8 @@ namespace netgen
INDEX_2 edge2(pi2, pi3);
edge1.Sort();
edge2.Sort();
if (mesh.GetIdentifications().GetSymmetric (pi1, pi4) &&
mesh.GetIdentifications().GetSymmetric (pi2, pi3))
if (mesh.GetIdentifications().UsedSymmetric (pi1, pi4) &&
mesh.GetIdentifications().UsedSymmetric (pi2, pi3))
{
//int p3 = el.PNum(pi3);
//int p4 = el.PNum(pi4);
@ -175,18 +176,18 @@ namespace netgen
}
}
for (i = 1; i <= mesh.GetNSE(); i++)
for (SurfaceElementIndex sei = 0; sei < mesh.GetNSE(); sei++)
{
Element2d & el = mesh.SurfaceElement(i);
Element2d & el = mesh.SurfaceElement(sei);
if (el.GetType() != TRIG) continue;
for (j = 1; j <= 3; j++)
for (int j = 1; j <= 3; j++)
{
k = (j % 3) + 1;
int k = (j % 3) + 1;
INDEX_2 edge(el.PNum(j), el.PNum(k));
edge.Sort();
if (mesh.GetIdentifications().GetSymmetric (el.PNum(j), el.PNum(k)))
if (mesh.GetIdentifications().UsedSymmetric (el.PNum(j), el.PNum(k)))
{
int pi3 = 6-j-k;
int p3 = el.PNum(pi3);
@ -244,7 +245,7 @@ namespace netgen
void RefinePrisms (Mesh & mesh, const CSGeometry * geom,
ZRefinementOptions & opt)
{
int i, j;
// int i, j;
bool found, change;
int cnt = 0;
@ -261,15 +262,23 @@ namespace netgen
// if (mesh.GetIdentifications().HasIdentifiedPoints())
{
INDEX_2_HASHTABLE<int> & identpts =
auto & identpts =
mesh.GetIdentifications().GetIdentifiedPoints ();
for (i = 1; i <= identpts.GetNBags(); i++)
for (j = 1; j <= identpts.GetBagSize(i); j++)
/*
for (int i = 1; i <= identpts.GetNBags(); i++)
for (int j = 1; j <= identpts.GetBagSize(i); j++)
{
INDEX_2 pair;
int idnr;
identpts.GetData(i, j, pair, idnr);
INDEX_3 pair;
int dummy;
identpts.GetData(i, j, pair, dummy);
*/
for (auto [hash, val] : identpts)\
{
auto [hash_pts, idnr] = hash;
auto [pi1, pi2] = hash_pts;
// auto idnr = pair[2];
const CloseSurfaceIdentification * csid =
dynamic_cast<const CloseSurfaceIdentification*>
(geom->identifications.Get(idnr));
@ -280,17 +289,25 @@ namespace netgen
if (first_id.Test (idnr))
{
first_id.Clear(idnr);
/*
ref_uniform.Append (INDEX_3 (pair.I1(), pair.I2(), csid->RefLevels()));
ref_singular.Append (INDEX_3 (pair.I1(), pair.I2(), csid->RefLevels1()));
ref_singular.Append (INDEX_3 (pair.I2(), pair.I1(), csid->RefLevels2()));
*/
ref_uniform.Append (INDEX_3 (pi1, pi2, csid->RefLevels()));
ref_singular.Append (INDEX_3 (pi1, pi2, csid->RefLevels1()));
ref_singular.Append (INDEX_3 (pi2, pi1, csid->RefLevels2()));
}
}
else
{
//const NgArray<double> & slices = csid->GetSlices();
INDEX_4 i4;
i4[0] = pair.I1();
i4[1] = pair.I2();
// i4[0] = pair.I1();
// i4[1] = pair.I2();
i4[0] = pi1;
i4[1] = pi2;
i4[2] = idnr;
i4[3] = csid->GetSlices().Size();
ref_slices.Append (i4);
@ -313,7 +330,7 @@ namespace netgen
found = 0;
// mark prisms due to close surface flags:
int oldsize = ref_uniform.Size();
for (i = 1; i <= oldsize; i++)
for (int i = 1; i <= oldsize; i++)
{
int pi1 = ref_uniform.Get(i).I1();
int pi2 = ref_uniform.Get(i).I2();
@ -339,7 +356,7 @@ namespace netgen
ref_uniform.Append (INDEX_3(pi2, npi, levels-1));
}
}
for (i = 1; i <= ref_singular.Size(); i++)
for (int i = 1; i <= ref_singular.Size(); i++)
{
int pi1 = ref_singular.Get(i).I1();
int pi2 = ref_singular.Get(i).I2();
@ -367,7 +384,7 @@ namespace netgen
}
}
for (i = 1; i <= ref_slices.Size(); i++)
for (int i = 1; i <= ref_slices.Size(); i++)
{
int pi1 = ref_slices.Get(i)[0];
int pi2 = ref_slices.Get(i)[1];
@ -413,13 +430,13 @@ namespace netgen
for (i = 1; i <= mesh.GetNE(); i++)
for (ElementIndex ei = 0; ei < mesh.GetNE(); ei++)
{
Element & el = mesh.VolumeElement (i);
Element & el = mesh.VolumeElement (ei);
if (el.GetType() != PRISM)
continue;
for (j = 1; j <= 3; j++)
for (int j = 1; j <= 3; j++)
{
int pi1 = el.PNum(j);
int pi2 = el.PNum(j+3);
@ -465,14 +482,14 @@ namespace netgen
{
PrintMessage (5, "start loop");
change = 0;
for (i = 1; i <= mesh.GetNE(); i++)
for (ElementIndex ei = 0; ei < mesh.GetNE(); ei++)
{
Element & el = mesh.VolumeElement (i);
Element & el = mesh.VolumeElement (ei);
if (el.GetType() != PRISM)
continue;
bool hasref = 0, hasnonref = 0;
for (j = 1; j <= 3; j++)
for (int j = 1; j <= 3; j++)
{
int pi1 = el.PNum(j);
int pi2 = el.PNum(j+3);
@ -491,7 +508,7 @@ namespace netgen
{
// cout << "el " << i << " in closure" << endl;
change = 1;
for (j = 1; j <= 3; j++)
for (int j = 1; j <= 3; j++)
{
int pi1 = el.PNum(j);
int pi2 = el.PNum(j+3);
@ -518,7 +535,7 @@ namespace netgen
int oldns = mesh.GetNSeg();
for (i = 1; i <= oldns; i++)
for (int i = 1; i <= oldns; i++)
{
const Segment & el = mesh.LineSegment(i);
@ -572,14 +589,14 @@ namespace netgen
// do refinement
int oldne = mesh.GetNE();
for (i = 1; i <= oldne; i++)
for (ElementIndex ei = 0; ei < oldne; ei++)
{
Element & el = mesh.VolumeElement (i);
Element & el = mesh.VolumeElement (ei);
if (el.GetNP() != 6)
continue;
int npi[3];
for (j = 1; j <= 3; j++)
for (int j = 1; j <= 3; j++)
{
int pi1 = el.PNum(j);
int pi2 = el.PNum(j+3);
@ -607,7 +624,7 @@ namespace netgen
if (npi[0])
{
Element nel1(6), nel2(6);
for (j = 1; j <= 3; j++)
for (int j = 1; j <= 3; j++)
{
nel1.PNum(j) = el.PNum(j);
nel1.PNum(j+3) = npi[j-1];
@ -616,7 +633,7 @@ namespace netgen
}
nel1.SetIndex (el.GetIndex());
nel2.SetIndex (el.GetIndex());
mesh.VolumeElement (i) = nel1;
mesh.VolumeElement (ei) = nel1;
mesh.AddVolumeElement (nel2);
}
}
@ -628,15 +645,15 @@ namespace netgen
// do surface elements
int oldnse = mesh.GetNSE();
// cout << "oldnse = " << oldnse << endl;
for (i = 1; i <= oldnse; i++)
for (SurfaceElementIndex sei = 0; sei < oldnse; sei++)
{
Element2d & el = mesh.SurfaceElement (i);
Element2d & el = mesh.SurfaceElement (sei);
if (el.GetType() != QUAD)
continue;
int index = el.GetIndex();
int npi[2];
for (j = 1; j <= 2; j++)
for (int j = 1; j <= 2; j++)
{
int pi1, pi2;
@ -669,7 +686,7 @@ namespace netgen
if (npi[0])
{
Element2d nel1(QUAD), nel2(QUAD);
for (j = 1; j <= 4; j++)
for (int j = 1; j <= 4; j++)
{
nel1.PNum(j) = el.PNum(j);
nel2.PNum(j) = el.PNum(j);
@ -690,7 +707,7 @@ namespace netgen
nel1.SetIndex (el.GetIndex());
nel2.SetIndex (el.GetIndex());
mesh.SurfaceElement (i) = nel1;
mesh.SurfaceElement (sei) = nel1;
mesh.AddSurfaceElement (nel2);
int si = mesh.GetFaceDescriptor (index).SurfNr();
@ -716,9 +733,9 @@ namespace netgen
void CombineSingularPrisms(Mesh& mesh)
{
for(int i = 1; i<=mesh.GetNE(); i++)
for(ElementIndex ei = 0; ei < mesh.GetNE(); ei++)
{
Element& el = mesh.VolumeElement(i);
Element& el = mesh.VolumeElement(ei);
if(el.GetType() != PRISM)
continue;
if(el.PNum(3) == el.PNum(6))

View File

@ -1,9 +1,7 @@
target_sources(nglib PRIVATE
dynamicmem.cpp
gzstream.cpp
hashtabl.cpp
mystring.cpp
ngarray.cpp
ngbitarray.cpp
optmem.cpp
parthreads.cpp
@ -13,12 +11,15 @@ target_sources(nglib PRIVATE
table.cpp
)
# dynamicmem.cpp
install(FILES
ngarray.hpp autodiff.hpp autoptr.hpp ngbitarray.hpp
dynamicmem.hpp hashtabl.hpp myadt.hpp
hashtabl.hpp myadt.hpp
mystring.hpp netgenout.hpp ngpython.hpp
optmem.hpp parthreads.hpp seti.hpp sort.hpp
spbita2d.hpp stack.hpp table.hpp template.hpp
gzstream.h
DESTINATION ${NG_INSTALL_DIR_INCLUDE}/general COMPONENT netgen_devel
)
# dynamicmem.hpp

View File

@ -9,6 +9,8 @@
// Automatic differentiation datatype
namespace netgen
{
/**
Datatype for automatic differentiation.
@ -284,18 +286,6 @@ inline AutoDiff<D,SCAL> operator* (const AutoDiff<D,SCAL> & x, const AutoDiff<D,
return res;
}
/// AutoDiff times AutoDiff
template<int D, typename SCAL>
inline AutoDiff<D,SCAL> sqr (const AutoDiff<D,SCAL> & x) throw()
{
AutoDiff<D,SCAL> res;
SCAL hx = x.Value();
res.Value() = hx*hx;
hx *= 2;
for (int i = 0; i < D; i++)
res.DValue(i) = hx*x.DValue(i);
return res;
}
/// Inverse of AutoDiff
template<int D, typename SCAL>
@ -329,14 +319,31 @@ inline AutoDiff<D,SCAL> operator/ (double x, const AutoDiff<D,SCAL> & y)
return x * Inv(y);
}
} // namespace netgen
namespace ngcore
{
/// AutoDiff times AutoDiff
template<int D, typename SCAL>
inline AutoDiff<D,SCAL> fabs (const AutoDiff<D,SCAL> & x)
inline netgen::AutoDiff<D,SCAL> sqr (const netgen::AutoDiff<D,SCAL> & x) throw()
{
netgen::AutoDiff<D,SCAL> res;
SCAL hx = x.Value();
res.Value() = hx*hx;
hx *= 2;
for (int i = 0; i < D; i++)
res.DValue(i) = hx*x.DValue(i);
return res;
}
} // namespace ngcore
namespace std
{
template<int D, typename SCAL>
inline netgen::AutoDiff<D,SCAL> fabs (const netgen::AutoDiff<D,SCAL> & x)
{
double abs = fabs (x.Value());
AutoDiff<D,SCAL> res( abs );
netgen::AutoDiff<D,SCAL> res( abs );
if (abs != 0.0)
for (int i = 0; i < D; i++)
res.DValue(i) = x.DValue(i) / abs;
@ -345,7 +352,5 @@ inline AutoDiff<D,SCAL> fabs (const AutoDiff<D,SCAL> & x)
res.DValue(i) = 0.0;
return res;
}
//@}
} // namespace std
#endif

View File

@ -1,3 +1,6 @@
not needed anymore ?
#ifndef FILE_DYNAMICMEM
#define FILE_DYNAMICMEM

View File

@ -44,7 +44,7 @@ namespace GZSTREAM_NAMESPACE {
// class gzstreambuf:
// --------------------------------------
gzstreambuf* gzstreambuf::open( const filesystem::path & name, int open_mode) {
gzstreambuf* gzstreambuf::open( const std::filesystem::path & name, int open_mode) {
if ( is_open())
return (gzstreambuf*)0;
mode = open_mode;
@ -143,7 +143,7 @@ int gzstreambuf::sync() {
// class gzstreambase:
// --------------------------------------
gzstreambase::gzstreambase( const filesystem::path & name, int mode) {
gzstreambase::gzstreambase( const std::filesystem::path & name, int mode) {
init( &buf);
open( name.c_str(), mode);
}
@ -152,7 +152,7 @@ gzstreambase::~gzstreambase() {
buf.close();
}
void gzstreambase::open( const filesystem::path & name, int open_mode) {
void gzstreambase::open( const std::filesystem::path & name, int open_mode) {
if ( ! buf.open( name.c_str(), open_mode))
clear( rdstate() | std::ios::badbit);
}

View File

@ -62,7 +62,7 @@ public:
// ASSERT: both input & output capabilities will not be used together
}
int is_open() { return opened; }
gzstreambuf* open( const filesystem::path & name, int open_mode);
gzstreambuf* open( const std::filesystem::path & name, int open_mode);
gzstreambuf* close();
~gzstreambuf() { close(); }
@ -76,9 +76,9 @@ protected:
gzstreambuf buf;
public:
gzstreambase() { init(&buf); }
gzstreambase( const filesystem::path & name, int open_mode);
gzstreambase( const std::filesystem::path & name, int open_mode);
~gzstreambase();
void open( const filesystem::path & name, int open_mode);
void open( const std::filesystem::path & name, int open_mode);
void close();
gzstreambuf* rdbuf() { return &buf; }
};
@ -92,10 +92,10 @@ public:
class DLL_HEADER igzstream : public gzstreambase, public std::istream {
public:
igzstream() : std::istream( &buf) {}
igzstream( const filesystem::path & name, int open_mode = std::ios::in)
igzstream( const std::filesystem::path & name, int open_mode = std::ios::in)
: gzstreambase( name, open_mode), std::istream( &buf) {}
gzstreambuf* rdbuf() { return gzstreambase::rdbuf(); }
void open( const filesystem::path & name, int open_mode = std::ios::in) {
void open( const std::filesystem::path & name, int open_mode = std::ios::in) {
gzstreambase::open( name, open_mode);
}
};
@ -103,10 +103,10 @@ public:
class DLL_HEADER ogzstream : public gzstreambase, public std::ostream {
public:
ogzstream() : std::ostream( &buf) {}
ogzstream( const filesystem::path & name, int mode = std::ios::out)
ogzstream( const std::filesystem::path & name, int mode = std::ios::out)
: gzstreambase( name, mode), std::ostream( &buf) {}
gzstreambuf* rdbuf() { return gzstreambase::rdbuf(); }
void open( const filesystem::path & name, int open_mode = std::ios::out) {
void open( const std::filesystem::path & name, int open_mode = std::ios::out) {
gzstreambase::open( name, open_mode);
}
};

View File

@ -292,7 +292,19 @@ namespace netgen
BASE_INDEX_3_CLOSED_HASHTABLE ::
BASE_INDEX_3_CLOSED_HASHTABLE (size_t size)
: hash(RoundUp2(size))
{
// cout << "orig size = " << size
// << ", roundup size = " << hash.Size();
size = hash.Size();
mask = size-1;
// cout << "mask = " << mask << endl;
invalid = -1;
for (size_t i = 0; i < size; i++)
hash[i].I1() = invalid;
}
void BASE_INDEX_3_CLOSED_HASHTABLE ::

View File

@ -7,6 +7,8 @@
/* Date: 01. Jun. 95 */
/**************************************************************************/
#include "table.hpp"
namespace netgen
{
@ -412,9 +414,14 @@ public:
int BagNr() const { return bagnr; }
int Pos() const { return pos; }
void operator++ (int)
Iterator operator++ (int)
{
Iterator it(ht, bagnr, pos);
++(*this);
return it;
}
Iterator& operator++()
{
// cout << "begin Operator ++: bagnr = " << bagnr << " - pos = " << pos << endl;
pos++;
while (bagnr < ht.GetNBags() &&
pos == ht.GetBagSize(bagnr+1))
@ -422,7 +429,12 @@ public:
pos = 0;
bagnr++;
}
// cout << "end Operator ++: bagnr = " << bagnr << " - pos = " << pos << endl;
return *this;
}
std::pair<INDEX_3, T> operator*()
{
return std::make_pair(ht.hash[bagnr][pos], ht.cont[bagnr][pos]);
}
bool operator != (int i) const
@ -444,6 +456,18 @@ public:
return GetNBags();
}
Iterator begin () const
{
Iterator it(*this, 0, -1);
it++;
return it;
}
int end() const
{
return GetNBags();
}
void GetData (const Iterator & it,
INDEX_3 & ahash, T & acont) const
{
@ -837,9 +861,10 @@ inline ostream & operator<< (ostream & ost, const INDEX_2_CLOSED_HASHTABLE<T> &
for (int i = 0; i < ht.Size(); i++)
if (ht.UsedPos(i))
{
INDEX_2 hash;
T data;
ht.GetData0 (i, hash, data);
// INDEX_2 hash;
// T data;
// ht.GetData0 (i, hash, data);
auto [hash,data] = ht.GetBoth(i);
ost << "hash = " << hash << ", data = " << data << endl;
}
return ost;
@ -856,7 +881,8 @@ protected:
size_t mask;
protected:
BASE_INDEX_3_CLOSED_HASHTABLE (size_t size)
BASE_INDEX_3_CLOSED_HASHTABLE (size_t size);
/*
: hash(RoundUp2(size))
{
// cout << "orig size = " << size
@ -868,6 +894,7 @@ protected:
for (size_t i = 0; i < size; i++)
hash[i].I1() = invalid;
}
*/
public:
int Size() const
@ -1049,9 +1076,12 @@ inline ostream & operator<< (ostream & ost, const INDEX_3_CLOSED_HASHTABLE<T> &
for (int i = 0; i < ht.Size(); i++)
if (ht.UsedPos(i))
{
/*
INDEX_3 hash;
T data;
ht.GetData (i, hash, data);
ht.GetData (i, hash, data);
*/
auto [hash, data] = ht.GetBoth();
ost << "hash = " << hash << ", data = " << data << endl;
}
return ost;
@ -1410,7 +1440,7 @@ inline size_t HashValue (INDEX_3 i3, size_t size) { return (i3[0]+15*size_t(i3[1
The array should be allocated with the double size of the expected number of entries.
*/
template <class T_HASH, class T>
class ClosedHashTable
class NgClosedHashTable
{
protected:
///
@ -1423,16 +1453,16 @@ inline size_t HashValue (INDEX_3 i3, size_t size) { return (i3[0]+15*size_t(i3[1
NgArray<T> cont;
public:
///
ClosedHashTable (size_t asize = 128)
NgClosedHashTable (size_t asize = 128)
: size(asize), used(0), hash(asize), cont(asize)
{
for (auto & v : hash)
SetInvalid(v);
}
ClosedHashTable (ClosedHashTable && ht2) = default;
NgClosedHashTable (NgClosedHashTable && ht2) = default;
ClosedHashTable (NgFlatArray<T_HASH> _hash, NgFlatArray<T> _cont)
NgClosedHashTable (NgFlatArray<T_HASH> _hash, NgFlatArray<T> _cont)
: size(_hash.Size()), used(0), hash(_hash.Size(), _hash.Addr(0)), cont(_cont.Size(), _cont.Addr(0))
{
for (auto & v : hash)
@ -1440,7 +1470,7 @@ inline size_t HashValue (INDEX_3 i3, size_t size) { return (i3[0]+15*size_t(i3[1
}
ClosedHashTable & operator= (ClosedHashTable && ht2) = default;
NgClosedHashTable & operator= (NgClosedHashTable && ht2) = default;
///
size_t Size() const
@ -1474,7 +1504,7 @@ inline size_t HashValue (INDEX_3 i3, size_t size) { return (i3[0]+15*size_t(i3[1
void DoubleSize()
{
ClosedHashTable tmp(2*Size());
NgClosedHashTable tmp(2*Size());
for (auto both : *this)
tmp[both.first] = both.second;
*this = std::move(tmp);
@ -1609,10 +1639,10 @@ inline size_t HashValue (INDEX_3 i3, size_t size) { return (i3[0]+15*size_t(i3[1
class Iterator
{
const ClosedHashTable & tab;
const NgClosedHashTable & tab;
size_t nr;
public:
Iterator (const ClosedHashTable & _tab, size_t _nr)
Iterator (const NgClosedHashTable & _tab, size_t _nr)
: tab(_tab), nr(_nr)
{
while (nr < tab.Size() && !tab.UsedPos(nr)) nr++;
@ -1639,7 +1669,7 @@ inline size_t HashValue (INDEX_3 i3, size_t size) { return (i3[0]+15*size_t(i3[1
template <class T_HASH, class T>
ostream & operator<< (ostream & ost,
const ClosedHashTable<T_HASH,T> & tab)
const NgClosedHashTable<T_HASH,T> & tab)
{
for (size_t i = 0; i < tab.Size(); i++)
if (tab.UsedPos(i))

View File

@ -1,54 +0,0 @@
/**************************************************************************/
/* File: mpi_interface.cpp */
/* Author: Joachim Schoeberl */
/* Date: 04. Apr. 97 */
/**************************************************************************/
#ifdef OLD
#include <mystdlib.h>
#include <myadt.hpp>
namespace netgen
{
#ifdef PARALLEL
void MyMPI_SendCmd (const char * cmd)
{
int ntasks;
MPI_Comm_size(MPI_COMM_WORLD, &ntasks);
if(ntasks==1)
return;
for (int dest = 1; dest < ntasks; dest++)
MPI_Send( (void*)cmd, (strlen(cmd)+1), MPI_CHAR, dest, MPI_TAG_CMD, MPI_COMM_WORLD);
}
string MyMPI_RecvCmd ()
{
MPI_Status status;
int flag;
int size_of_msg = -1;
MPI_Probe(0, MPI_TAG_CMD, MPI_COMM_WORLD, &status);
MPI_Get_count(&status, MPI_CHAR, &size_of_msg);
//char* buf = (char*)malloc(size_of_msg*sizeof(char));
char buf[100000]; //1MB should be enough...
MPI_Recv( &buf, size_of_msg, MPI_CHAR, 0, MPI_TAG_CMD, MPI_COMM_WORLD, &status);
return string(buf);
}
// #else
// MPI_Comm MPI_COMM_WORLD, MPI_COMM_NULL;
#endif
}
#endif

View File

@ -1,336 +0,0 @@
braucht keiner mehr
#ifdef XXXXXX
#ifndef FILE_PARALLEL
#define FILE_PARALLEL
#ifdef VTRACE
#include "vt_user.h"
#else
#define VT_USER_START(n)
#define VT_USER_END(n)
#define VT_TRACER(n)
#endif
namespace netgen
{
#ifdef OLD
#ifdef PARALLEL
template <class T>
inline MPI_Datatype MyGetMPIType ( )
{ cerr << "ERROR in GetMPIType() -- no type found" << endl;return 0; }
template <>
inline MPI_Datatype MyGetMPIType<int> ( )
{ return MPI_INT; }
template <>
inline MPI_Datatype MyGetMPIType<double> ( )
{ return MPI_DOUBLE; }
template <>
inline MPI_Datatype MyGetMPIType<char> ( )
{ return MPI_CHAR; }
template<>
inline MPI_Datatype MyGetMPIType<size_t> ( )
{ return MPI_UINT64_T; }
#else
typedef int MPI_Datatype;
template <class T> inline MPI_Datatype MyGetMPIType ( ) { return 0; }
#endif
#endif
enum { MPI_TAG_CMD = 110 };
enum { MPI_TAG_MESH = 210 };
enum { MPI_TAG_VIS = 310 };
#ifdef PARALLEL
[[deprecated("mympi_send int, use comm.Send instead")]]
inline void MyMPI_Send (int i, int dest, int tag, MPI_Comm comm)
{
int hi = i;
MPI_Send( &hi, 1, MPI_INT, dest, tag, comm);
}
[[deprecated("mympi_revc int, use comm.Recv instead")]]
inline void MyMPI_Recv (int & i, int src, int tag, MPI_Comm comm)
{
MPI_Status status;
MPI_Recv( &i, 1, MPI_INT, src, tag, comm, &status);
}
[[deprecated("mympi_send string, use comm.Send instead")]]
inline void MyMPI_Send (const string & s, int dest, int tag, MPI_Comm comm)
{
MPI_Send( const_cast<char*> (s.c_str()), s.length(), MPI_CHAR, dest, tag, comm);
}
[[deprecated("mympi_revc string, use comm.Recv instead")]]
inline void MyMPI_Recv (string & s, int src, int tag, MPI_Comm comm)
{
MPI_Status status;
int len;
MPI_Probe (src, tag, MPI_COMM_WORLD, &status);
MPI_Get_count (&status, MPI_CHAR, &len);
s.assign (len, ' ');
MPI_Recv( &s[0], len, MPI_CHAR, src, tag, comm, &status);
}
template <class T, int BASE>
[[deprecated("mympi_send ngflatarray, use comm.send instead")]]
inline void MyMPI_Send (NgFlatArray<T, BASE> s, int dest, int tag, MPI_Comm comm)
{
MPI_Send( &s.First(), s.Size(), GetMPIType<T>(), dest, tag, comm);
}
template <class T, int BASE>
[[deprecated("mympi_recv ngflatarray, use comm.Recv instead")]]
inline void MyMPI_Recv ( NgFlatArray<T, BASE> s, int src, int tag, MPI_Comm comm)
{
MPI_Status status;
MPI_Recv( &s.First(), s.Size(), GetMPIType<T>(), src, tag, comm, &status);
}
template <class T, int BASE>
[[deprecated("use ngcore - Array instead")]]
inline void MyMPI_Recv ( NgArray <T, BASE> & s, int src, int tag, MPI_Comm comm)
{
MPI_Status status;
int len;
MPI_Probe (src, tag, comm, &status);
MPI_Get_count (&status, GetMPIType<T>(), &len);
s.SetSize (len);
MPI_Recv( &s.First(), len, GetMPIType<T>(), src, tag, comm, &status);
}
template <class T, int BASE>
[[deprecated("use ngcore - Array instead")]]
inline int MyMPI_Recv ( NgArray <T, BASE> & s, int tag, MPI_Comm comm)
{
MPI_Status status;
int len;
MPI_Probe (MPI_ANY_SOURCE, tag, comm, &status);
int src = status.MPI_SOURCE;
MPI_Get_count (&status, GetMPIType<T>(), &len);
s.SetSize (len);
MPI_Recv( &s.First(), len, GetMPIType<T>(), src, tag, comm, &status);
return src;
}
/*
template <class T, int BASE>
inline void MyMPI_ISend (NgFlatArray<T, BASE> s, int dest, int tag, MPI_Request & request)
{
MPI_Isend( &s.First(), s.Size(), MyGetMPIType<T>(), dest, tag, MPI_COMM_WORLD, & request);
}
template <class T, int BASE>
inline void MyMPI_IRecv (NgFlatArray<T, BASE> s, int dest, int tag, MPI_Request & request)
{
MPI_Irecv( &s.First(), s.Size(), MyGetMPIType<T>(), dest, tag, MPI_COMM_WORLD, & request);
}
*/
template <class T, int BASE>
[[deprecated("mympi_isend ngflatarray, use comm.send instead")]]
[[deprecated("use ngcore - Array instead")]]
inline MPI_Request MyMPI_ISend (NgFlatArray<T, BASE> s, int dest, int tag, MPI_Comm comm)
{
MPI_Request request;
MPI_Isend( &s.First(), s.Size(), GetMPIType<T>(), dest, tag, comm, &request);
return request;
}
template <class T, int BASE>
[[deprecated("mympi_irecv ngflatarray, use comm.recv instead")]]
inline MPI_Request MyMPI_IRecv (NgFlatArray<T, BASE> s, int dest, int tag, MPI_Comm comm)
{
MPI_Request request;
MPI_Irecv( &s.First(), s.Size(), GetMPIType<T>(), dest, tag, comm, &request);
return request;
}
/*
template <class T, int BASE>
inline void MyMPI_ISend (NgFlatArray<T, BASE> s, int dest, int tag)
{
MPI_Request request;
MPI_Isend( &s.First(), s.Size(), MyGetMPIType<T>(), dest, tag, MPI_COMM_WORLD, &request);
MPI_Request_free (&request);
}
template <class T, int BASE>
inline void MyMPI_IRecv (NgFlatArray<T, BASE> s, int dest, int tag)
{
MPI_Request request;
MPI_Irecv( &s.First(), s.Size(), MyGetMPIType<T>(), dest, tag, MPI_COMM_WORLD, &request);
MPI_Request_free (&request);
}
*/
/*
send a table entry to each of the processes in the group ...
receive-table entries will be set
*/
template <typename T>
[[deprecated("do we need that ? ")]]
inline void MyMPI_ExchangeTable (TABLE<T> & send_data,
TABLE<T> & recv_data, int tag,
const NgMPI_Comm & comm)
{
int rank = comm.Rank();
int ntasks = comm.Size();
Array<int> send_sizes(ntasks);
Array<int> recv_sizes(ntasks);
for (int i = 0; i < ntasks; i++)
send_sizes[i] = send_data[i].Size();
comm.AllToAll (send_sizes, recv_sizes);
for (int i = 0; i < ntasks; i++)
recv_data.SetEntrySize (i, recv_sizes[i], sizeof(T));
Array<MPI_Request> requests;
for (int dest = 0; dest < ntasks; dest++)
if (dest != rank && send_data[dest].Size())
requests.Append (comm.ISend (FlatArray<T>(send_data[dest]), dest, tag));
for (int dest = 0; dest < ntasks; dest++)
if (dest != rank && recv_data[dest].Size())
requests.Append (comm.IRecv (FlatArray<T>(recv_data[dest]), dest, tag));
MyMPI_WaitAll (requests);
}
template <typename T>
[[deprecated("do we need that ? ")]]
inline void MyMPI_ExchangeTable (DynamicTable<T> & send_data,
DynamicTable<T> & recv_data, int tag,
const NgMPI_Comm & comm)
{
int rank = comm.Rank();
int ntasks = comm.Size();
Array<int> send_sizes(ntasks);
Array<int> recv_sizes(ntasks);
for (int i = 0; i < ntasks; i++)
send_sizes[i] = send_data[i].Size();
comm.AllToAll (send_sizes, recv_sizes);
// for (int i = 0; i < ntasks; i++)
// recv_data.SetEntrySize (i, recv_sizes[i], sizeof(T));
recv_data = DynamicTable<T> (recv_sizes, true);
Array<MPI_Request> requests;
for (int dest = 0; dest < ntasks; dest++)
if (dest != rank && send_data[dest].Size())
requests.Append (comm.ISend (FlatArray<T>(send_data[dest]), dest, tag));
for (int dest = 0; dest < ntasks; dest++)
if (dest != rank && recv_data[dest].Size())
requests.Append (comm.IRecv (FlatArray<T>(recv_data[dest]), dest, tag));
MyMPI_WaitAll (requests);
}
[[deprecated("do we still send commands?")]]
DLL_HEADER void MyMPI_SendCmd (const char * cmd);
[[deprecated("do we still send commands?")]]
extern string MyMPI_RecvCmd ();
template <class T>
[[deprecated("use comm.BCast instead")]]
inline void MyMPI_Bcast (T & s, MPI_Comm comm)
{
MPI_Bcast (&s, 1, GetMPIType<T>(), 0, comm);
}
template <class T>
[[deprecated("use comm.BCast instead")]]
inline void MyMPI_Bcast (NgArray<T, 0> & s, NgMPI_Comm comm)
{
int size = s.Size();
// MyMPI_Bcast (size, comm);
comm.Bcast(size);
// if (MyMPI_GetId(comm) != 0) s.SetSize (size);
if (comm.Rank() != 0) s.SetSize (size);
MPI_Bcast (&s[0], size, GetMPIType<T>(), 0, comm);
}
template <class T>
[[deprecated("use comm.BCast instead")]]
inline void MyMPI_Bcast (NgArray<T, 0> & s, int root, MPI_Comm comm)
{
int id;
MPI_Comm_rank(comm, &id);
int size = s.Size();
MPI_Bcast (&size, 1, MPI_INT, root, comm);
if (id != root) s.SetSize (size);
if ( !size ) return;
MPI_Bcast (&s[0], size, GetMPIType<T>(), root, comm);
}
template <class T, class T2>
[[deprecated("mympi_allgather deprecated, use comm.allgather")]]
inline void MyMPI_Allgather (const T & send, NgFlatArray<T2> recv, MPI_Comm comm)
{
MPI_Allgather( const_cast<T*> (&send), 1, GetMPIType<T>(), &recv[0], 1, GetMPIType<T2>(), comm);
}
template <class T, class T2>
[[deprecated("mympi_alltoall deprecated, use comm.alltoall")]]
inline void MyMPI_Alltoall (NgFlatArray<T> send, NgFlatArray<T2> recv, MPI_Comm comm)
{
MPI_Alltoall( &send[0], 1, GetMPIType<T>(), &recv[0], 1, GetMPIType<T2>(), comm);
}
#else
template <typename T>
[[deprecated("do we need that ? ")]]
inline void MyMPI_ExchangeTable (TABLE<T> & send_data,
TABLE<T> & recv_data, int tag,
const NgMPI_Comm & comm)
{
;
}
template <typename T>
[[deprecated("do we need that ? ")]]
inline void MyMPI_ExchangeTable (DynamicTable<T> & send_data,
DynamicTable<T> & recv_data, int tag,
const NgMPI_Comm & comm)
{ ; }
#endif // PARALLEL
}
#endif
#endif

View File

@ -12,7 +12,6 @@
*/
#include "../include/mystdlib.h"
#include "../include/mydefs.hpp"
@ -25,7 +24,7 @@ namespace netgen
}
#include "parthreads.hpp"
// #include "moveablemem.hpp"
#include "dynamicmem.hpp"
// #include "dynamicmem.hpp"
#include "template.hpp"
#include "ngarray.hpp"
@ -46,5 +45,4 @@ namespace netgen
// #include "mpi_interface.hpp"
#include "netgenout.hpp"
#endif

View File

@ -155,7 +155,7 @@ MyStr::MyStr(long l)
MyStr::MyStr(size_t l)
{
char buffer[32];
snprintf(buffer, 32, "%ld", l);
snprintf(buffer, 32, "%zu", l);
length = unsigned(strlen(buffer));
if (length > SHORTLEN)
str = new char[length + 1];
@ -223,6 +223,16 @@ MyStr::MyStr(const string & st)
strcpy (str, st.c_str());
}
MyStr::MyStr(string_view sv)
{
length = unsigned(sv.length());
if (length > SHORTLEN)
str = new char[length + 1];
else
str = shortstr;
strcpy (str, sv.data());
}
MyStr::MyStr(const filesystem::path & path)
: MyStr(path.string())
{ }

View File

@ -60,6 +60,7 @@ public:
MyStr(const Point3d& p);
MyStr(const Vec3d& p);
MyStr(const string & st);
MyStr(string_view sv);
MyStr(const filesystem::path & st);
~MyStr();

View File

@ -1,75 +0,0 @@
#ifndef FILE_NGSTD_NgArrayCPP
#define FILE_NGSTD_NgArrayCPP
// necessary for SGI ????
/**************************************************************************/
/* File: array.cpp */
/* Author: Joachim Schoeberl */
/* Date: 01. Jun. 95 */
/**************************************************************************/
/*
Abstract data type NgArray
*/
#include <mystdlib.h>
#include <myadt.hpp>
#include <assert.h>
namespace netgen
{
//using namespace netgen;
#ifdef NONE
void BASE_Array :: ReSize (int minsize, int elementsize)
{
cout << "resize, minsize = " << minsize << endl;
if (inc == -1)
throw Exception ("Try to resize fixed size array");
void * p;
int nsize = (inc) ? allocsize + inc : 2 * allocsize;
if (nsize < minsize) nsize = minsize;
if (data)
{
p = new char [nsize * elementsize];
int mins = (nsize < actsize) ? nsize : actsize;
memcpy (p, data, mins * elementsize);
delete [] static_cast<char*> (data);
data = p;
}
else
{
data = new char[nsize * elementsize];
}
allocsize = nsize;
cout << "resize done" << endl;
}
void BASE_Array :: RangeCheck (int i) const
{
if (i < 0 || i >= actsize)
throw ArrayRangeException ();
}
void BASE_Array :: CheckNonEmpty () const
{
if (!actsize)
{
throw Exception ("NgArray should not be empty");
// cerr << "NgArray shouldn't be empty";
}
}
#endif
}
#endif // FILE_NGSTD_NgArrayCPP

View File

@ -7,12 +7,14 @@
/* Date: 01. Jun. 95 */
/**************************************************************************/
#include <core/array.hpp>
namespace netgen
{
using namespace ngcore;
// template <class T, int B1, int B2> class IndirectArray;
template <class TA1, class TA2> class IndirectArray;
template <class TA1, class TA2> class NgIndirectArray;
@ -110,18 +112,14 @@ namespace netgen
/// Access array. BASE-based
T & operator[] (TIND i) const
{
#ifdef DEBUG
if (i-BASE < 0 || i-BASE >= size)
cout << "array<" << typeid(T).name() << "> out of range, i = " << i << ", s = " << size << endl;
#endif
NETGEN_CHECK_RANGE(i,BASE,size+BASE);
return data[i-BASE];
}
template <typename T2, int B2>
IndirectArray<NgFlatArray, NgFlatArray<T2,B2> > operator[] (const NgFlatArray<T2,B2> & ia) const
NgIndirectArray<NgFlatArray, NgFlatArray<T2,B2> > operator[] (const NgFlatArray<T2,B2> & ia) const
{
return IndirectArray<NgFlatArray, NgFlatArray<T2,B2> > (*this, ia);
return NgIndirectArray<NgFlatArray, NgFlatArray<T2,B2> > (*this, ia);
}
@ -129,13 +127,7 @@ namespace netgen
/// Access array, one-based (old fashioned)
T & Elem (int i)
{
#ifdef DEBUG
if (i < 1 || i > size)
cout << "NgArray<" << typeid(T).name()
<< ">::Elem out of range, i = " << i
<< ", s = " << size << endl;
#endif
NETGEN_CHECK_RANGE(i,1,size+1);
return ((T*)data)[i-1];
}
@ -143,30 +135,21 @@ namespace netgen
// [[deprecated("Use operator[] instead")]]
const T & Get (int i) const
{
#ifdef DEBUG
if (i < 1 || i > size)
cout << "NgArray<" << typeid(T).name() << ">::Get out of range, i = " << i
<< ", s = " << size << endl;
#endif
NETGEN_CHECK_RANGE(i,1,size+1);
return ((const T*)data)[i-1];
}
/// Access array, one-based (old fashioned)
void Set (int i, const T & el)
{
#ifdef DEBUG
if (i < 1 || i > size)
cout << "NgArray<" << typeid(T).name() << ">::Set out of range, i = " << i
<< ", s = " << size << endl;
#endif
NETGEN_CHECK_RANGE(i,1,size+1);
((T*)data)[i-1] = el;
}
/// access first element
T & First () const
{
NETGEN_CHECK_RANGE(0,0,size);
return data[0];
}
@ -174,6 +157,7 @@ namespace netgen
/// access last element. check by macro CHECK_RANGE
T & Last () const
{
NETGEN_CHECK_RANGE(size-1,0,size);
return data[size-1];
}
@ -206,10 +190,10 @@ namespace netgen
return ( Pos(elem) >= 0 );
}
operator FlatArray<T> () const
operator ngcore::FlatArray<T> () const
{
static_assert (BASE==0);
return FlatArray<T>(size, data);
return ngcore::FlatArray<T>(size, data);
}
};
@ -344,10 +328,7 @@ namespace netgen
/// Delete element i (0-based). Move last element to position i.
void Delete (TIND i)
{
#ifdef CHECK_Array_RANGE
RangeCheck (i+1);
#endif
NETGEN_CHECK_RANGE(i,0,size);
data[i] = std::move(data[size-1]);
size--;
// DeleteElement (i+1);
@ -357,10 +338,7 @@ namespace netgen
/// Delete element i (1-based). Move last element to position i.
void DeleteElement (TIND i)
{
#ifdef CHECK_Array_RANGE
RangeCheck (i);
#endif
NETGEN_CHECK_RANGE(i,1,size+1);
data[i-1] = std::move(data[size-1]);
size--;
}
@ -421,8 +399,9 @@ namespace netgen
}
// Only provide this function if T is archivable
template<typename T2=T>
auto DoArchive(Archive& archive) -> typename std::enable_if<is_archivable<T2>, void>::type
template<typename ARCHIVE>
auto DoArchive(ARCHIVE& archive)
-> typename std::enable_if_t<ARCHIVE::template is_archivable<T>, void>
{
if(archive.Output())
archive << size;
@ -531,13 +510,13 @@ namespace netgen
*/
template <class TA1, class TA2>
class IndirectArray
class NgIndirectArray
{
const TA1 & array;
const TA2 & ia;
public:
IndirectArray (const TA1 & aa, const TA2 & aia)
NgIndirectArray (const TA1 & aa, const TA2 & aia)
: array(aa), ia(aia) { ; }
int Size() const { return ia.Size(); }
[[deprecated("Use *Range().begin() instead")]]
@ -553,7 +532,7 @@ namespace netgen
template <typename T1, typename T2>
inline ostream & operator<< (ostream & s, const IndirectArray<T1,T2> & ia)
inline ostream & operator<< (ostream & s, const NgIndirectArray<T1,T2> & ia)
{
for (int i = ia.Begin(); i < ia.End(); i++)
s << i << ": " << ia[i] << endl;

View File

@ -12,7 +12,6 @@
namespace netgen
{
/**
data type NgBitArray
@ -29,8 +28,11 @@ class NgBitArray
unsigned char * data;
public:
// [[ deprecated ("use BitArray instead")]]
DLL_HEADER NgBitArray ();
///
// [[ deprecated ("use BitArray instead")]]
DLL_HEADER NgBitArray (INDEX asize);
///
DLL_HEADER ~NgBitArray ();

View File

@ -8,7 +8,7 @@
#include <iostream>
#include <sstream>
using namespace ngcore;
// using namespace ngcore;
template <typename T>
py::array MoveToNumpy(std::vector<T>& vec)

View File

@ -7,6 +7,10 @@
/* Date: 04. Apr. 97 */
/**************************************************************************/
#include <mydefs.hpp>
#include "ngarray.hpp"
namespace netgen
{

View File

@ -77,8 +77,8 @@ public:
template<typename TFunc>
void ParallelFor( int first, int next, const TFunc & f )
{
int nthreads = thread::hardware_concurrency();
thread * threads = new thread[nthreads];
int nthreads = std::thread::hardware_concurrency();
std::thread * threads = new std::thread[nthreads];
for (int i=0; i<nthreads; i++)
{
int myfirst = first + (next-first)*i/nthreads;
@ -97,7 +97,7 @@ void ParallelFor( int first, int next, const TFunc & f )
typedef void (*NgTaskManager)(std::function<void(int,int)>);
typedef void (*NgTracer)(string, bool); // false .. start, true .. stop
typedef void (*NgTracer)(std::string, bool); // false .. start, true .. stop
inline void DummyTaskManager (std::function<void(int,int)> func)
{
@ -105,7 +105,7 @@ void ParallelFor( int first, int next, const TFunc & f )
func(1,2);
}
inline void DummyTracer (string, bool) { ; }
inline void DummyTracer (std::string, bool) { ; }
template <typename FUNC>
inline void ParallelFor (NgTaskManager tm, size_t n, FUNC func)

View File

@ -108,8 +108,9 @@ namespace netgen
if (line.size == line.maxsize)
{
void * p = new char [(line.maxsize+5) * elsize];
memcpy (p, line.col, line.maxsize * elsize);
if (line.maxsize && elsize)
memcpy (p, line.col, line.maxsize * elsize);
delete [] (char*)line.col;
line.col = p;

View File

@ -120,7 +120,7 @@ public:
/// Creates fixed maximal element size table
inline TABLE (const NgFlatArray<int,BASE> & entrysizes)
: BASE_TABLE (NgFlatArray<int> (entrysizes.Size(), const_cast<int*>(&entrysizes[BASE])),
: BASE_TABLE (NgFlatArray<int> (entrysizes.Size(), entrysizes.Size() ? const_cast<int*>(&entrysizes[BASE]) : nullptr),
sizeof(T))
{ ; }
@ -169,6 +169,7 @@ public:
/// Inserts element acont into row i. BASE-based. Does not test if already used, assumes to have enough memory
inline void AddSave (int i, const T & acont)
{
NETGEN_CHECK_RANGE(i, BASE, data.Size()+BASE);
((T*)data[i-BASE].col)[data[i-BASE].size] = acont;
data[i-BASE].size++;
}

View File

@ -7,14 +7,16 @@
/* Date: 01. Jun. 95 */
/**************************************************************************/
#include <core/utils.hpp>
namespace netgen
{
using namespace ngcore;
/*
templates, global types, defines and variables
*/
DLL_HEADER extern const string netgen_version;
DLL_HEADER extern const std::string netgen_version;
/// The following value may be adapted to the hardware !
#ifndef CLOCKS_PER_SEC
@ -112,14 +114,24 @@ class INDEX_2
public:
///
// protected:
INDEX_2 () { }
INDEX_2 (const INDEX_2&) = default;
public:
INDEX_2 (INDEX_2&&) = default;
INDEX_2 & operator= (const INDEX_2&) = default;
INDEX_2 & operator= (INDEX_2&&) = default;
///
INDEX_2 (INDEX ai1, INDEX ai2)
{ i[0] = ai1; i[1] = ai2; }
constexpr INDEX_2 (INDEX ai1, INDEX ai2)
: i{ai1, ai2} { }
// { i[0] = ai1; i[1] = ai2; }
///
INDEX_2 (const INDEX_2 & in2)
{ i[0] = in2.i[0]; i[1] = in2.i[1]; }
// constexpr INDEX_2 (const INDEX_2 & in2)
// : i{in2.i[0], in2.i[1]} { }
// { i[0] = in2.i[0]; i[1] = in2.i[1]; }
///
int operator== (const INDEX_2 & in2) const
@ -128,7 +140,7 @@ public:
///
INDEX_2 Sort ()
constexpr INDEX_2 Sort ()
{
if (i[0] > i[1])
{
@ -147,7 +159,7 @@ public:
return INDEX_2 (i1,i2);
}
operator std::array<INDEX,2>() { return { i[0], i[1] }; }
///
INDEX & I1 () { return i[0]; }
///
@ -163,7 +175,7 @@ public:
///
int & operator[] (int j) { return i[j]; }
///
const int & operator[] (int j) const { return i[j]; }
constexpr const int & operator[] (int j) const { return i[j]; }
///
friend ostream & operator<<(ostream & s, const INDEX_2 & i2);
};
@ -201,13 +213,12 @@ public:
///
INDEX_3 () { }
///
INDEX_3 (INDEX ai1, INDEX ai2, INDEX ai3)
{ i[0] = ai1; i[1] = ai2; i[2] = ai3; }
///
INDEX_3 (const INDEX_3 & in2)
{ i[0] = in2.i[0]; i[1] = in2.i[1]; i[2] = in2.i[2]; }
constexpr INDEX_3 (INDEX ai1, INDEX ai2, INDEX ai3)
: i{ai1, ai2, ai3} { }
///
constexpr INDEX_3 (const INDEX_3 & in2)
: i{in2.i[0], in2.i[1], in2.i[2]} { }
static INDEX_3 Sort (INDEX_3 i3)
{
@ -462,4 +473,37 @@ void MergeSort (int size, T * data, T * help);
}
namespace ngcore
{
// template <>
// constexpr inline netgen::INDEX_2 InvalidHash<netgen::INDEX_2> () { return netgen::INDEX_2{-1,-1}; }
template <>
struct CHT_trait<netgen::INDEX_2>
{
constexpr static inline netgen::INDEX_2 Invalid() { return { -1, -1 } ; }
constexpr static inline size_t HashValue (const netgen::INDEX_2 & hash, size_t mask)
{ return HashValue2(IVec<2,netgen::INDEX>(hash[0], hash[1]), mask); }
};
}
namespace netgen
{
/*
inline size_t HashValue2 (const netgen::INDEX_2 & ind, size_t mask)
{
return HashValue2(IVec<2,netgen::INDEX>(ind[0], ind[1]), mask);
}
*/
inline size_t HashValue2 (const netgen::INDEX_3 & ind, size_t mask)
{
return HashValue2(IVec<3,netgen::INDEX>(ind[0], ind[1], ind[2]), mask);
}
}
#endif

View File

@ -12,8 +12,6 @@
namespace netgen
{
using ngcore::INT;
constexpr static double EPSILON=0.000000001;
void ComputeWeight( Spline & s, Point<2> p )
@ -670,7 +668,7 @@ IntersectionType Intersect( Spline p, Spline s, double &alpha, double &beta)
if(have_intersection)
{
for(auto i : IntRange(10))
for([[maybe_unused]] auto i : IntRange(10))
NewtonIntersect(p, s, alpha, beta);
return ClassifyNonOverlappingIntersection( alpha, beta );
}
@ -1733,7 +1731,7 @@ Solid2d ClipSolids ( Solid2d && s1, Solid2d && s2, char op)
res.polys.Append(std::move(res_polys));
return std::move(res);
return res;
}
Vertex* Loop :: getNonIntersectionVertex()
@ -2037,13 +2035,13 @@ shared_ptr<netgen::SplineGeometry2d> CSG2d :: GenerateSplineGeometry()
}
netgen::BoxTree <2> solid_tree(box);
Array<INT<2>> loop_list;
Array<IVec<2>> loop_list;
for(auto i : Range(solids))
for(auto li : Range(solids[i].polys))
{
solid_tree.Insert(solids[i].polys[li].GetBoundingBox(), loop_list.Size());
loop_list.Append(INT<2>(i, li));
loop_list.Append(IVec<2>(i, li));
}
for(auto i1 : Range(solids))

View File

@ -7,7 +7,7 @@
namespace netgen
{
using namespace std;
using namespace ngcore;
using netgen::Point;
using netgen::Vec;
@ -602,7 +602,7 @@ struct Loop
size_t cnt = 0;
for(auto v : Vertices(ALL))
for([[maybe_unused]] auto v : Vertices(ALL))
cnt++;
return cnt;

View File

@ -5,7 +5,7 @@ namespace netgen
{
// extern DLL_HEADER MeshingParameters mparam;
extern void Optimize2d (Mesh & mesh, MeshingParameters & mp);
extern void Optimize2d (Mesh & mesh, MeshingParameters & mp, int faceindex=0);
@ -81,7 +81,7 @@ namespace netgen
for (int j = 1; j <= n && i < nel; j++)
{
double t = (j-0.5)*dt;
// double t = (j-0.5)*dt;
double fun = hi[j-1];
f = oldf + dt / fun;
@ -92,7 +92,7 @@ namespace netgen
i++;
}
oldf = f;
t += dt;
// t += dt;
}
points.Append (len);
}
@ -139,7 +139,9 @@ namespace netgen
mark = spline.GetPoint (edgelength);
{
PointIndex pi1 = -1, pi2 = -1;
PointIndex pi1{PointIndex::INVALID};
PointIndex pi2{PointIndex::INVALID};
Point3d mark3(mark(0), mark(1), 0);
Point3d oldmark3(oldmark(0), oldmark(1), 0);
@ -157,12 +159,12 @@ namespace netgen
if ( mesh[PointIndex(locsearch[k])].GetLayer() == spline.layer)
pi2 = locsearch[k];
if (pi1 == -1)
if (!pi1.IsValid())
{
pi1 = mesh.AddPoint(oldmark3, spline.layer);
searchtree.Insert (oldmark3, pi1);
}
if (pi2 == -1)
if (!pi2.IsValid())
{
pi2 = mesh.AddPoint(mark3, spline.layer);
searchtree.Insert (mark3, pi2);
@ -278,7 +280,7 @@ namespace netgen
mesh2d.AddLockedPoint(npi);
Element0d el(npi, npi);
el.name = point.name;
mesh2d.SetCD2Name(npi, point.name);
mesh2d.SetCD2Name(npi-IndexBASE<PointIndex>()+1, point.name);
mesh2d.pointelements.Append (el);
searchtree.Insert (newp, npi);
}
@ -292,20 +294,20 @@ namespace netgen
Point<2> hnewp = (j == 1) ? splines[i]->StartPI() : splines[i]->EndPI();
Point<3> newp(hnewp(0), hnewp(1), 0);
int layer = GetSpline(i).layer;
int npi = -1;
for (PointIndex pi = PointIndex::BASE;
pi < mesh2d.GetNP()+PointIndex::BASE; pi++)
PointIndex npi(PointIndex::INVALID);
for (PointIndex pi = IndexBASE<PointIndex>();
pi < mesh2d.GetNP()+IndexBASE<PointIndex>(); pi++)
if (Dist2 (mesh2d.Point(pi), newp) < 1e-12 * diam2 && mesh2d.Point(pi).GetLayer() == layer)
npi = pi;
if (npi == -1)
if (!npi.IsValid())
{
npi = mesh2d.AddPoint (newp, layer);
searchtree.Insert (newp, npi);
mesh2d.AddLockedPoint(npi);
Element0d el(npi, npi);
Element0d el(npi, npi-IndexBASE<PointIndex>()+1);
el.name = "";
mesh2d.SetCD2Name(npi, "");
mesh2d.SetCD2Name(npi-IndexBASE<PointIndex>()+1, "");
mesh2d.pointelements.Append (el);
}
}
@ -463,8 +465,8 @@ namespace netgen
PointIndex mpi(0);
Point<2> gp = geometry.GetPoint(i);
Point<3> gp3(gp(0), gp(1), 0);
for (PointIndex pi = PointIndex::BASE;
pi < mesh->GetNP()+PointIndex::BASE; pi++)
for (PointIndex pi = IndexBASE<PointIndex>();
pi < mesh->GetNP()+IndexBASE<PointIndex>(); pi++)
if (Dist2(gp3, (*mesh)[pi]) < mindist)
{
mpi = pi;
@ -511,7 +513,7 @@ namespace netgen
t_h.Stop();
int bnp = mesh->GetNP(); // boundary points
auto BndPntRange = mesh->Points().Range();
// auto BndPntRange = mesh->Points().Range();
int hquad = mp.quad;
@ -521,8 +523,8 @@ namespace netgen
{ // tensor product mesh
RegionTimer rt(t_tensor);
NgArray<PointIndex, PointIndex::BASE> nextpi(bnp);
NgArray<int, PointIndex::BASE> si1(bnp), si2(bnp);
Array<PointIndex, PointIndex> nextpi(bnp);
Array<int, PointIndex> si1(bnp), si2(bnp);
// PointIndex firstpi;
nextpi = -1;
@ -551,7 +553,8 @@ namespace netgen
PointIndex c1(0), c2, c3, c4; // 4 corner points
int nex = 1, ney = 1;
for (PointIndex pi = 1; pi <= si2.Size(); pi++)
// for (PointIndex pi = 1; pi <= si2.Size(); pi++)
for (PointIndex pi : si2.Range())
if (si2[pi] != -1)
{ c1 = pi; break; }
@ -564,13 +567,17 @@ namespace netgen
NgArray<PointIndex> pts ( (nex+1) * (ney+1) ); // x ... inner loop
pts = -1;
for (PointIndex pi = c1, i = 0; pi != c2; pi = nextpi[pi], i++)
int i = 0;
for (PointIndex pi = c1; pi != c2; pi = nextpi[pi], i++)
pts[i] = pi;
for (PointIndex pi = c2, i = 0; pi != c3; pi = nextpi[pi], i++)
i = 0;
for (PointIndex pi = c2; pi != c3; pi = nextpi[pi], i++)
pts[(nex+1)*i+nex] = pi;
for (PointIndex pi = c3, i = 0; pi != c4; pi = nextpi[pi], i++)
i = 0;
for (PointIndex pi = c3; pi != c4; pi = nextpi[pi], i++)
pts[(nex+1)*(ney+1)-i-1] = pi;
for (PointIndex pi = c4, i = 0; pi != c1; pi = nextpi[pi], i++)
i = 0;
for (PointIndex pi = c4; pi != c1; pi = nextpi[pi], i++)
pts[(nex+1)*(ney-i)] = pi;

View File

@ -1105,6 +1105,6 @@ namespace netgen
};
SplineGeoInit sginit;
static RegisterClassForArchive<SplineGeometry2d, SplineGeometry<2>, NetgenGeometry> regspg2;
static RegisterClassForArchive<SplineGeometry2d, tuple<SplineGeometry<2>, NetgenGeometry>> regspg2;
static RegisterClassForArchive<SplineSegExt, SplineSeg<2>> regssext;
}

View File

@ -401,10 +401,8 @@ NGCORE_API_EXPORT void ExportGeom2d(py::module &m)
{
MeshingParameters mp;
if(pars) mp = *pars;
{
py::gil_scoped_acquire aq;
CreateMPfromKwargs(mp, kwargs);
}
CreateMPfromKwargs(mp, kwargs);
py::gil_scoped_release gil_release;
auto mesh = make_shared<Mesh>();
mesh->SetGeometry(self);
SetGlobalMesh (mesh);
@ -414,7 +412,6 @@ NGCORE_API_EXPORT void ExportGeom2d(py::module &m)
throw Exception("Meshing failed!");
return mesh;
}, py::arg("mp") = nullopt,
py::call_guard<py::gil_scoped_release>(),
meshingparameter_description.c_str())
.def("_SetDomainTensorMeshing", &SplineGeometry2d::SetDomainTensorMeshing)
;
@ -427,7 +424,8 @@ NGCORE_API_EXPORT void ExportGeom2d(py::module &m)
.def(py::self-py::self)
.def(py::self*py::self)
.def(py::self+=py::self)
.def(py::self-=py::self)
// .def(py::self-=py::self) // false clange warning, see https://github.com/pybind/pybind11/issues/1893
.def("__isub__", [](Solid2d& lhs, const Solid2d& rhs) { return lhs -= rhs; }, py::is_operator())
.def(py::self*=py::self)
.def("Mat", &Solid2d::Mat)
@ -466,10 +464,8 @@ NGCORE_API_EXPORT void ExportGeom2d(py::module &m)
{
MeshingParameters mp;
if(pars) mp = *pars;
{
py::gil_scoped_acquire aq;
CreateMPfromKwargs(mp, kwargs);
}
py::gil_scoped_release gil_release;
auto mesh = make_shared<Mesh>();
auto geo = self.GenerateSplineGeometry();
mesh->SetGeometry(geo);
@ -480,7 +476,6 @@ NGCORE_API_EXPORT void ExportGeom2d(py::module &m)
throw Exception("Meshing failed!");
return mesh;
}, py::arg("mp") = nullopt,
py::call_guard<py::gil_scoped_release>(),
meshingparameter_description.c_str())
;

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